Browse Source

Use shared_ptr<const ObjectBase> in many places.

ObjPtr
Michael Uleysky 8 years ago
parent
commit
821aace1eb
  1. 65
      include/common.h
  2. 46
      include/object.h
  3. 34
      src/deptree.cpp
  4. 14
      src/object.cpp
  5. 8
      src/parser/grammatical.y

65
include/common.h

@ -154,6 +154,8 @@ class OBTypeM<Func>
}; };
typedef std::shared_ptr<const ObjectBase> ObjPtr;
// Error class // Error class
class EXPORT ObjectError: public ObjectBase class EXPORT ObjectError: public ObjectBase
{ {
@ -215,7 +217,6 @@ public:
// Own functions // Own functions
T Value() const {return val;} T Value() const {return val;}
void SetValue(T s) {val=s;}
}; };
// Simple objects // Simple objects
@ -236,23 +237,22 @@ class EXPORT ObjectPair: public ObjectBase
{ {
private: private:
std::string name; std::string name;
std::shared_ptr<const ObjectBase> val; ObjPtr val;
ObjectPair(const ObjectPair* p):name(p->name),val(p->val) {}
public: public:
ObjectPair() {} ObjectPair() = delete;
ObjectPair(const std::string& n, const ObjectBase* v):name(n) {val.reset(v);} ObjectPair(const std::string& n, const ObjectBase* v):name(n) {val.reset(v);}
ObjectPair(std::string&& n, const ObjectBase* v):name(std::move(n)) {val.reset(v);}
ObjectPair(const std::string* n, const ObjectBase* v):name(*n) {val.reset(v);} ObjectPair(const std::string* n, const ObjectBase* v):name(*n) {val.reset(v);}
~ObjectPair() {} ObjectPair(const std::string& n, const ObjPtr& v):name(n),val(v) {}
// Pure virtual overrides // Pure virtual overrides
const ObjectBase* Copy() const override const ObjectBase* Copy() const override
{ {
auto ret=new ObjectPair; return new ObjectPair(this);
ret->name=name; ret->val=val;
return ret;
} }
bool Print() const override bool Print() const override
{ {
if(!Exist()) return false;
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl; COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
COUT(NORMAL)<<"Name is: "<<Name()<<std::endl; COUT(NORMAL)<<"Name is: "<<Name()<<std::endl;
COUT(NORMAL)<<"Value type: "<<val->Type()<<std::endl; COUT(NORMAL)<<"Value type: "<<val->Type()<<std::endl;
@ -264,20 +264,12 @@ public:
std::string Dump() const override { return Name()+"="+val->Dump(); } std::string Dump() const override { return Name()+"="+val->Dump(); }
// Own functions // Own functions
bool Exist() const {return nullptr!=val.get();}
const ObjectBase* Get(const std::string& gname) const const ObjectBase* Get(const std::string& gname) const
{ {
if(gname==name) return val->Copy(); if(gname==name) return val->Copy();
else return new ObjectError("ObjectPair Get","pair has name "+name+" not "+gname); else return new ObjectError("ObjectPair Get","pair has name "+name+" not "+gname);
} }
// This function is same as Get but return pointer on constant object
const ObjectBase* Find(const std::string& gname) const
{
if(gname==name) return val.get();
else return nullptr;
}
std::string Name() const {return name;} std::string Name() const {return name;}
void SetPair(const std::string& n, const ObjectBase* v) {if(!Exist()) {name=n; val.reset(v);}}
const ObjectBase* Value() const {return val.get();} const ObjectBase* Value() const {return val.get();}
}; };
@ -285,24 +277,18 @@ public:
class EXPORT ObjectList: public ObjectBase class EXPORT ObjectList: public ObjectBase
{ {
public: public:
typedef std::deque<const ObjectBase*> ListValues; typedef std::deque<ObjPtr> ListValues;
private: private:
std::shared_ptr<ListValues> vals; std::shared_ptr<ListValues> vals;
ObjectList(const ObjectList* l):vals(l->vals) {}
public: public:
ObjectList() {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;});} ObjectList(): vals(std::make_shared<ListValues>()) {};
ObjectList(const ObjectBase* o) {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;}); PushBack(o);} ObjectList(const ObjectBase* o): vals(std::make_shared<ListValues>()) {vals->push_back(ObjPtr(o));}
~ObjectList() {}
// Pure virtual overrides // Pure virtual overrides
const ObjectBase* Copy() const override const ObjectBase* Copy() const override {return new ObjectList(this);}
{
auto ret=new ObjectList;
ret->vals=vals;
return ret;
}
bool Print() const override bool Print() const override
{ {
if(!Exist()) return false;
COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl; COUT(NORMAL)<<std::endl<<"Object type: "<<Type()<<std::endl;
COUT(NORMAL)<<"Number of elements: "<<Size()<<std::endl; COUT(NORMAL)<<"Number of elements: "<<Size()<<std::endl;
return true; return true;
@ -319,31 +305,26 @@ public:
} }
// Own functions // Own functions
const ObjectBase* At(ListValues::size_type i) const {return (*vals)[i];} const ObjectBase* At(ListValues::size_type i) const {return (*vals)[i].get();}
bool Exist() const {return 0!=vals->size();}
const ObjectBase* Get(const std::string& gname) const const ObjectBase* Get(const std::string& gname) const
{
const ObjectBase* p=Find(gname);
return (nullptr==p)?new ObjectError("ObjectList Get","name "+gname+" not found in list"):p->Copy();
}
// This function is same as Get but return pointer on constant object
const ObjectBase* Find(const std::string& gname) const
{ {
const ObjectBase* p; const ObjectBase* p;
for(auto& i: *vals) for(const auto& i: *vals)
{ {
p=nullptr; p=nullptr;
OBType<ObjectPair> pair(i); OBType<ObjectPair> pair(i.get());
OBType<ObjectList> list(i); OBType<ObjectList> list(i.get());
if(pair) p=pair->Find(gname); if(pair) p=pair->Get(gname);
else if(list) p=list->Find(gname); else if(list) p=list->Get(gname);
if(nullptr!=p) return p; if(nullptr!=p) return p;
} }
return nullptr; return nullptr;
} }
ListValues::size_type Size() const {return vals->size();} ListValues::size_type Size() const {return vals->size();}
ObjectList* PushBack(const ObjectBase* p) {vals->push_back(p); return this;} ObjectList* PushBack(const ObjectBase* p) {vals->push_back(ObjPtr(p)); return this;}
ObjectList* PushFront(const ObjectBase* p) {vals->push_front(p); return this;} ObjectList* PushBack(const ObjPtr& p) {vals->push_back(p); return this;}
ObjectList* PushFront(const ObjectBase* p) {vals->push_front(ObjPtr(p)); return this;}
ObjectList* PushFront(const ObjPtr& p) {vals->push_front(p); return this;}
}; };
typedef const ObjectBase* (*Func)(const ObjectList*); typedef const ObjectBase* (*Func)(const ObjectList*);

