Browse Source

Interpret dot as function GET.

Add functions Copy (make object copy) and Evaluate (run functions) for class ObjectBase and its derivatives.
test
Michael Uleysky 9 years ago
parent
commit
e011354f04
  1. 2
      src/arifmetic.cpp
  2. 13
      src/arifmetic.h
  3. 3
      src/init.cpp
  4. 29
      src/object.cpp
  5. 175
      src/object.h
  6. 8
      src/parser/grammatical.y
  7. 3
      src/parser/lexical.l

2
src/arifmetic.cpp

@ -145,4 +145,4 @@ ObjectBase* Arifm_Pos(ObjectList* input)
if(t==tr) return new ObjectReal(dynamic_cast<const ObjectReal*>(input->At(0))->Value()); if(t==tr) return new ObjectReal(dynamic_cast<const ObjectReal*>(input->At(0))->Value());
return 0; return 0;
} }

13
src/arifmetic.h

@ -6,4 +6,15 @@ ObjectBase* Arifm_Mul(ObjectList* input);
ObjectBase* Arifm_Div(ObjectList* input); ObjectBase* Arifm_Div(ObjectList* input);
ObjectBase* Arifm_Pow(ObjectList* input); ObjectBase* Arifm_Pow(ObjectList* input);
ObjectBase* Arifm_Neg(ObjectList* input); ObjectBase* Arifm_Neg(ObjectList* input);
ObjectBase* Arifm_Pos(ObjectList* input); ObjectBase* Arifm_Pos(ObjectList* input);
template<class T>
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<const T*>(ob)->Get(dynamic_cast<const ObjectString*>(name)->Value());
}

3
src/init.cpp

@ -45,6 +45,9 @@ int RegisterArifmeticFunctions()
RegisterFunction("POW",Arifm_Pow); RegisterFunction("POW",Arifm_Pow);
RegisterFunction("POS",Arifm_Pos); RegisterFunction("POS",Arifm_Pos);
RegisterFunction("NEG",Arifm_Neg); RegisterFunction("NEG",Arifm_Neg);
RegisterFunction("GET",Get<ObjectList>);
RegisterFunction("GET",Get<ObjectPair>);
return 0; return 0;
} }

29
src/object.cpp

@ -1,6 +1,35 @@
#include "object.h" #include "object.h"
#include "globals.h"
template<> EXPORT std::string ObjectSimple<bool>::type="bool"; template<> EXPORT std::string ObjectSimple<bool>::type="bool";
template<> EXPORT std::string ObjectSimple<int64_t>::type="integer"; template<> EXPORT std::string ObjectSimple<int64_t>::type="integer";
template<> EXPORT std::string ObjectSimple<double>::type="real"; template<> EXPORT std::string ObjectSimple<double>::type="real";
template<> EXPORT std::string ObjectSimple<std::string>::type="string"; template<> EXPORT std::string ObjectSimple<std::string>::type="string";
inline ObjectBase* OFunc::Evaluate(bool* err)
{
*err=false;
if(G_funcs.find(name)==G_funcs.end())
{
*err=true;
COUT(ERROR)<<"Function "<<name<< " not found"<<std::endl;
return 0;
}
args->Evaluate(err);
if(*err)
{
COUT(ERROR)<<" in function call "<<Dump()<<std::endl;
return 0;
}
ObjectBase* ret;
auto p=G_funcs.equal_range(name);
for(auto f=p.first;f!=p.second;f++)
{
ret=(*(f->second))(args);
if(ret!=0) return ret;
}
*err=true;
COUT(ERROR)<<"Function(s) "<<name<< "can't evaluate expression "<<args->Dump()<<std::endl;
return 0;
}

175
src/object.h

