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 10 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());
return 0;
}
}

13
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);
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("POS",Arifm_Pos);
RegisterFunction("NEG",Arifm_Neg);
RegisterFunction("GET",Get<ObjectList>);
RegisterFunction("GET",Get<ObjectPair>);
return 0;
}

29
src/object.cpp

@ -1,6 +1,35 @@
#include "object.h"
#include "globals.h"
template<> EXPORT std::string ObjectSimple<bool>::type="bool";
template<> EXPORT std::string ObjectSimple<int64_t>::type="integer";
template<> EXPORT std::string ObjectSimple<double>::type="real";
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 <sstream>
#include <set>
#include <memory>
#include <typeinfo>
#include <typeindex>
#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<std::string>& funcs) 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
@ -105,6 +110,7 @@ public:
s<<val;
return s.str();
}
ObjectBase* Copy() const override {return new ObjectSimple<T>(val);}
};
// Simple objects
@ -125,18 +131,14 @@ class EXPORT ObjectPair: public ObjectBase
{
private:
std::string name;
ObjectBase* val;
std::shared_ptr<ObjectBase> 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<std::string>& funcs) const override {return val->UsedFuncs(funcs);}
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 EXPORT ObjectList: public ObjectBase
{
private:
std::vector<ObjectBase*> vals;
typedef std::vector<ObjectBase*> ListValues;
std::shared_ptr<ListValues> 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()<<std::endl;
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";}
ObjectList* PushBack(ObjectBase* p) {vals.push_back(p); return this;}
const ObjectBase* At(std::vector<ObjectBase*>::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<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 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);}
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 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<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
@ -239,6 +330,16 @@ public:
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 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

8
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 <ob> longidentifier
%type <ob> expression
%type <ob> call
%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 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));}

3
src/parser/lexical.l

@ -57,7 +57,8 @@ include\(\".+\"\); {/*
<PARSE>\; COUT(MOREDEBUG)<<" ENDL()"<<std::endl; BEGIN(0); return ENDL;
<PARSE>= COUT(MOREDEBUG)<<" ASSIGN()"; return ASSIGN;
<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>\#.*
<PARSE>\" BEGIN(PSTRING); str.erase();

Loading…
Cancel
Save