46
include/object.h

@ -40,35 +40,24 @@ public:
if(TYPE_VARIABLE==t || TYPE_FUNCTION==t || TYPE_MKPAIR==t) name=s; if(TYPE_VARIABLE==t || TYPE_FUNCTION==t || TYPE_MKPAIR==t) name=s;
else type=TYPE_EMPTY; else type=TYPE_EMPTY;
} }
StackElem(ObjectBase* o, const struct grammatic_location& loc):type(TYPE_OBJECT),obj(o),location(loc) {} StackElem(const ObjPtr& o, const struct grammatic_location& loc):type(TYPE_OBJECT),obj(o),location(loc) {}
~StackElem() {if(TYPE_OBJECT==type) delete obj;} StackElem(ObjPtr&& o, const struct grammatic_location& loc):type(TYPE_OBJECT),obj(std::move(o)),location(loc) {}
StackElem(StackElem&& s):type(s.type),name(s.name),location(s.location) StackElem(StackElem&& s) = default;
{
if(TYPE_OBJECT==type)
{
// Simple copy of pointer
obj=s.obj;
// Prevent destruction of ObjectBase in StackElem destructor
s.type=TYPE_EMPTY;
}
}
const ObjectBase* Object() const {return isObject()?obj:nullptr;} const ObjectBase* Object() const {return isObject()?obj.get():nullptr;}
// Detach object const ObjPtr& PickObject() const {return obj;}
const ObjectBase* PickObject() bool ReplaceByObject(const ObjPtr& ob)
{
if(isObject())
{ {
type=TYPE_EMPTY; if(isObject()) return false;
return obj; type=TYPE_OBJECT;
} obj=ob;
else return nullptr; return true;
} }
bool ReplaceByObject(const ObjectBase* ob) bool ReplaceByObject(ObjPtr&& ob)
{ {
if(isObject()) {delete ob; return false;} if(isObject()) return false;
type=TYPE_OBJECT; type=TYPE_OBJECT;
obj=ob; obj=std::move(ob);
return true; return true;
} }
std::string Name() const {return (isVar() || isFunc() || isMKPair())?name:std::string();} std::string Name() const {return (isVar() || isFunc() || isMKPair())?name:std::string();}
@ -83,7 +72,7 @@ public:
private: private:
Type type; Type type;
const ObjectBase* obj; ObjPtr obj;
std::string name; std::string name;
struct grammatic_location location; struct grammatic_location location;
}; };
@ -92,7 +81,7 @@ typedef std::list<StackElem> ExecExpr;
inline StackElem SEBList(const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_BEGINLIST,loc);} inline StackElem SEBList(const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_BEGINLIST,loc);}
inline StackElem SEEList(const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_ENDLIST,loc);} inline StackElem SEEList(const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_ENDLIST,loc);}
inline StackElem SEObj(ObjectBase* o, const struct grammatic_location& loc) {return StackElem(o,loc);} inline StackElem SEObj(const ObjectBase* o, const struct grammatic_location& loc) {return StackElem(ObjPtr(o),loc);}
inline StackElem SEMKPair(const std::string& s, const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_MKPAIR,loc,s);} inline StackElem SEMKPair(const std::string& s, const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_MKPAIR,loc,s);}
inline StackElem SEVar(const std::string& s, const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_VARIABLE,loc,s);} inline StackElem SEVar(const std::string& s, const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_VARIABLE,loc,s);}
inline StackElem SEFunc(const std::string& s, const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_FUNCTION,loc,s);} inline StackElem SEFunc(const std::string& s, const struct grammatic_location& loc) {return StackElem(StackElem::TYPE_FUNCTION,loc,s);}
@ -104,8 +93,7 @@ std::string DumpExprE(const ExecExpr& exp);
std::string DumpExpr(const ExecExpr& exp); std::string DumpExpr(const ExecExpr& exp);
UsedType UsedVars(const ExecExpr& exp); UsedType UsedVars(const ExecExpr& exp);
UsedType UsedFuncs(const ExecExpr& exp); UsedType UsedFuncs(const ExecExpr& exp);
const ObjectBase* Evaluate(ExecExpr& exp, bool* err); ObjPtr Evaluate(ExecExpr& exp, bool* err);
//inline void ReplaceVar(ExecExpr& exp, const std::string& var, ObjectBase* ob) {for(auto& se: exp) if(se.isVar() && var==se.Name()) se.ReplaceByObject(ob);} void ReplaceVar(ExecExpr& exp, const std::string& var, const ObjPtr& ob);
void ReplaceVar(ExecExpr& exp, const std::string& var, const ObjectBase* ob);// {for(auto& se: exp) if(se.isVar() && var==se.Name()) se.ReplaceByObject(ob);}
#endif #endif

