Author: dragonking
Date: Wed Apr  9 20:36:16 2008
New Revision: 25713

URL: http://svn.gna.org/viewcvs/wesnoth?rev=25713&view=rev
Log:
Add support for a map to the formula system
Syntax:
{ 'elvish fighter' -> 40, 'elvish archer' -> 30 }
Changed comments in the formula system from
{ text of a comment }  to  # text of a comment #

Modified:
    trunk/src/formula.cpp
    trunk/src/formula_tokenizer.cpp
    trunk/src/formula_tokenizer.hpp
    trunk/src/variant.cpp
    trunk/src/variant.hpp

Modified: trunk/src/formula.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula.cpp?rev=25713&r1=25712&r2=25713&view=diff
==============================================================================
--- trunk/src/formula.cpp (original)
+++ trunk/src/formula.cpp Wed Apr  9 20:36:16 2008
@@ -100,6 +100,27 @@
                res.reserve(items_.size());
                for(std::vector<expression_ptr>::const_iterator i = 
items_.begin(); i != items_.end(); ++i) {
                        res.push_back((*i)->evaluate(variables));
+               }
+
+               return variant(&res);
+       }
+
+       std::vector<expression_ptr> items_;
+};
+
+class map_expression : public formula_expression {
+public:
+       explicit map_expression(const std::vector<expression_ptr>& items)
+          : items_(items)
+       {}
+
+private:
+       variant execute(const formula_callable& variables) const {
+               std::map<variant,variant> res;
+               for(std::vector<expression_ptr>::const_iterator i = 
items_.begin(); ( i != items_.end() ) && ( i+1 != items_.end() ) ; i+=2) {
+                               variant key = (*i)->evaluate(variables);
+                               variant value = (*(i+1))->evaluate(variables);
+                               res[ key ] = value;
                }
 
                return variant(&res);
@@ -475,6 +496,41 @@
                } else if(i1->type == TOKEN_RPARENS || i1->type == 
TOKEN_RSQUARE) {
                        --parens;
                } else if(i1->type == TOKEN_COMMA && !parens) {
+                       res->push_back(parse_expression(beg,i1, symbols));
+                       beg = i1+1;
+               }
+
+               ++i1;
+       }
+
+       if(beg != i1) {
+               res->push_back(parse_expression(beg,i1, symbols));
+       }
+}
+
+void parse_set_args(const token* i1, const token* i2,
+                std::vector<expression_ptr>* res,
+                               function_symbol_table* symbols)
+{
+       int parens = 0;
+       bool check_pointer = false;
+       const token* beg = i1;
+       while(i1 != i2) {
+               if(i1->type == TOKEN_LPARENS || i1->type == TOKEN_LSQUARE) {
+                       ++parens;
+               } else if(i1->type == TOKEN_RPARENS || i1->type == 
TOKEN_RSQUARE) {
+                       --parens;
+               } else if( i1->type == TOKEN_POINTER && !parens ) {
+                       if (!check_pointer) {
+                               check_pointer = true;
+                               res->push_back(parse_expression(beg,i1, 
symbols));
+                               beg = i1+1;
+                       } else {
+                               std::cerr << "Too many '->' operators\n";
+                               throw formula_error();
+                       }
+               } else if( i1->type == TOKEN_COMMA && !parens ) {
+                       check_pointer = false;
                        res->push_back(parse_expression(beg,i1, symbols));
                        beg = i1+1;
                }
@@ -598,9 +654,15 @@
                if(i1->type == TOKEN_LPARENS && (i2-1)->type == TOKEN_RPARENS) {
                        return parse_expression(i1+1,i2-1,symbols);
                } else if(i1->type == TOKEN_LSQUARE && (i2-1)->type == 
TOKEN_RSQUARE) {
+                               //create a list
                                std::vector<expression_ptr> args;
                                parse_args(i1+1,i2-1,&args,symbols);
                                return expression_ptr(new 
list_expression(args));
+               } else if(i1->type == TOKEN_LBRACKET && (i2-1)->type == 
TOKEN_RBRACKET) {
+                               //create a map TODO: add support for a set
+                               std::vector<expression_ptr> args;
+                               parse_set_args(i1+1,i2-1,&args,symbols);
+                               return expression_ptr(new map_expression(args));
                } else if(i2 - i1 == 1) {
                        if(i1->type == TOKEN_KEYWORD) {
                                if(std::string(i1->begin,i1->end) == 
"functions") {

Modified: trunk/src/formula_tokenizer.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula_tokenizer.cpp?rev=25713&r1=25712&r2=25713&view=diff
==============================================================================
--- trunk/src/formula_tokenizer.cpp (original)
+++ trunk/src/formula_tokenizer.cpp Wed Apr  9 20:36:16 2008
@@ -31,7 +31,7 @@
 };
 
 //create the array with list of possible tokens
-token_type token_types[] = { { 
regex("^(not\\b|and\\b|or\\b|where\\b|d(?=[^a-zA-Z])|\\*|\\+|\\-|\\^|%|/|<=|>=|<|>|!=|=|\\.)"),
 TOKEN_OPERATOR },
+token_type token_types[] = { { 
regex("^(not\\b|and\\b|or\\b|where\\b|d(?=[^a-zA-Z])|\\*|\\+|-(?=[^>])|\\^|%|/|<=|>=|<|>|!=|=|\\.)"),
 TOKEN_OPERATOR },
                                { regex("^functions\\b"),  TOKEN_KEYWORD },
                                { regex("^def\\b"),        TOKEN_KEYWORD },
                                { regex("^'[^']*'"),       TOKEN_STRING_LITERAL 
},
@@ -41,10 +41,13 @@
                                { regex("^\\)"),           TOKEN_RPARENS },
                                { regex("^\\["),           TOKEN_LSQUARE },
                                { regex("^\\]"),           TOKEN_RSQUARE },
-                               { regex("^\\{.*?\\}"),     TOKEN_COMMENT },
+                               { regex("^\\{"),           TOKEN_LBRACKET },
+                               { regex("^\\}"),           TOKEN_RBRACKET },
+                               { regex("^#.*?#"),         TOKEN_COMMENT },
                                { regex("^,"),             TOKEN_COMMA },
                                { regex("^;"),             TOKEN_SEMICOLON },
-                               { regex("^\\s+"),          TOKEN_WHITESPACE }
+                               { regex("^\\s+"),          TOKEN_WHITESPACE },
+                               { regex("^->"),          TOKEN_POINTER }
 };
 
 }
@@ -57,7 +60,7 @@
                        res.type = t.type;
                        res.begin = i1;
                        i1 = res.end = i1 + match.length();
-
+                       
                        return res;
                }
        }

Modified: trunk/src/formula_tokenizer.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/formula_tokenizer.hpp?rev=25713&r1=25712&r2=25713&view=diff
==============================================================================
--- trunk/src/formula_tokenizer.hpp (original)
+++ trunk/src/formula_tokenizer.hpp Wed Apr  9 20:36:16 2008
@@ -25,9 +25,10 @@
                          TOKEN_IDENTIFIER, TOKEN_INTEGER,
                   TOKEN_LPARENS, TOKEN_RPARENS,
                                  TOKEN_LSQUARE, TOKEN_RSQUARE, 
+                                 TOKEN_LBRACKET, TOKEN_RBRACKET,
                                  TOKEN_COMMA, TOKEN_SEMICOLON, 
                                  TOKEN_WHITESPACE, TOKEN_KEYWORD,
-                                 TOKEN_COMMENT };
+                                 TOKEN_COMMENT, TOKEN_POINTER  };
 
 struct token {
        TOKEN_TYPE type;

Modified: trunk/src/variant.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/variant.cpp?rev=25713&r1=25712&r2=25713&view=diff
==============================================================================
--- trunk/src/variant.cpp (original)
+++ trunk/src/variant.cpp Wed Apr  9 20:36:16 2008
@@ -28,6 +28,8 @@
                return "list";
        case variant::TYPE_STRING: 
                return "string";
+       case variant::TYPE_MAP: 
+               return "map";
        default:
                assert(false);
                return "invalid";
@@ -80,6 +82,13 @@
        int refcount;
 };
 
