1. Tommaso Urli
  2. JSON++

Commits

Tommaso Urli  committed 86afe98

Added some tests, fixed memory issues.

  • Participants
  • Parent commits 227e67a
  • Branches default

Comments (0)

Files changed (6)

File json.l

View file
  • Ignore whitespace
 [-+]?[0-9]+             { yylval.int_v = atoi(yytext); return NUMBER_I; }
 [-+]?[0-9]*\.?[0-9]*    { yylval.float_v = atof(yytext); return NUMBER_F; }
 true|false              { yylval.bool_v = ( strcmp(yytext, "true") == 0 ? true : false); return BOOLEAN; }
-null                    { yylval.null_p = true; return NULL; }
+null                    { return NULL_T; }
 .                       {  }
 
 %%

File json.y

View file
  • Ignore whitespace
 
 %union
 {
+    // "Pure" types
     int int_v;
     float float_v;
     bool bool_v;
     bool null_p;
     char* string_v;
+    
+    // Pointers to more complex classes
     Object* object_p;
     Array* array_p;
     Value* value_p;
 %token DOUBLE_QUOTED_STRING SINGLE_QUOTED_STRING
 %token NUMBER_I NUMBER_F
 %token BOOLEAN
+%token NULL_T
 
 %type <object_p> object assignment_list
 %type <array_p> array list
 %start json
 
 %%
-    
-/** JSON grammar */
 
 // Entry point (every JSON file represents a value)
 json: value { parsd = $1; } ;
 // Object rule
 object: CURLY_BRACKET_L assignment_list CURLY_BRACKET_R { $$ = $2; } ;
 
+// Array rule
 array : SQUARE_BRACKET_L list SQUARE_BRACKET_R { $$ = $2; } ;
 
+// Values rule
 value : NUMBER_I { $$ = new Value($1); }
     | NUMBER_F { $$ = new Value($1); }
     | BOOLEAN { $$ = new Value($1); }
-    | string { $$ = new Value(std::string($1)); }
-    | object { $$ = new Value(*$1); }
-    | array { $$ = new Value(*$1); }
+    | NULL_T { $$ = new Value(); }
+    | string { $$ = new Value(std::string($1)); delete $1; }
+    | object { $$ = new Value(*$1); delete $1; }
+    | array { $$ = new Value(*$1); delete $1; }
     ;
-    
+
+// String rule
 string : DOUBLE_QUOTED_STRING {
         // Trim string
         std::string s($1);
         s = s.substr(1, s.length()-2);
-
         char* t = new char[s.length()+1];
         strcpy(t, s.c_str());
-
         $$ = t;
     } 
     | SINGLE_QUOTED_STRING {
         // Trim string
         std::string s($1);
         s = s.substr(1, s.length()-2);
-
         char* t = new char[s.length()+1];
         strcpy(t, s.c_str());
-
         $$ = t;
     };
 
+// Assignments rule
 assignment_list: /* empty */ { $$ = new Object(); } 
     | string COLON value {
         $$ = new Object();
-        $$->insert(std::make_pair($1, *$3));
+        $$->insert(std::make_pair(std::string($1), *$3));
+        delete $1;
+        delete $3;
     } 
-    | assignment_list COMMA string COLON value { $$->insert(std::make_pair($3, *$5)); }
+    | assignment_list COMMA string COLON value { 
+        $$->insert(std::make_pair(std::string($3), *$5));
+        delete $3;
+        delete $5;
+    }
     ;
-
+    
+// List rule
 list: /* empty */ { $$ = new Array(); }
     | value {
         $$ = new Array();
         $$->push_back(*$1);
+        delete $1;
     }
-    | list COMMA value { $$->push_back(*$3); }
+    | list COMMA value { 
+        $$->push_back(*$3); 
+        delete $3;
+    }
     ;
     
 %%
 
 int main(int argc, char **argv)
 {
-    FILE* in = fopen(argv[1], "r");
+    int status = 1;
     
-    load_file(in);
+    if (argc > 1)
+    {
     
-    int status = yyparse();
+        FILE* in = fopen(argv[1], "r");
     
-    // If parsing went wrong delete the object constructed so far
+        load_file(in);
+    
+        status = yyparse();
+    }
+    else
+        status = yyparse();
+    
     if (status)
         delete parsd;
     
     std::cerr << *parsd << std::endl;
+    
+    delete parsd;
 }
 
-
 void yyerror(const char *s)
 {
     fprintf(stderr, "error: %s\n", s);

File json_st.cc

View file
  • Ignore whitespace
 
 using namespace std;
 
-Value::Value() {}
+Value::Value() : type_t(NIL) {}
 
 Value::Value(const int& i) : int_v(i), type_t(INT) { }
 
 
 Object::Object() { }
 
-Object::~Object()
-{
-    for (auto p : _object)
-        delete p;
-}
+Object::~Object() { }
 
 Object::Object(const Object& o) : _object(o._object) { }
 
 
 Array::Array() { }
 
-Array::Array(const Array& o)
+Array::~Array() { }
+
+Array::Array(const Array& a)
 {
-    _array = o._array;
+    _array = a._array;
 }
 
-Value& Array::operator[] (const int i)
+Array& Array::operator=(const Array& a)
+{
+    _array = a._array;
+}
+
+
+Value& Array::operator[] (size_t i)
 {
     return _array[i];
 }
     _array.push_back(v);
 }
 
-Value& Value::operator=(const Value& e)
-{
-    
-    type_t = e.type();
-    
-    switch (type_t)
-    {
-        case INT:
-        int_v = e.int_v;
-        break;
-
-        case FLOAT:
-        float_v = e.float_v;
-        break;
-
-        case BOOL:
-        bool_v = e.bool_v;
-        break;
-
-        case STRING:
-        string_v = e.string_v;
-        break;
-
-        case OBJECT:
-        object_v = e.object_v;
-        break;
-
-        case ARRAY:
-        array_v = e.array_v;
-        break;                
-    }
-
-    return *this;
-}
-
-
 void indent(ostream& os)
 {
     for (unsigned int i  = 0; i < ind; i++)
         /** Base types */
         
         case INT:
-        os << v.int_v;
+        os << (int)v;
         break;
         
         case FLOAT:
-        os << v.float_v;
+        os << (float)v;
         break;
         
         case BOOL:
-        os << (v.bool_v ? "true" : "false");
+        os << ((bool)v ? "true" : "false");
+        break;
+        
+        case NIL:
+        os << "null";
         break;
         
         case STRING:
-        os << '"' << v.string_v << '"';                
+        os << '"' << (string)v << '"';                
         break;
         
         /** Compound types */
         
         case ARRAY:
-        os << v.array_v;                
+        os << (Array)v;                
         break;
         
         case OBJECT:
-        os << v.object_v;                
+        os << (Object)v;                
         break;
         
     }
     for (auto e = a.begin(); e != a.end();)
     {
         indent(os);
-        os << *e;
+        os << (*e);
         if (++e != a.end())
             os << ",";
         os << endl;

File json_st.hh

View file
  • Ignore whitespace
 /** Possible JSON type of a value (array, object, bool, ...). */
 enum ValueType
 {
-    INT,
-    FLOAT,
-    BOOL,
-    STRING,
-    OBJECT,
-    ARRAY
+    INT,        // JSON's int
+    FLOAT,      // JSON's float 3.14 12e-10
+    BOOL,       // JSON's boolean (true, false)
+    STRING,     // JSON's string " ... " or (not really JSON) ' ... '
+    OBJECT,     // JSON's object { ... }
+    ARRAY,      // JSON's array [ ... ]
+    NIL         // JSON's null
 };
 
 // Forward declaration
     /** Subscript operator, access an element by key.
         @param key key of the object to access
     */
-    Value* operator[] (const std::string& key) const;
+    Value& operator[] (const std::string& key);
 
     /** Retrieves the starting iterator (const).
         @remark mainly for printing
     */
-    std::map<std::string, Value*>::const_iterator begin() const;
+    std::map<std::string, Value>::const_iterator begin() const;
 
     /** Retrieves the ending iterator (const).
         @remark mainly for printing
     */
-    std::map<std::string, Value*>::const_iterator end() const;
+    std::map<std::string, Value>::const_iterator end() const;
     
     /** Retrieves the starting iterator */
-    std::map<std::string, Value*>::iterator begin();
+    std::map<std::string, Value>::iterator begin();
 
     /** Retrieves the ending iterator */
-    std::map<std::string, Value*>::iterator end();
+    std::map<std::string, Value>::iterator end();
     
     /** Inserts a field in the object.
         @param v pair <key, value> to insert
         @return an iterator to the inserted object
     */
-    std::pair<std::map<std::string, Value>::iterator, bool> insert(std::pair<std::string, Value*>* v);
+    std::pair<std::map<std::string, Value>::iterator, bool> insert(const std::pair<std::string, Value>& v);
 
     /** Size of the object. */
     size_t size() const;
 protected:
 
     /** Inner container. */
-    std::map<std::string, Value*> _object;
+    std::map<std::string, Value> _object;
 };
 
 /** A JSON array, i.e., an indexed container of elements. It contains
     /** Constructor. */
     Array();
     
+    /** Destructor. */
+    ~Array();
+    
     /** Copy constructor. 
         @param o the object to copy from
     */
     /** Subscript operator, access an element by index. 
         @param i index of the element to access
     */
-    Value* operator[] (size_t i);
-    
-    /** Subscript operator, access an element by index. Const.
-        @param i index of the element to access
-    */
-    const Value* operator[] (size_t i) const;
+    Value& operator[] (size_t i);
 
     /** Retrieves the starting iterator (const).
         @remark mainly for printing
     */
-    std::vector<Value*>::const_iterator begin() const;
+    std::vector<Value>::const_iterator begin() const;
 
     /** Retrieves the ending iterator (const).
         @remark mainly for printing
     */
-    std::vector<Value*>::const_iterator end() const;
+    std::vector<Value>::const_iterator end() const;
 
     /** Retrieves the starting iterator. */
-    std::vector<Value*>::iterator begin();
+    std::vector<Value>::iterator begin();
 
     /** Retrieves the ending iterator */
-    std::vector<Value*>::iterator end();
+    std::vector<Value>::iterator end();
 
     /** Inserts an element in the array.
         @param n (a pointer to) the value to add
     */
-    void push_back(Value* n);
+    void push_back(const Value& n);
     
     /** Size of the array. */
     size_t size() const;
 protected:
 
     /** Inner container. */
-    std::vector<Value*> _array;
+    std::vector<Value> _array;
 
 };
 
 {
 public:
     
-    /** Default constructor. */
+    /** Default constructor (type = NIL). */
     Value();
     
-    /** Constructor from pointer to int. */
-    Value(int* i);
+    /** Constructor from int. */
+    Value(const int& i);
     
-    /** Constructor from pointer to float. */
-    Value(float* f);
+    /** Constructor from float. */
+    Value(const float& f);
     
-    /** Constructor from pointer to bool. */
-    Value(bool* b);
+    /** Constructor from bool. */
+    Value(const bool& b);
     
-    /** Constructor from pointer to string. */
-    Value(std::string* s);
-        
-    Value(Object* o);
+    /** Constructor from pointer to char (C-string)  */
+    Value(const std::string& s);
     
-    Value(Array* o);
-
-    Value& operator=(const Value& e);
+    /** Constructor from pointer to Object */
+    Value(const Object& o);
+    
+    /** Constructor from pointer to Array */
+    Value(const Array& a);
     
     ValueType type() const
     {
         return type_t;
     }
-            
+    
+    /** Cast operator for float */
+    operator float() const { return float_v; }
+    
+    /** Cast operator for float */
+    operator int() const { return int_v; }
+    
+    /** Cast operator for float */
+    operator bool() const { return bool_v; }
+    
+    /** Cast operator for float */
+    operator std::string () const { return string_v; }
+    
+    /** Cast operator for Object */
+    operator Object () const { return object_v; }
+    
+    /** Cast operator for Object */
+    operator Array () const { return array_v; }
+
+
+protected:
+    
     float           float_v;
     int             int_v;
     bool            bool_v;
     std::string     string_v;
+    
     Object          object_v;
     Array           array_v;
+    
     ValueType       type_t;
 };
     
+/** Output operator for Values */
 std::ostream& operator<<(std::ostream&, const Value&);
 
+/** Output operator for Objects */
 std::ostream& operator<<(std::ostream&, const Object&);
 
+/** Output operator for Arrays */
 std::ostream& operator<<(std::ostream&, const Array&);
 
+/** Indentation counter */
 static unsigned int ind;
 
-static unsigned int count;
-
-static std::stack<Value> list_s;
-
-static std::stack<std::pair<std::string, Value> > assign_list_s;
-
+/** Print correct indentation before printing anything */
 static void indent(std::ostream& os = std::cout);
 
 #endif

File tests/comp.json

View file
  • Ignore whitespace
+{
+    "type": "and",
+    "postprocessors": [
+        {
+            "type": "hammersley",
+            "points": 16
+        },
+	{
+            "type": "rounding",
+            "round": {
+                "temperature": 0,
+                "neighbors-accepted": 0
+            }
+	} 
+    ],
+    "descendants": [
+        {
+            "type": "directory",
+            "name": "instance",
+            "path": "../instances/comp",
+            "match": ".*\\.ectt"
+        },
+        {
+            "type": "discrete",
+            "name": "init-free-variables",
+            "values": [ 2 ]
+        },
+        {
+            "type": "discrete",
+            "name": "max-free-variables",
+            "values": [ 0.05 ]
+        },
+        {
+            "type": "discrete",
+            "name": "max-idle-iterations",
+            "values": [ 200 ] 
+        },
+        {
+            "type": "discrete",
+            "name": "ms-per-variable",
+            "values": [ 10 ]
+        },
+        {
+            "type": "discrete",
+            "name": "random-relaxation",
+            "values": [ 0.05 ]
+        },
+        {
+            "type": "discrete",
+            "name": "min-temperature",
+            "values": [ 0.04 ]
+        },
+        {
+            "type": "discrete",
+            "name": "delta-probability",
+            "values": [ 0.05 ]
+        },
+        {
+            "type": "discrete",
+            "name": "cooling-rate",
+            "values": [ 0.98 ]
+        },
+        {
+            "type": "continuous",
+            "values": { "min": 1, "max": 50 },
+            "name": "neighbors-accepted"
+        },
+        {
+            "type": "continuous",
+            "values": { "min": 0.05, "max": 100 },
+            "name": "temperature"
+        },
+	{
+            "type": "discrete",
+            "name": "random-branching",
+            "values": [ "random" ]
+        },
+        {
+            "type": "discrete",
+            "name": "time",
+            "values": [ 400000 ]
+        },
+        {
+            "type": "discrete",
+            "name": "model",
+            "values": [ "experiments" ]
+        }
+    ]
+}