@ -7,12 +7,14 @@
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <set> #include <set>
#include <memory>
#include <typeinfo> #include <typeinfo>
#include <typeindex> #include <typeindex>
#include "debug.h" #include "debug.h"
// Check if pointer is ObjectBase derivative class // Check if pointer is ObjectBase derivative class
#define IS_OTYPE(quo,equ) (std::type_index(typeid(*quo))==std::type_index(typeid(equ))) #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 // Base class for all objects
class EXPORT ObjectBase class EXPORT ObjectBase
@ -67,6 +69,9 @@ public:
virtual std::string Dump() const {return "%"+Type()+"%";} virtual std::string Dump() const {return "%"+Type()+"%";}
virtual void UsedFuncs(std::set<std::string>& funcs) const {} virtual void UsedFuncs(std::set<std::string>& funcs) const {}
virtual void UsedIdents(std::set<std::string>& ids) const {} virtual void UsedIdents(std::set<std::string>& 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 // Template for objects without specific constructor/destructor
@ -105,6 +110,7 @@ public:
s<<val; s<<val;
return s.str(); return s.str();
} }
ObjectBase* Copy() const override {return new ObjectSimple<T>(val);}
}; };
// Simple objects // Simple objects
@ -125,18 +131,14 @@ class EXPORT ObjectPair: public ObjectBase
{ {
private: private:
std::string name; std::string name;
ObjectBase* val; std::shared_ptr<ObjectBase> val;
public: public:
ObjectPair():val(0) {} ObjectPair() {}
ObjectPair(const std::string& n, ObjectBase* v):name(n),val(v) {} ObjectPair(const std::string& n, ObjectBase* v):name(n) {val.reset(v);}
ObjectPair(const std::string* n, ObjectBase* v):name(*n),val(v) {} ObjectPair(const std::string* n, ObjectBase* v):name(*n) {val.reset(v);}
~ObjectPair() ~ObjectPair() {}
{ bool Exist() const {return 0!=val.get();}
if(val!=0) delete val;
val=0;
}
bool Exist() const {return 0==val;}
bool Print() const override bool Print() const override
{ {
@ -148,28 +150,55 @@ public:
} }
std::string Type() const override {return "pair";} std::string Type() const override {return "pair";}
std::string Name() const {return name;} std::string Name() const {return name;}
const ObjectBase* Value() const {return val;} const ObjectBase* Value() const {return val.get();}
void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val=v;}} void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val.reset(v);}}
std::string Dump() const override { return Name()+"="+val->Dump(); } std::string Dump() const override { return Name()+"="+val->Dump(); }
void UsedFuncs(std::set<std::string>& funcs) const override {return val->UsedFuncs(funcs);} void UsedFuncs(std::set<std::string>& funcs) const override {return val->UsedFuncs(funcs);}
void UsedIdents(std::set<std::string>& ids) const override {return val->UsedIdents(ids);} void UsedIdents(std::set<std::string>& 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 "<<Dump()<<std::endl;
return 0;
}
if(0==p) return 0;
val.reset(p);
return 0;
}
ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override
{
auto p=val->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 for objects list
class EXPORT ObjectList: public ObjectBase class EXPORT ObjectList: public ObjectBase
{ {
private: private:
std::vector<ObjectBase*> vals; typedef std::vector<ObjectBase*> ListValues;
std::shared_ptr<ListValues> vals;
public: public:
ObjectList() {} ObjectList() {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;});}
ObjectList(ObjectBase* o) {PushBack(o);} ObjectList(ObjectBase* o) {vals.reset(new ListValues, [](ListValues* p){for(auto& i: *p) delete i; delete p;}); PushBack(o);}
~ObjectList() ~ObjectList() {}
{ bool Exist() const {return 0==vals->size();}
for(auto& i: vals) delete i;
vals.clear();
}
bool Exist() const {return 0==vals.size();}
bool Print() const override bool Print() const override
{ {
@ -178,41 +207,103 @@ public:
COUT(INFO)<<"Number of elements: "<<Size()<<std::endl; COUT(INFO)<<"Number of elements: "<<Size()<<std::endl;
return true; return true;
} }
std::vector<ObjectBase*>::size_type Size() const {return vals.size();} ListValues::size_type Size() const {return vals->size();}
std::string Type() const override {return "list";} std::string Type() const override {return "list";}
ObjectList* PushBack(ObjectBase* p) {vals.push_back(p); return this;} ObjectList* PushBack(ObjectBase* p) {vals->push_back(p); return this;}
const ObjectBase* At(std::vector<ObjectBase*>::size_type i) const {return vals[i];} const ObjectBase* At(ListValues::size_type i) const {return (*vals)[i];}
std::string Dump() const override std::string Dump() const override
{ {
std::string s("("); std::string s("(");
for(auto& i: vals) s+=i->Dump()+", "; for(auto& i: *vals) s+=i->Dump()+", ";
if(vals.size()!=0) s.resize(s.length()-2); if(vals->size()!=0) s.resize(s.length()-2);
return s+")"; return s+")";
} }
void UsedFuncs(std::set<std::string>& funcs) const override {for(auto& i: vals) i->UsedFuncs(funcs);} void UsedFuncs(std::set<std::string>& funcs) const override {for(auto& i: *vals) i->UsedFuncs(funcs);}
void UsedIdents(std::set<std::string>& ids) const override {for(auto& i: vals) i->UsedIdents(ids);} void UsedIdents(std::set<std::string>& 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 "<<i->Dump()<<std::endl;
return 0;
}
if(0!=p)
{
delete i;
i=p;
}
}
return 0;
}
ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override
{
ObjectBase* p;
for(auto& i: *vals)
{
p=i->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<const ObjectPair*>(i)->Get(gname);
if(0!=p) return p;
if(IS_OTYPEI(i,ObjectList)) p=dynamic_cast<const ObjectList*>(i)->Get(gname);
if(0!=p) return p;
}
return 0;
}
}; };
// Class for storing identifiers // Class for storing identifiers
class OId: public ObjectBase class OId: public ObjectBase
{ {
std::string name; std::string name;
std::string fullname;
void ParseName(const std::string& s)
{
fullname=s;
name=s.substr(0,s.find_first_of('.'));
}
public: public:
OId(const std::string* t) {ParseName(*t);} OId(const std::string* t) {name=*t;}
~OId() {} ~OId() {}
bool Print() const override {return false;} bool Print() const override {return false;}
std::string Type() const override {return "IDENT";} std::string Type() const override {return "IDENT";}
std::string Name() const {return name;} std::string Name() const {return name;}
void SetName(std::string s) {ParseName(s);} void SetName(const std::string& s) {name=s;}
std::string Dump() const override {return fullname;}; std::string Dump() const override {return name;};
void UsedIdents(std::set<std::string>& ids) const override {ids.insert(name);} void UsedIdents(std::set<std::string>& ids) const override {ids.insert(name);}
ObjectBase* Copy() const override
{
COUT(WARNING)<<"OId::Copy: this call must never be happens."<<std::endl;
return new OId(&name);
}
ObjectBase* Evaluate(bool* err) override
{
COUT(ERROR)<<"Variable "<<name<<" still not defined."<<std::endl;
*err=true;
return 0;
}
ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override
{
if(vname==Name()) return ob->Copy();
else return 0;
}
}; };
// Class for storing functions // Class for storing functions
@ -239,6 +330,16 @@ public:
std::string Dump() const override {return Name()+args->Dump();}; std::string Dump() const override {return Name()+args->Dump();};
void UsedFuncs(std::set<std::string>& funcs) const override {funcs.insert(name); args->UsedFuncs(funcs);} void UsedFuncs(std::set<std::string>& funcs) const override {funcs.insert(name); args->UsedFuncs(funcs);}
void UsedIdents(std::set<std::string>& ids) const override {args->UsedIdents(ids);} void UsedIdents(std::set<std::string>& ids) const override {args->UsedIdents(ids);}
ObjectBase* Copy() const override
{
COUT(WARNING)<<"OFunc::Copy: this call must never be happens."<<std::endl;
return new OFunc(&name,args->Copy());
}
ObjectBase* Evaluate(bool* err) override;
ObjectBase* ReplaceVar(const std::string& vname, ObjectBase* ob) override
{
return args->ReplaceVar(vname,ob);
}
}; };
#endif #endif