+struct variant_map {
+       variant_map() : refcount(0)
+       {}
+       std::map<variant,variant> elements;
+       int refcount;
+};
+
 void variant::increment_refcount()
 {
        switch(type_) {
@@ -88,6 +97,9 @@
                break;
        case TYPE_STRING:
                ++string_->refcount;
+               break;
+       case TYPE_MAP:
+               ++map_->refcount;
                break;
        case TYPE_CALLABLE:
                intrusive_ptr_add_ref(callable_);
@@ -111,6 +123,11 @@
        case TYPE_STRING:
                if(--string_->refcount == 0) {
                        delete string_;
+               }
+               break;
+       case TYPE_MAP:
+               if(--map_->refcount == 0) {
+                       delete map_;
                }
                break;
        case TYPE_CALLABLE:
@@ -154,6 +171,15 @@
        increment_refcount();
 }
 
+variant::variant(std::map<variant,variant>* map)
+    : type_(TYPE_MAP)
+{
+       assert(map);
+       map_ = new variant_map;
+       map_->elements.swap(*map);
+       increment_refcount();
+}
+
 variant::variant(const variant& v)
 {
        memcpy(this, &v, sizeof(v));
@@ -191,15 +217,44 @@
        return list_->elements[n];
 }
 
+const variant& variant::operator[](const variant v) const
+{
+       if(type_ == TYPE_CALLABLE) {
+               assert(v.as_int() == 0);
+               return *this;
+       }
+
+       if(type_ == TYPE_MAP) {
+               assert(map_);
+               std::map<variant,variant>::const_iterator i = 
map_->elements.find(v);
+               if (i == map_->elements.end())
+               {
+                       static variant null_variant;
+                       return null_variant;
+               }
+               return i->second;
+       } else if(type_ == TYPE_LIST) {
+               return operator[](v.as_int());
+       } else {
+               throw type_error(formatter() << "type error: " << " expected a 
list or a map but found " << variant_type_to_string(type_) << " (" << 
to_debug_string() << ")");
+       }       
+}
+
 size_t variant::num_elements() const
 {
        if(type_ == TYPE_CALLABLE) {
                return 1;
        }
 
-       must_be(TYPE_LIST);
-       assert(list_);
-       return list_->elements.size();
+       if (type_ == TYPE_LIST) {
+               assert(list_);
+               return list_->elements.size();
+       } else if (type_ == TYPE_MAP) {
+               assert(map_);
+               return map_->elements.size();
+       } else {
+               throw type_error(formatter() << "type error: " << " expected a 
list or a map but found " << variant_type_to_string(type_) << " (" << 
to_debug_string() << ")");
+       }
 }
 
 variant variant::get_member(const std::string& str) const
@@ -226,6 +281,8 @@
                return callable_ != NULL;
        case TYPE_LIST:
                return !list_->elements.empty();
+       case TYPE_MAP:
+               return !map_->elements.empty();
        case TYPE_STRING:
                return !string_->str.empty();
        default:
@@ -260,6 +317,17 @@
                        return variant(&res);
                }
        }
+       if(type_ == TYPE_MAP) {
+               if(v.type_ == TYPE_MAP) {
+                       std::map<variant,variant> res(map_->elements);
+
+                       for(std::map<variant,variant>::const_iterator i = 
v.map_->elements.begin(); i != v.map_->elements.end(); ++i) {
+                               res[i->first] = i->second;
+                       }
+
+                       return variant(&res);
+               }
+       }
 
        return variant(as_int() + v.as_int());
 }
