Michael Uleysky
9 years ago
13 changed files with 482 additions and 35 deletions
@ -1,21 +1,33 @@ |
|||||||
CFLAGS=-O2 -g
|
CFLAGS=-O2 -g -std=gnu++11
|
||||||
|
LDFLAGS=
|
||||||
OBJECTS=main.o debug.o init.o parser/lexical.o
|
|
||||||
|
|
||||||
|
CC=g++
|
||||||
|
|
||||||
|
SOURCE = $(wildcard *.cpp) parser/lexical.cpp parser/grammatical.cpp
|
||||||
|
DEPENDS = $(subst .cpp,.d,$(SOURCE))
|
||||||
|
OBJECTS = $(subst .cpp,.o,$(SOURCE))
|
||||||
|
|
||||||
makemap: $(OBJECTS) |
makemap: $(OBJECTS) |
||||||
g++ $(CFLAGS) -o $@ $(OBJECTS)
|
$(CC) $(LDFLAGS) -o $@ $(OBJECTS)
|
||||||
|
|
||||||
|
include $(DEPENDS) |
||||||
|
|
||||||
|
%.o: %.cpp |
||||||
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
main.o: debug.h init.h |
%.d: %.cpp |
||||||
init.o: parser/lexical.h parser/parser.h debug.h init.h |
$(CC) $(CFLAGS) -MM -MT $(subst .cpp,.o,$<) $< | sed 's%\(^.*\):%\1 $@ :%g' >$@
|
||||||
parser/lexical.o: parser/parser.h debug.h |
|
||||||
|
parser/grammatical.d: parser/lexical.h |
||||||
|
|
||||||
parser/lexical.h parser/lexical.cpp: parser/lexical.l |
parser/lexical.h parser/lexical.cpp: parser/lexical.l |
||||||
cd parser && flex lexical.l
|
cd parser && flex lexical.l
|
||||||
|
|
||||||
|
parser/grammatical.h parser/grammatical.cpp: parser/grammatical.y |
||||||
|
cd parser && bison grammatical.y
|
||||||
|
|
||||||
clean: |
clean: |
||||||
rm -f *.o parser/*.o parser/lexical.{cpp,h}
|
rm -f *.o *.d parser/*.{o,d} parser/{lexical,grammatical}.{cpp,h}
|
||||||
|
|
||||||
distclean: clean |
distclean: clean |
||||||
rm -f makemap
|
rm -f makemap
|
@ -0,0 +1,24 @@ |
|||||||
|
#include "globals.h" |
||||||
|
|
||||||
|
// Variables definitions
|
||||||
|
std::map<std::string,ObjectBase*> G_vars; |
||||||
|
|
||||||
|
// Functions addresses
|
||||||
|
std::multimap<std::string,Func> G_funcs; |
||||||
|
|
||||||
|
// List of objects to save
|
||||||
|
std::list<ObjectBase*> G_tosave; |
||||||
|
|
||||||
|
// List of objects to print
|
||||||
|
std::list<ObjectBase*> G_toprint; |
||||||
|
|
||||||
|
void ClearGlobals() |
||||||
|
{ |
||||||
|
for(auto& it:G_vars) delete it.second; |
||||||
|
for(auto& it:G_tosave) delete it; |
||||||
|
for(auto& it:G_toprint) delete it; |
||||||
|
|
||||||
|
G_vars.clear(); |
||||||
|
G_tosave.clear(); |
||||||
|
G_toprint.clear(); |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
#ifndef GLOBALS_H |
||||||
|
#define GLOBALS_H |
||||||
|
#include <map> |
||||||
|
#include <list> |
||||||
|
#include <string> |
||||||
|
#include "object.h" |
||||||
|
|
||||||
|
// Variables definitions
|
||||||
|
extern std::map<std::string,ObjectBase*> G_vars; |
||||||
|
|
||||||
|
// Functions addresses
|
||||||
|
typedef ObjectBase* (*Func)(ObjectList*); |
||||||
|
extern std::multimap<std::string,Func> G_funcs; |
||||||
|
|
||||||
|
// List of objects to save
|
||||||
|
extern std::list<ObjectBase*> G_tosave; |
||||||
|
|
||||||
|
// List of objects to print
|
||||||
|
extern std::list<ObjectBase*> G_toprint; |
||||||
|
|
||||||
|
void ClearGlobals(); |
||||||
|
#endif |
@ -1,13 +1,18 @@ |
|||||||
#include "debug.h" |
#include "debug.h" |
||||||
#include "init.h" |
#include "init.h" |
||||||
|
#include "globals.h" |
||||||
|
|
||||||
int main(int argc, char** argv) |
int main(int argc, char** argv) |
||||||
{ |
{ |
||||||
if(argc!=2) return 1; |
if(argc!=2) return 1; |
||||||
|
|
||||||
SetDebugLevel(DEBUG); |
SetDebugLevel(INFO); |
||||||
|
|
||||||
ParseConfigFile(argv[1]); |
ParseConfigFile(argv[1]); |
||||||
|
|
||||||
|
COUT(INFO)<<G_vars.size()<<std::endl; |
||||||
|
for(auto& i: G_vars) COUT(INFO)<<i.first<<"="+i.second->Dump()<<";"<<std::endl; |
||||||
|
|
||||||
|
ClearGlobals(); |
||||||
return 0; |
return 0; |
||||||
} |
} |
||||||
|
@ -0,0 +1,6 @@ |
|||||||
|
#include "object.h" |
||||||
|
|
||||||
|
template<> std::string ObjectSimple<bool>::type="bool"; |
||||||
|
template<> std::string ObjectSimple<int64_t>::type="integer"; |
||||||
|
template<> std::string ObjectSimple<double>::type="real"; |
||||||
|
template<> std::string ObjectSimple<std::string>::type="string"; |
@ -0,0 +1,227 @@ |
|||||||
|
#ifndef OBJECT_H |
||||||
|
#define OBJECT_H |
||||||
|
#include <stdio.h> |
||||||
|
#include <errno.h> |
||||||
|
#include <string.h> |
||||||
|
#include <inttypes.h> |
||||||
|
#include <list> |
||||||
|
#include <sstream> |
||||||
|
#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))) |
||||||
|
|
||||||
|
// Base class for all objects
|
||||||
|
class ObjectBase |
||||||
|
{ |
||||||
|
protected: |
||||||
|
// No save by default
|
||||||
|
virtual const int8_t* Blob(size_t* size) const { *size=0; return 0; } |
||||||
|
virtual void DeallocBlob(const void* ptr) const {}; |
||||||
|
public: |
||||||
|
|
||||||
|
ObjectBase() = default; |
||||||
|
ObjectBase(const ObjectBase&) = delete; |
||||||
|
virtual ~ObjectBase(){} |
||||||
|
virtual std::string Type() const=0; |
||||||
|
virtual bool Print() const=0; |
||||||
|
bool Save(const char* fname) const |
||||||
|
{ |
||||||
|
size_t size,offset=0,wr; |
||||||
|
const int8_t* dptr; |
||||||
|
FILE* fd; |
||||||
|
int serrno; |
||||||
|
|
||||||
|
fd=fopen(fname,"w"); |
||||||
|
serrno=errno; |
||||||
|
if(0==fd) |
||||||
|
{ |
||||||
|
COUT(ERROR)<<"Can't open file "<<fname<<" for writing: "<<strerror(serrno)<<std::endl; |
||||||
|
return false; |
||||||
|
} |
||||||
|
dptr=Blob(&size); |
||||||
|
if(0==dptr) |
||||||
|
{ |
||||||
|
COUT(ERROR)<<"Can't get blob for writing to "<<fname<<std::endl; |
||||||
|
fclose(fd); |
||||||
|
return false; |
||||||
|
} |
||||||
|
while(offset!=size) |
||||||
|
{ |
||||||
|
wr=fwrite(dptr+offset,1,size-offset,fd); |
||||||
|
if(0==wr) |
||||||
|
{ |
||||||
|
COUT(ERROR)<<"Failed to write in file "<<fname<<std::endl; |
||||||
|
fclose(fd); DeallocBlob(dptr); |
||||||
|
return false; |
||||||
|
} |
||||||
|
offset+=wr; |
||||||
|
} |
||||||
|
fclose(fd); |
||||||
|
DeallocBlob(dptr); |
||||||
|
return true; |
||||||
|
} |
||||||
|
virtual std::string Dump() const {return "%"+Type()+"%";} |
||||||
|
}; |
||||||
|
|
||||||
|
// Template for objects without specific constructor/destructor
|
||||||
|
template<class T> |
||||||
|
class ObjectSimple: public ObjectBase |
||||||
|
{ |
||||||
|
private: |
||||||
|
T val; |
||||||
|
static std::string type; |
||||||
|
|
||||||
|
const int8_t* Blob(size_t* size) const override |
||||||
|
{ |
||||||
|
*size=sizeof(T); |
||||||
|
return reinterpret_cast<const int8_t*>(&val); |
||||||
|
} |
||||||
|
|
||||||
|
public: |
||||||
|
ObjectSimple(T t):val(t) {} |
||||||
|
ObjectSimple(const T* t):val(*t) {} |
||||||
|
~ObjectSimple() {} |
||||||
|
bool Print() const override |
||||||
|
{ |
||||||
|
COUT(INFO)<<"Object type: "<<Type()<<"."<<std::endl; |
||||||
|
COUT(INFO)<<"Value: "<<val<<std::endl; |
||||||
|
return true; |
||||||
|
} |
||||||
|
std::string Type() const override {return type;} |
||||||
|
T Value() const {return val;} |
||||||
|
void SetValue(T s) {val=s;} |
||||||
|
std::string Dump() const override |
||||||
|
{ |
||||||
|
std::stringstream s; |
||||||
|
if(std::type_index(typeid(T))==std::type_index(typeid(std::string))) |
||||||
|
s<<"\""<<val<<"\""; |
||||||
|
else |
||||||
|
s<<val; |
||||||
|
return s.str(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// Simple objects
|
||||||
|
typedef ObjectSimple<bool> ObjectBool; |
||||||
|
typedef ObjectSimple<int64_t> ObjectInt; |
||||||
|
typedef ObjectSimple<double> ObjectReal; |
||||||
|
typedef ObjectSimple<std::string> ObjectString; |
||||||
|
|
||||||
|
template<> |
||||||
|
inline const int8_t* ObjectSimple<std::string>::Blob(size_t* size) const |
||||||
|
{ |
||||||
|
*size=val.length(); |
||||||
|
return reinterpret_cast<const int8_t*>(val.c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
// Class for name-value pair
|
||||||
|
class ObjectPair: public ObjectBase |
||||||
|
{ |
||||||
|
private: |
||||||
|
std::string name; |
||||||
|
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;} |
||||||
|
|
||||||
|
bool Print() const override |
||||||
|
{ |
||||||
|
if(!Exist()) return false; |
||||||
|
COUT(INFO)<<"Object type: "<<Type()<<"."<<std::endl; |
||||||
|
COUT(INFO)<<"Name: "<<Name()<<std::endl; |
||||||
|
COUT(INFO)<<"Value type: "<<val->Type()<<std::endl; |
||||||
|
return true; |
||||||
|
} |
||||||
|
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;}} |
||||||
|
std::string Dump() const override { return Name()+"="+val->Dump(); } |
||||||
|
}; |
||||||
|
|
||||||
|
// Class for objects list
|
||||||
|
class ObjectList: public ObjectBase |
||||||
|
{ |
||||||
|
private: |
||||||
|
std::list<ObjectBase*> vals; |
||||||
|
|
||||||
|
public: |
||||||
|
ObjectList() {} |
||||||
|
ObjectList(ObjectBase* o) {PushBack(o);} |
||||||
|
~ObjectList() |
||||||
|
{ |
||||||
|
for(auto& i: vals) delete i; |
||||||
|
vals.clear(); |
||||||
|
} |
||||||
|
bool Exist() const {return 0==vals.size();} |
||||||
|
|
||||||
|
bool Print() const override |
||||||
|
{ |
||||||
|
if(!Exist()) return false; |
||||||
|
COUT(INFO)<<"Object type: "<<Type()<<"."<<std::endl; |
||||||
|
COUT(INFO)<<"Number of elements: "<<Size()<<std::endl; |
||||||
|
return true; |
||||||
|
} |
||||||
|
std::list<ObjectBase*>::size_type Size() const {return vals.size();} |
||||||
|
std::string Type() const override {return "list";} |
||||||
|
ObjectList* PushFront(ObjectBase* p) {vals.push_front(p); return this;} |
||||||
|
ObjectList* PushBack(ObjectBase* p) {vals.push_back(p); return this;} |
||||||
|
std::string Dump() const override |
||||||
|
{ |
||||||
|
std::string s("("); |
||||||
|
for(auto& i: vals) s+=i->Dump()+", "; |
||||||
|
if(vals.size()!=0) s.resize(s.length()-2); |
||||||
|
return s+")"; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// Class for storing identifiers
|
||||||
|
class OId: public ObjectBase |
||||||
|
{ |
||||||
|
std::string name; |
||||||
|
public: |
||||||
|
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) {name=s;} |
||||||
|
std::string Dump() const override {return Name();}; |
||||||
|
}; |
||||||
|
|
||||||
|
// Class for storing functions
|
||||||
|
class OFunc: public ObjectBase |
||||||
|
{ |
||||||
|
std::string name; |
||||||
|
ObjectList* args; |
||||||
|
public: |
||||||
|
OFunc(const std::string* t, ObjectBase* p):name(*t) |
||||||
|
{ |
||||||
|
if(IS_OTYPE(p,ObjectList)) args=dynamic_cast<ObjectList*>(p); |
||||||
|
else args=new ObjectList(p); |
||||||
|
} |
||||||
|
OFunc(const char* t, ObjectBase* p):name(t) |
||||||
|
{ |
||||||
|
if(IS_OTYPE(p,ObjectList)) args=dynamic_cast<ObjectList*>(p); |
||||||
|
else args=new ObjectList(p); |
||||||
|
} |
||||||
|
~OFunc() {if(args!=0) delete args;} |
||||||
|
bool Print() const override {return false;} |
||||||
|
std::string Type() const override {return "FUNC";} |
||||||
|
std::string Name() const {return name;} |
||||||
|
void SetName(std::string s) {name=s;} |
||||||
|
std::string Dump() const override {return Name()+args->Dump();}; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,107 @@ |
|||||||
|
%name-prefix "conf" |
||||||
|
%language "c" |
||||||
|
%output "grammatical.cpp" |
||||||
|
%defines "grammatical.h" |
||||||
|
%param {yyscan_t scanner} |
||||||
|
%define api.pure full |
||||||
|
%define parse.lac full |
||||||
|
%locations |
||||||
|
//%no-lines |
||||||
|
|
||||||
|
%{ |
||||||
|
#include <inttypes.h> |
||||||
|
#include <algorithm> |
||||||
|
#include "parser.h" |
||||||
|
#include "../debug.h" |
||||||
|
#include "../object.h" |
||||||
|
#include "../globals.h" |
||||||
|
#ifndef YY_TYPEDEF_YY_SCANNER_T |
||||||
|
#define YY_TYPEDEF_YY_SCANNER_T |
||||||
|
typedef void* yyscan_t; |
||||||
|
#endif |
||||||
|
#include "yyloc.h" |
||||||
|
#include "grammatical.h" |
||||||
|
inline void conferror(YYLTYPE *locp, yyscan_t sc, const char * str) |
||||||
|
{ |
||||||
|
COUT(ERROR)<<str<<std::endl; |
||||||
|
} |
||||||
|
#include "lexical.h" |
||||||
|
%} |
||||||
|
|
||||||
|
%union |
||||||
|
{ |
||||||
|
bool b; |
||||||
|
int64_t i; |
||||||
|
double r; |
||||||
|
std::string* str; |
||||||
|
ObjectBase* ob; |
||||||
|
} |
||||||
|
|
||||||
|
%token ASSIGN OBRACE CBRACE ENDL |
||||||
|
|
||||||
|
%token <r> REAL |
||||||
|
%token <b> BOOL |
||||||
|
%token <i> INTEGER |
||||||
|
%token <str> NAME |
||||||
|
%token <str> IDENTIFIER |
||||||
|
%token <str> STRING |
||||||
|
|
||||||
|
%left '-' '+' |
||||||
|
%left '*' '/' |
||||||
|
%precedence UNARY /* negation--unary minus */ |
||||||
|
%right '^' /* exponentiation */ |
||||||
|
|
||||||
|
%type <ob> expression |
||||||
|
%type <ob> call |
||||||
|
%type <ob> object |
||||||
|
%type <ob> pair |
||||||
|
%type <ob> list |
||||||
|
%% |
||||||
|
input: |
||||||
|
%empty {COUT(DEBUG)<<"Empty input\n";} |
||||||
|
| input line {COUT(DEBUG)<<" input line\n";} |
||||||
|
; |
||||||
|
|
||||||
|
line: |
||||||
|
NAME ASSIGN object ENDL {COUT(DEBUG)<<" NAME ASSIGN object ENDL\n"; if(G_vars.count(*$1)!=0) delete G_vars[*$1]; G_vars[*$1]=$3; delete $1;} |
||||||
|
| NAME ASSIGN list ENDL {COUT(DEBUG)<<" NAME ASSIGN list ENDL\n"; if(G_vars.count(*$1)!=0) delete G_vars[*$1]; G_vars[*$1]=$3; delete $1;} |
||||||
|
| NAME OBRACE list CBRACE ENDL {COUT(DEBUG)<<" NAME OBRACE list CBRACE ENDL\n"; transform($1->begin(),$1->end(),$1->begin(),::tolower); if(*$1=="save") G_tosave.push_back($3); if(*$1=="print") G_toprint.push_back($3); delete $1;} |
||||||
|
| NAME OBRACE object CBRACE ENDL {COUT(DEBUG)<<" NAME OBRACE object CBRACE ENDL\n"; transform($1->begin(),$1->end(),$1->begin(),::tolower); if(*$1=="save") G_tosave.push_back($3); if(*$1=="print") G_toprint.push_back($3); delete $1;} |
||||||
|
; |
||||||
|
|
||||||
|
list: |
||||||
|
object object {COUT(DEBUG)<<" object object\n"; $$=(new ObjectList($1))->PushBack($2);} |
||||||
|
| list object {COUT(DEBUG)<<" list object\n"; dynamic_cast<ObjectList*>($1)->PushBack($2); $$=$1;} |
||||||
|
; |
||||||
|
|
||||||
|
pair: |
||||||
|
IDENTIFIER ASSIGN object {COUT(DEBUG)<<" IDENTIFIER ASSIGN object\n"; $$=new ObjectPair($1,$3);} |
||||||
|
; |
||||||
|
|
||||||
|
object: |
||||||
|
STRING {COUT(DEBUG)<<" STRING\n"; $$=new ObjectString($1);} |
||||||
|
| BOOL {COUT(DEBUG)<<" BOOL\n"; $$=new ObjectBool($1);} |
||||||
|
| OBRACE list CBRACE {COUT(DEBUG)<<" OBRACE list CBRACE\n"; $$=$2;} |
||||||
|
| expression {COUT(DEBUG)<<" expression\n"; $$=$1;} |
||||||
|
| pair {COUT(DEBUG)<<" pair\n"; $$=$1;} |
||||||
|
| OBRACE object CBRACE {COUT(DEBUG)<<" OBRACE object CBRACE\n"; $$=$2;} |
||||||
|
; |
||||||
|
|
||||||
|
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;} |
||||||
|
|
||||||
|
expression: |
||||||
|
IDENTIFIER {COUT(DEBUG)<<" IDENTIFIER\n"; $$=new OId($1); delete $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));} |
||||||
|
| expression '+' expression {COUT(DEBUG)<<" +\n"; $$=new OFunc("ADD",(new ObjectList($1))->PushBack($3));} |
||||||
|
| expression '/' expression {COUT(DEBUG)<<" /\n"; $$=new OFunc("DIV",(new ObjectList($1))->PushBack($3));} |
||||||
|
| expression '*' expression {COUT(DEBUG)<<" *\n"; $$=new OFunc("MUL",(new ObjectList($1))->PushBack($3));} |
||||||
|
| expression '^' expression {COUT(DEBUG)<<" ^\n"; $$=new OFunc("POW",(new ObjectList($1))->PushBack($3));} |
||||||
|
| '-' expression %prec UNARY {COUT(DEBUG)<<" unary -\n"; $$=new OFunc("NEG",$2);} |
||||||
|
| '+' expression %prec UNARY {COUT(DEBUG)<<" unary +\n"; $$=new OFunc("POS",$2);} |
||||||
|
| OBRACE expression CBRACE {COUT(DEBUG)<<" OBRACE expression CBRACE\n"; $$=$2;} |
||||||
|
| call {COUT(DEBUG)<<" call\n"; $$=$1;} |
||||||
|
; |
@ -0,0 +1,19 @@ |
|||||||
|
#ifndef PARSER_YYLOC_H |
||||||
|
#define PARSER_YYLOC_H |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED |
||||||
|
typedef struct YYLTYPE |
||||||
|
{ |
||||||
|
int first_line; |
||||||
|
int first_column; |
||||||
|
int last_line; |
||||||
|
int last_column; |
||||||
|
std::string filename; |
||||||
|
std::string token_type; |
||||||
|
std::string token_value; |
||||||
|
} YYLTYPE; |
||||||
|
#define YYLTYPE_IS_DECLARED 1 |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue