From e011354f04f83e08690b5787c608bbb0feaf843e Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Sat, 5 Sep 2015 13:33:28 +1000 Subject: [PATCH] Interpret dot as function GET. Add functions Copy (make object copy) and Evaluate (run functions) for class ObjectBase and its derivatives. --- src/arifmetic.cpp | 2 +- src/arifmetic.h | 13 ++- src/init.cpp | 3 + src/object.cpp | 29 +++++++ src/object.h | 175 ++++++++++++++++++++++++++++++--------- src/parser/grammatical.y | 8 ++ src/parser/lexical.l | 3 +- 7 files changed, 193 insertions(+), 40 deletions(-) diff --git a/src/arifmetic.cpp b/src/arifmetic.cpp index ba34354..9c2b8c3 100644 --- a/src/arifmetic.cpp +++ b/src/arifmetic.cpp @@ -145,4 +145,4 @@ ObjectBase* Arifm_Pos(ObjectList* input) if(t==tr) return new ObjectReal(dynamic_cast(input->At(0))->Value()); return 0; -} \ No newline at end of file +} diff --git a/src/arifmetic.h b/src/arifmetic.h index 9fd4b5c..2c980b9 100644 --- a/src/arifmetic.h +++ b/src/arifmetic.h @@ -6,4 +6,15 @@ ObjectBase* Arifm_Mul(ObjectList* input); ObjectBase* Arifm_Div(ObjectList* input); ObjectBase* Arifm_Pow(ObjectList* input); ObjectBase* Arifm_Neg(ObjectList* input); -ObjectBase* Arifm_Pos(ObjectList* input); \ No newline at end of file +ObjectBase* Arifm_Pos(ObjectList* input); + +template +ObjectBase* Get(ObjectList* input) +{ + if(input->Size()!=2) return 0; + const ObjectBase* ob=input->At(0); + const ObjectBase* name=input->At(1); + if( (!IS_OTYPE(ob,T)) || (!IS_OTYPE(name,ObjectString)) ) return 0; + + return dynamic_cast(ob)->Get(dynamic_cast(name)->Value()); +} diff --git a/src/init.cpp b/src/init.cpp index 5b418de..ddc8680 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -45,6 +45,9 @@ int RegisterArifmeticFunctions() RegisterFunction("POW",Arifm_Pow); RegisterFunction("POS",Arifm_Pos); RegisterFunction("NEG",Arifm_Neg); + + RegisterFunction("GET",Get); + RegisterFunction("GET",Get); return 0; } diff --git a/src/object.cpp b/src/object.cpp index 8c91507..a21186e 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -1,6 +1,35 @@ #include "object.h" +#include "globals.h" template<> EXPORT std::string ObjectSimple::type="bool"; template<> EXPORT std::string ObjectSimple::type="integer"; template<> EXPORT std::string ObjectSimple::type="real"; template<> EXPORT std::string ObjectSimple::type="string"; + +inline ObjectBase* OFunc::Evaluate(bool* err) +{ + *err=false; + if(G_funcs.find(name)==G_funcs.end()) + { + *err=true; + COUT(ERROR)<<"Function "<Evaluate(err); + if(*err) + { + COUT(ERROR)<<" in function call "<second))(args); + if(ret!=0) return ret; + } + *err=true; + COUT(ERROR)<<"Function(s) "<Dump()< #include #include +#include #include #include #include "debug.h" // Check if pointer is ObjectBase derivative class #define IS_OTYPE(quo,equ) (std::type_index(typeid(*quo))==std::type_index(typeid(equ))) +#define IS_OTYPEI(quo,equ) (std::type_index(typeid(quo))==std::type_index(typeid(equ))) // Base class for all objects class EXPORT ObjectBase @@ -67,6 +69,9 @@ public: virtual std::string Dump() const {return "%"+Type()+"%";} virtual void UsedFuncs(std::set& funcs) const {} virtual void UsedIdents(std::set& ids) const {} + virtual ObjectBase* Copy() const=0; + virtual ObjectBase* Evaluate(bool* err) {*err=false; return 0;} + virtual ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) {return 0;} }; // Template for objects without specific constructor/destructor @@ -105,6 +110,7 @@ public: s<(val);} }; // Simple objects @@ -125,18 +131,14 @@ class EXPORT ObjectPair: public ObjectBase { private: std::string name; - ObjectBase* val; + std::shared_ptr val; public: - ObjectPair():val(0) {} - ObjectPair(const std::string& n, ObjectBase* v):name(n),val(v) {} - ObjectPair(const std::string* n, ObjectBase* v):name(*n),val(v) {} - ~ObjectPair() - { - if(val!=0) delete val; - val=0; - } - bool Exist() const {return 0==val;} + ObjectPair() {} + ObjectPair(const std::string& n, ObjectBase* v):name(n) {val.reset(v);} + ObjectPair(const std::string* n, ObjectBase* v):name(*n) {val.reset(v);} + ~ObjectPair() {} + bool Exist() const {return 0!=val.get();} bool Print() const override { @@ -148,28 +150,55 @@ public: } std::string Type() const override {return "pair";} std::string Name() const {return name;} - const ObjectBase* Value() const {return val;} - void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val=v;}} + const ObjectBase* Value() const {return val.get();} + void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val.reset(v);}} std::string Dump() const override { return Name()+"="+val->Dump(); } void UsedFuncs(std::set& funcs) const override {return val->UsedFuncs(funcs);} void UsedIdents(std::set& ids) const override {return val->UsedIdents(ids);} + ObjectBase* Copy() const override + { + auto ret=new ObjectPair; + ret->name=name; + ret->val=val; + return ret; + } + ObjectBase* Evaluate(bool* err) override + { + auto p=val->Evaluate(err); + if(*err) + { + COUT(ERROR)<<" in pair "<ReplaceVar(vname,ob); + if(0!=p) val.reset(p); + return 0; + } + ObjectBase* Get(const std::string& gname) const + { + if(gname==name) return val->Copy(); + else return 0; + } }; // Class for objects list class EXPORT ObjectList: public ObjectBase { private: - std::vector vals; + typedef std::vector ListValues; + std::shared_ptr vals; public: - ObjectList() {} - ObjectList(ObjectBase* o) {PushBack(o);} - ~ObjectList() - { - for(auto& i: vals) delete i; - vals.clear(); - } - bool Exist() const {return 0==vals.size();} + ObjectList() {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;});} + ObjectList(ObjectBase* o) {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;}); PushBack(o);} + ~ObjectList() {} + bool Exist() const {return 0==vals->size();} bool Print() const override { @@ -178,41 +207,103 @@ public: COUT(INFO)<<"Number of elements: "<::size_type Size() const {return vals.size();} + ListValues::size_type Size() const {return vals->size();} std::string Type() const override {return "list";} - ObjectList* PushBack(ObjectBase* p) {vals.push_back(p); return this;} - const ObjectBase* At(std::vector::size_type i) const {return vals[i];} + ObjectList* PushBack(ObjectBase* p) {vals->push_back(p); return this;} + const ObjectBase* At(ListValues::size_type i) const {return (*vals)[i];} std::string Dump() const override { std::string s("("); - for(auto& i: vals) s+=i->Dump()+", "; - if(vals.size()!=0) s.resize(s.length()-2); + for(auto& i: *vals) s+=i->Dump()+", "; + if(vals->size()!=0) s.resize(s.length()-2); return s+")"; } - void UsedFuncs(std::set& funcs) const override {for(auto& i: vals) i->UsedFuncs(funcs);} - void UsedIdents(std::set& ids) const override {for(auto& i: vals) i->UsedIdents(ids);} + void UsedFuncs(std::set& funcs) const override {for(auto& i: *vals) i->UsedFuncs(funcs);} + void UsedIdents(std::set& ids) const override {for(auto& i: *vals) i->UsedIdents(ids);} + ObjectBase* Copy() const override + { + auto ret=new ObjectList; + ret->vals=vals; + return ret; + } + ObjectBase* Evaluate(bool* err) override + { + ObjectBase* p; + for(auto& i: *vals) + { + p=i->Evaluate(err); + if(*err) + { + COUT(ERROR)<<" in list member "<Dump()<ReplaceVar(vname,ob); + if(0!=p) + { + delete i; + i=p; + } + } + return 0; + } + ObjectBase* Get(const std::string& gname) const + { + ObjectBase* p; + for(auto& i: *vals) + { + p=0; + if(IS_OTYPEI(i,ObjectPair)) p=dynamic_cast(i)->Get(gname); + if(0!=p) return p; + if(IS_OTYPEI(i,ObjectList)) p=dynamic_cast(i)->Get(gname); + if(0!=p) return p; + } + return 0; + } }; // Class for storing identifiers class OId: public ObjectBase { std::string name; - std::string fullname; - void ParseName(const std::string& s) - { - fullname=s; - name=s.substr(0,s.find_first_of('.')); - } public: - OId(const std::string* t) {ParseName(*t);} + OId(const std::string* t) {name=*t;} ~OId() {} bool Print() const override {return false;} std::string Type() const override {return "IDENT";} std::string Name() const {return name;} - void SetName(std::string s) {ParseName(s);} - std::string Dump() const override {return fullname;}; + void SetName(const std::string& s) {name=s;} + std::string Dump() const override {return name;}; void UsedIdents(std::set& ids) const override {ids.insert(name);} + ObjectBase* Copy() const override + { + COUT(WARNING)<<"OId::Copy: this call must never be happens."<Copy(); + else return 0; + } }; // Class for storing functions @@ -239,6 +330,16 @@ public: std::string Dump() const override {return Name()+args->Dump();}; void UsedFuncs(std::set& funcs) const override {funcs.insert(name); args->UsedFuncs(funcs);} void UsedIdents(std::set& ids) const override {args->UsedIdents(ids);} + ObjectBase* Copy() const override + { + COUT(WARNING)<<"OFunc::Copy: this call must never be happens."<Copy()); + } + ObjectBase* Evaluate(bool* err) override; + ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override + { + return args->ReplaceVar(vname,ob); + } }; #endif diff --git a/src/parser/grammatical.y b/src/parser/grammatical.y index 7e13372..d98dd86 100644 --- a/src/parser/grammatical.y +++ b/src/parser/grammatical.y @@ -50,7 +50,9 @@ inline void conferror(YYLTYPE *locp, yyscan_t sc, const char * str) %left '*' '/' %precedence UNARY /* negation--unary minus */ %right '^' /* exponentiation */ +%left '.' +%type longidentifier %type expression %type call %type object @@ -120,8 +122,14 @@ call: IDENTIFIER OBRACE object CBRACE {COUT(DEBUG)<<" IDENTIFIER OBRACE object CBRACE\n"; $$=new OFunc($1,$3); delete $1;} | IDENTIFIER OBRACE list CBRACE {COUT(DEBUG)<<" IDENTIFIER OBRACE list CBRACE\n"; $$=new OFunc($1,$3); delete $1;} + +longidentifier: + IDENTIFIER '.' IDENTIFIER {COUT(DEBUG)<<" IDENTIFIER DOT IDENTIFIER\n"; $$=new OFunc("GET",(new ObjectList(new OId($1)))->PushBack(new ObjectString($3))); delete $1; delete $3;} + | longidentifier '.' IDENTIFIER {COUT(DEBUG)<<" longidentifier '.' IDENTIFIER\n"; $$=new OFunc("GET",(new ObjectList($1))->PushBack(new ObjectString($3))); delete $3;} + expression: IDENTIFIER {COUT(DEBUG)<<" IDENTIFIER\n"; $$=new OId($1); delete $1;} + | longidentifier {COUT(DEBUG)<<" longidentifier\n"; $$=$1;} | REAL {COUT(DEBUG)<<" REAL\n"; $$=new ObjectReal($1);} | INTEGER {COUT(DEBUG)<<" INTEGER\n"; $$=new ObjectInt($1);} | expression '-' expression {COUT(DEBUG)<<" -\n"; $$=new OFunc("SUB",(new ObjectList($1))->PushBack($3));} diff --git a/src/parser/lexical.l b/src/parser/lexical.l index 7ac72b4..8062dc5 100644 --- a/src/parser/lexical.l +++ b/src/parser/lexical.l @@ -57,7 +57,8 @@ include\(\".+\"\); {/* \; COUT(MOREDEBUG)<<" ENDL()"<= COUT(MOREDEBUG)<<" ASSIGN()"; return ASSIGN; , COUT(MOREDEBUG)<<" DELIM()"; return DELIM; -([a-zA-Z][a-zA-Z0-9_]*\.)*[a-zA-Z][a-zA-Z0-9_]* COUT(MOREDEBUG)<<" IDENTIFIER("<str=new std::string(yytext); return IDENTIFIER; +[a-zA-Z][a-zA-Z0-9_]* COUT(MOREDEBUG)<<" IDENTIFIER("<str=new std::string(yytext); return IDENTIFIER; +\. COUT(MOREDEBUG)<<" DOT()"; return yytext[0]; [ \n\t] \#.* \" BEGIN(PSTRING); str.erase();