@@ -339,6 +407,10 @@
                return true;
        }
 
+       case TYPE_MAP: {
+               return map_->elements == v.map_->elements;
+       }
+
        case TYPE_CALLABLE: {
                return callable_->equals(v.callable_);
        }
@@ -356,15 +428,7 @@
 bool variant::operator<=(const variant& v) const
 {
        if(type_ != v.type_) {
-               if(type_ == TYPE_NULL) {
-                       return variant(0) <= v;
-               }
-
-               if(v.type_ == TYPE_NULL) {
-                       return *this <= variant(0);
-               }
-
-               return false;
+               return type_ < v.type_;
        }
 
        switch(type_) {
@@ -390,6 +454,10 @@
                }
 
                return num_elements() <= v.num_elements();
+       }
+
+       case TYPE_MAP: {
+               return map_->elements <= v.map_->elements;
        }
 
        case TYPE_CALLABLE: {
@@ -448,6 +516,21 @@
                str += "]";
                break;
        }
+       case TYPE_MAP: {
+               str += "{";
+               bool first_time = true;
+               for(std::map<variant,variant>::const_iterator 
i=map_->elements.begin(); i != map_->elements.end(); ++i) {
+                       if(!first_time) {
+                               str += ",";
+                       }
+                       first_time = false;
+                       i->first.serialize_to_string(str);
+                       str += "->";
+                       i->second.serialize_to_string(str);
+               }
+               str += "}";
+               break;
+       }
        case TYPE_STRING:
                str += "'";
                str += string_->str;