8
src/parser/grammatical.y

@ -50,7 +50,9 @@ inline void conferror(YYLTYPE *locp, yyscan_t sc, const char * str)
%left '*' '/' %left '*' '/'
%precedence UNARY /* negation--unary minus */ %precedence UNARY /* negation--unary minus */
%right '^' /* exponentiation */ %right '^' /* exponentiation */
%left '.'
%type <ob> longidentifier
%type <ob> expression %type <ob> expression
%type <ob> call %type <ob> call
%type <ob> object %type <ob> 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 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;} | 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: expression:
IDENTIFIER {COUT(DEBUG)<<" IDENTIFIER\n"; $$=new OId($1); delete $1;} IDENTIFIER {COUT(DEBUG)<<" IDENTIFIER\n"; $$=new OId($1); delete $1;}
| longidentifier {COUT(DEBUG)<<" longidentifier\n"; $$=$1;}
| REAL {COUT(DEBUG)<<" REAL\n"; $$=new ObjectReal($1);} | REAL {COUT(DEBUG)<<" REAL\n"; $$=new ObjectReal($1);}
| INTEGER {COUT(DEBUG)<<" INTEGER\n"; $$=new ObjectInt($1);} | INTEGER {COUT(DEBUG)<<" INTEGER\n"; $$=new ObjectInt($1);}
| expression '-' expression {COUT(DEBUG)<<" -\n"; $$=new OFunc("SUB",(new ObjectList($1))->PushBack($3));} | expression '-' expression {COUT(DEBUG)<<" -\n"; $$=new OFunc("SUB",(new ObjectList($1))->PushBack($3));}

3
src/parser/lexical.l

@ -57,7 +57,8 @@ include\(\".+\"\); {/*
<PARSE>\; COUT(MOREDEBUG)<<" ENDL()"<<std::endl; BEGIN(0); return ENDL; <PARSE>\; COUT(MOREDEBUG)<<" ENDL()"<<std::endl; BEGIN(0); return ENDL;
<PARSE>= COUT(MOREDEBUG)<<" ASSIGN()"; return ASSIGN; <PARSE>= COUT(MOREDEBUG)<<" ASSIGN()"; return ASSIGN;
<PARSE>, COUT(MOREDEBUG)<<" DELIM()"; return DELIM; <PARSE>, COUT(MOREDEBUG)<<" DELIM()"; return DELIM;
<PARSE>([a-zA-Z][a-zA-Z0-9_]*\.)*[a-zA-Z][a-zA-Z0-9_]* COUT(MOREDEBUG)<<" IDENTIFIER("<<yytext<<")"; yylval_param->str=new std::string(yytext); return IDENTIFIER; <PARSE>[a-zA-Z][a-zA-Z0-9_]* COUT(MOREDEBUG)<<" IDENTIFIER("<<yytext<<")"; yylval_param->str=new std::string(yytext); return IDENTIFIER;
<PARSE>\. COUT(MOREDEBUG)<<" DOT()"; return yytext[0];
<PARSE,INITIAL>[ \n\t] <PARSE,INITIAL>[ \n\t]
<PARSE,INITIAL>\#.* <PARSE,INITIAL>\#.*
<PARSE>\" BEGIN(PSTRING); str.erase(); <PARSE>\" BEGIN(PSTRING); str.erase();

Loading…
Cancel
Save