File tests/st_lopes.json

View file
  • Ignore whitespace
+{
+    "postprocessors": [
+        {
+            "points": 20, 
+            "type": "hammersley"
+        }, 
+        {
+            "expression": "instance_path.value+'/'+instance.value", 
+            "type": "expression", 
+            "result": "main::instance", 
+            "match": "^instance(_path)?$"
+        }, 
+        {
+            "type": "ignore", 
+            "match": "^instance(_path)?$"
+        }, 
+        {
+            "expression": "10.0**st.value", 
+            "type": "expression", 
+            "result": "BSA::start_temperature", 
+            "match": "st"
+        }, 
+        {
+            "expression": "10.0**na_ns.value", 
+            "type": "expression", 
+            "result": "BSA::neighbors_accepted_ratio", 
+            "match": "na_ns"
+        }, 
+        {
+            "expression": "BSA::start_temperature.value*5", 
+            "type": "expression", 
+            "result": "BSA::temperature_range", 
+            "match": "BSA::start_temperature"
+        }, 
+        {
+            "expression": "-log(tr.value)/log(BSA::cooling_rate.value)", 
+            "type": "expression", 
+            "result": "nt", 
+            "match": "tr|BSA::cooling_rate"
+        }, 
+        {
+            "expression": "int(ceil(BSA::max_iterations.value/nt.value))", 
+            "type": "expression", 
+            "result": "BSA::neighbors_sampled", 
+            "match": "BSA::max_iterations|nt"
+        },
+        {
+            "type": "rounding", 
+            "round": {
+                "BSA::start_temperature": 2
+            }
+        }, 
+        {
+            "type": "ignore", 
+            "match": "nt|na_ns|st"
+        }
+    ], 
+    "type": "and", 
+    "descendants": [
+        {
+            "values": [ 100 ], 
+            "type": "discrete", 
+            "name": "main::hard_weight"
+        }, 
+        {
+            "values": [ -1.8 ], 
+            "type": "discrete", 
+            "name": "na_ns"
+        }, 
+        {
+            "values": { "max": 2.0, "min": 0.25 }, 
+            "type": "continuous", 
+            "name": "st"
+        }, 
+        {
+            "values": [ "BSA" ], 
+            "type": "discrete", 
+            "name": "main::solution_method"
+        }, 
+        {
+            "values": [ 0.45 ], 
+            "type": "discrete", 
+            "name": "main::swap_rate"
+        }, 
+        {
+            "values": [ 0.99 ], 
+            "type": "discrete", 
+            "name": "BSA::cooling_rate"
+        }, 
+        {
+            "values": [ 10000000 ], 
+            "type": "discrete", 
+            "name": "BHC::max_idle_iterations"
+        }, 
+        {
+            "values": [ 120000000 ], 
+            "type": "discrete", 
+            "name": "BSA::max_iterations"
+        },
+        {
+            "type": "file",
+            "name": "instance",
+            "path": "selected_lopes.txt",
+            "match": ".*"
+        },
+        {
+            "type": "discrete",
+            "name": "instance_path",
+            "values": [ "../instances/lopes" ]
+        }
+    ]
+}