34
src/deptree.cpp

@ -299,8 +299,8 @@ void* TreeEvaluateM(void* arg)
if(DepTree::SAVE==leaf->type) if(DepTree::SAVE==leaf->type)
{ {
err=false; err=false;
auto olp=Evaluate(leaf->exe,&err);
std::unique_ptr<const ObjectList> ol(dynamic_cast<const ObjectList*>(Evaluate(leaf->exe,&err))); // No check for return value, trust in grammatical parser auto ol=dynamic_cast<const ObjectList*>(olp.get()); // No check for return value, trust in grammatical parser
if(err) if(err)
{ {
const struct grammatic_location& loc=leaf->exe.front().Location(); const struct grammatic_location& loc=leaf->exe.front().Location();
@ -309,7 +309,7 @@ void* TreeEvaluateM(void* arg)
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
} }
if(!Save(ol.get())) if(!Save(ol))
{ {
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
@ -325,8 +325,8 @@ void* TreeEvaluateM(void* arg)
if(DepTree::PRINT==leaf->type) if(DepTree::PRINT==leaf->type)
{ {
err=false; err=false;
auto olp=Evaluate(leaf->exe,&err);
std::unique_ptr<const ObjectList> ol(dynamic_cast<const ObjectList*>(Evaluate(leaf->exe,&err))); // No check for return value, trust in grammatical parser auto ol=dynamic_cast<const ObjectList*>(olp.get()); // No check for return value, trust in grammatical parser
if(err) if(err)
{ {
const struct grammatic_location& loc=leaf->exe.front().Location(); const struct grammatic_location& loc=leaf->exe.front().Location();
@ -335,7 +335,7 @@ void* TreeEvaluateM(void* arg)
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
} }
if(!Print(ol.get())) if(!Print(ol))
{ {
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
@ -351,11 +351,9 @@ void* TreeEvaluateM(void* arg)
if(DepTree::VAR==leaf->type) if(DepTree::VAR==leaf->type)
{ {
const ObjectBase *eob;
// Main working call // Main working call
err=false; err=false;
eob=Evaluate(leaf->exe,&err); ObjPtr eob(Evaluate(leaf->exe,&err));
if(err) if(err)
{ {
const struct grammatic_location& loc=leaf->exe.front().Location(); const struct grammatic_location& loc=leaf->exe.front().Location();
@ -383,7 +381,6 @@ void* TreeEvaluateM(void* arg)
} }
// End critical section // End critical section
pthread_mutex_unlock(&p->tree_mtx); pthread_mutex_unlock(&p->tree_mtx);
delete eob;
} }
leaf->parents.clear(); leaf->parents.clear();
@ -410,8 +407,8 @@ void* TreeEvaluate(void* arg)
if(DepTree::SAVE==leaf->type) if(DepTree::SAVE==leaf->type)
{ {
err=false; err=false;
auto olp=Evaluate(leaf->exe,&err);
std::unique_ptr<const ObjectList> ol(dynamic_cast<const ObjectList*>(Evaluate(leaf->exe,&err))); // No check for return value, trust in grammatical parser auto ol=dynamic_cast<const ObjectList*>(olp.get()); // No check for return value, trust in grammatical parser
if(err) if(err)
{ {
const struct grammatic_location& loc=leaf->exe.front().Location(); const struct grammatic_location& loc=leaf->exe.front().Location();
@ -421,7 +418,7 @@ void* TreeEvaluate(void* arg)
return nullptr; return nullptr;
} }
// eob is evaluated object // eob is evaluated object
if(!Save(ol.get())) if(!Save(ol))
{ {
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
@ -433,8 +430,8 @@ void* TreeEvaluate(void* arg)
if(DepTree::PRINT==leaf->type) if(DepTree::PRINT==leaf->type)
{ {
err=false; err=false;
auto olp=Evaluate(leaf->exe,&err);
std::unique_ptr<const ObjectList> ol(dynamic_cast<const ObjectList*>(Evaluate(leaf->exe,&err))); // No check for return value, trust in grammatical parser auto ol=dynamic_cast<const ObjectList*>(olp.get()); // No check for return value, trust in grammatical parser
if(err) if(err)
{ {
const struct grammatic_location& loc=leaf->exe.front().Location(); const struct grammatic_location& loc=leaf->exe.front().Location();
@ -443,7 +440,7 @@ void* TreeEvaluate(void* arg)
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
} }
if(!Print(ol.get())) if(!Print(ol))
{ {
p->exitcode=1; p->exitcode=1;
return nullptr; return nullptr;
@ -454,11 +451,9 @@ void* TreeEvaluate(void* arg)
if(DepTree::VAR==leaf->type) if(DepTree::VAR==leaf->type)
{ {
const ObjectBase *eob;
// Main working call // Main working call
err=false; err=false;
eob=Evaluate(leaf->exe,&err); ObjPtr eob(Evaluate(leaf->exe,&err));
if(err) if(err)
{ {
const struct grammatic_location& loc=leaf->exe.front().Location(); const struct grammatic_location& loc=leaf->exe.front().Location();
@ -477,7 +472,6 @@ void* TreeEvaluate(void* arg)
// If node have no children, it's a new leaf node // If node have no children, it's a new leaf node
if(0==i->childrens.size() && DepTree::ROOT!=i->type) p->leafs.push_back(i); if(0==i->childrens.size() && DepTree::ROOT!=i->type) p->leafs.push_back(i);
} }
delete eob;
} }
leaf->parents.clear(); leaf->parents.clear();
delete leaf; delete leaf;

14
src/object.cpp

@ -114,7 +114,7 @@ UsedType UsedFuncs(const ExecExpr& exp)
return ret; return ret;
} }
const ObjectBase* Evaluate(ExecExpr& exp, bool* err) ObjPtr Evaluate(ExecExpr& exp, bool* err)
{ {
ExecExpr::iterator cse=exp.begin(); ExecExpr::iterator cse=exp.begin();
while(cse!=exp.end()) while(cse!=exp.end())
@ -123,7 +123,7 @@ const ObjectBase* Evaluate(ExecExpr& exp, bool* err)
{ {
case(StackElem::TYPE_ENDLIST): // Making list case(StackElem::TYPE_ENDLIST): // Making list
{ {
ObjectList* ol=new ObjectList; auto ol=std::make_shared<ObjectList>();
ExecExpr::iterator bl,el; ExecExpr::iterator bl,el;
bl=el=cse++; bl=el=cse++;
bl--; bl--;
@ -141,7 +141,7 @@ const ObjectBase* Evaluate(ExecExpr& exp, bool* err)
// Previous element must be OBJECT. We don't check this, we trust in grammatical parser. // Previous element must be OBJECT. We don't check this, we trust in grammatical parser.
ExecExpr::iterator pr=cse; ExecExpr::iterator pr=cse;
pr--; pr--;
cse->ReplaceByObject(new ObjectPair(cse->Name(),pr->PickObject())); cse->ReplaceByObject(ObjPtr(new ObjectPair(cse->Name(),pr->PickObject())));
// Remove previous element // Remove previous element
exp.erase(pr); exp.erase(pr);
// Go to next element // Go to next element
@ -184,7 +184,7 @@ const ObjectBase* Evaluate(ExecExpr& exp, bool* err)
return nullptr; return nullptr;
} }
// Replace function on returned value // Replace function on returned value
cse->ReplaceByObject(res); cse->ReplaceByObject(ObjPtr(res));
// Go to next element // Go to next element
cse++; continue; cse++; continue;
} }
@ -192,16 +192,16 @@ const ObjectBase* Evaluate(ExecExpr& exp, bool* err)
} }
} }
// After all, our list contains only one object. // After all, our list contains only one object.
const ObjectBase* ret=exp.begin()->PickObject(); ObjPtr ret=exp.begin()->PickObject();
exp.clear(); exp.clear();
return ret; return ret;
} }
void ReplaceVar(ExecExpr& exp, const std::string& var, const ObjectBase* ob) void ReplaceVar(ExecExpr& exp, const std::string& var, const ObjPtr& ob)
{ {
for(auto& se: exp) for(auto& se: exp)
if(se.isVar() && var==se.Name()) if(se.isVar() && var==se.Name())
se.ReplaceByObject(ob->Copy()); se.ReplaceByObject(ob);
} }
bool ObjectBase::Save(const char* fname) const bool ObjectBase::Save(const char* fname) const

8
src/parser/grammatical.y

@ -148,8 +148,8 @@ pair:
; ;
object: object:
STRING {COUT(DEBUG)<<" STRING\n"; I($$); $$->push_back(StackElem(new ObjectString($1),@1)); delete $1;} STRING {COUT(DEBUG)<<" STRING\n"; I($$); $$->push_back(SEObj(new ObjectString($1),@1)); delete $1;}
| BOOL {COUT(DEBUG)<<" BOOL\n"; I($$); $$->push_back(StackElem(new ObjectBool($1),@1));} | BOOL {COUT(DEBUG)<<" BOOL\n"; I($$); $$->push_back(SEObj(new ObjectBool($1),@1));}
| OBRACE list CBRACE {COUT(DEBUG)<<" OBRACE list CBRACE\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$2); $$->push_back(SEEList(@3));} | OBRACE list CBRACE {COUT(DEBUG)<<" OBRACE list CBRACE\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$2); $$->push_back(SEEList(@3));}
| expression %prec ASSIGN {COUT(DEBUG)<<" expression\n"; I($$); EADD($$,$1);} | expression %prec ASSIGN {COUT(DEBUG)<<" expression\n"; I($$); EADD($$,$1);}
| pair {COUT(DEBUG)<<" pair\n"; I($$); EADD($$,$1);} | pair {COUT(DEBUG)<<" pair\n"; I($$); EADD($$,$1);}
@ -166,8 +166,8 @@ expression:
| IDENTIFIER OBRACE object CBRACE {COUT(DEBUG)<<" IDENTIFIER OBRACE object CBRACE\n"; I($$); $$->push_front(SEBList(@2)); EADD($$,$3); $$->push_back(SEEList(@4)); $$->push_back(SEFunc($1,@1)); delete $1;} | IDENTIFIER OBRACE object CBRACE {COUT(DEBUG)<<" IDENTIFIER OBRACE object CBRACE\n"; I($$); $$->push_front(SEBList(@2)); EADD($$,$3); $$->push_back(SEEList(@4)); $$->push_back(SEFunc($1,@1)); delete $1;}
| IDENTIFIER OBRACE list CBRACE {COUT(DEBUG)<<" IDENTIFIER OBRACE list CBRACE\n"; I($$); $$->push_front(SEBList(@2)); EADD($$,$3); $$->push_back(SEEList(@4)); $$->push_back(SEFunc($1,@1)); delete $1;} | IDENTIFIER OBRACE list CBRACE {COUT(DEBUG)<<" IDENTIFIER OBRACE list CBRACE\n"; I($$); $$->push_front(SEBList(@2)); EADD($$,$3); $$->push_back(SEEList(@4)); $$->push_back(SEFunc($1,@1)); delete $1;}
| longidentifier {COUT(DEBUG)<<" longidentifier\n"; I($$); EADD($$,$1);} | longidentifier {COUT(DEBUG)<<" longidentifier\n"; I($$); EADD($$,$1);}
| REAL {COUT(DEBUG)<<" REAL\n"; I($$); $$->push_front(StackElem(new ObjectReal($1),@1));} | REAL {COUT(DEBUG)<<" REAL\n"; I($$); $$->push_front(SEObj(new ObjectReal($1),@1));}
| INTEGER {COUT(DEBUG)<<" INTEGER\n"; I($$); $$->push_front(StackElem(new ObjectInt($1),@1));} | INTEGER {COUT(DEBUG)<<" INTEGER\n"; I($$); $$->push_front(SEObj(new ObjectInt($1),@1));}
| expression '-' expression {COUT(DEBUG)<<" -\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$1); EADD($$,$3); $$->push_back(SEEList(@3)); $$->push_back(SEFunc("SUB",@2));} | expression '-' expression {COUT(DEBUG)<<" -\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$1); EADD($$,$3); $$->push_back(SEEList(@3)); $$->push_back(SEFunc("SUB",@2));}
| expression '+' expression {COUT(DEBUG)<<" +\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$1); EADD($$,$3); $$->push_back(SEEList(@3)); $$->push_back(SEFunc("ADD",@2));} | expression '+' expression {COUT(DEBUG)<<" +\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$1); EADD($$,$3); $$->push_back(SEEList(@3)); $$->push_back(SEFunc("ADD",@2));}
| expression '/' expression {COUT(DEBUG)<<" /\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$1); EADD($$,$3); $$->push_back(SEEList(@3)); $$->push_back(SEFunc("DIV",@2));} | expression '/' expression {COUT(DEBUG)<<" /\n"; I($$); $$->push_front(SEBList(@1)); EADD($$,$1); EADD($$,$3); $$->push_back(SEEList(@3)); $$->push_back(SEFunc("DIV",@2));}

Loading…
Cancel
Save