@@ -475,6 +558,9 @@
                break;
        case TYPE_STRING:
                return string_->refcount;
+               break;
+       case TYPE_MAP:
+               return map_->refcount;
                break;
        case TYPE_CALLABLE:
                return callable_->refcount();
@@ -504,6 +590,18 @@
                        res += var.string_cast();
                }
 
+               return res;
+       }
+       case TYPE_MAP: {
+               std::string res = "";
+               for(std::map<variant,variant>::const_iterator 
i=map_->elements.begin(); i != map_->elements.end(); ++i) {
+                       if(!res.empty()) {
+                               res += ",";
+                       }
+                       res += i->first.string_cast();
+                       res += "->";
+                       res += i->second.string_cast();
+               }
                return res;
        }
 
@@ -568,6 +666,21 @@
                s << "}";
                break;
        }
+       case TYPE_MAP: {
+               s << "{";
+               bool first_time = true;
+               for(std::map<variant,variant>::const_iterator 
i=map_->elements.begin(); i != map_->elements.end(); ++i) {
+                       if(!first_time) {
+                               s << ",";
+                       }
+                       first_time = false;
+                       s << i->first.to_debug_string(seen);
+                       s << "->";
+                       s << i->second.to_debug_string(seen);
+               }
+               s << "}";
+               break;
+       }
        case TYPE_STRING: {
                s << "'" << string_->str << "'";
                break;

Modified: trunk/src/variant.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/variant.hpp?rev=25713&r1=25712&r2=25713&view=diff
==============================================================================
--- trunk/src/variant.hpp (original)
+++ trunk/src/variant.hpp Wed Apr  9 20:36:16 2008
@@ -25,6 +25,7 @@
 
 struct variant_list;
 struct variant_string;
+struct variant_map;
 
 struct type_error {
        explicit type_error(const std::string& str);
@@ -38,12 +39,14 @@
        explicit variant(const game_logic::formula_callable* callable);
        explicit variant(std::vector<variant>* array);
        explicit variant(const std::string& str);
+       explicit variant(std::map<variant,variant>* map);
        ~variant();
 
        variant(const variant& v);
        const variant& operator=(const variant& v);
 
        const variant& operator[](size_t n) const;
+       const variant& operator[](const variant v) const;
        size_t num_elements() const;
 
        variant get_member(const std::string& str) const;
@@ -51,6 +54,7 @@
        bool is_string() const { return type_ == TYPE_STRING; }
        bool is_null() const { return type_ == TYPE_NULL; }
        bool is_int() const { return type_ == TYPE_INT; }
+       bool is_map() const { return type_ == TYPE_MAP; }
        int as_int() const { if(type_ == TYPE_NULL) { return 0; } 
must_be(TYPE_INT); return int_value_; }
        bool as_bool() const;
 
@@ -106,7 +110,7 @@
        std::string string_cast() const;
 
        std::string to_debug_string(std::vector<const 
game_logic::formula_callable*>* seen=NULL) const;
-       enum TYPE { TYPE_NULL, TYPE_INT, TYPE_CALLABLE, TYPE_LIST, TYPE_STRING 
};
+       enum TYPE { TYPE_NULL, TYPE_INT, TYPE_CALLABLE, TYPE_LIST, TYPE_STRING, 
TYPE_MAP };
 private:
        void must_be(TYPE t) const;
        TYPE type_;
@@ -116,6 +120,7 @@
                game_logic::formula_callable* mutable_callable_;
                variant_list* list_;
                variant_string* string_;
+               variant_map* map_;
        };
 
        void increment_refcount();


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to