Michael Uleysky
9 years ago
13 changed files with 482 additions and 35 deletions
@ -1,21 +1,33 @@
|
||||
CFLAGS=-O2 -g
|
||||
|
||||
OBJECTS=main.o debug.o init.o parser/lexical.o
|
||||
CFLAGS=-O2 -g -std=gnu++11
|
||||
LDFLAGS=
|
||||
|
||||
CC=g++
|
||||
|
||||
SOURCE = $(wildcard *.cpp) parser/lexical.cpp parser/grammatical.cpp
|
||||
DEPENDS = $(subst .cpp,.d,$(SOURCE))
|
||||
OBJECTS = $(subst .cpp,.o,$(SOURCE))
|
||||
|
||||
makemap: $(OBJECTS) |
||||
g++ $(CFLAGS) -o $@ $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJECTS)
|
||||
|
||||
include $(DEPENDS) |
||||
|
||||
%.o: %.cpp |
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
main.o: debug.h init.h |
||||
init.o: parser/lexical.h parser/parser.h debug.h init.h |
||||
parser/lexical.o: parser/parser.h debug.h |
||||
%.d: %.cpp |
||||
$(CC) $(CFLAGS) -MM -MT $(subst .cpp,.o,$<) $< | sed 's%\(^.*\):%\1 $@ :%g' >$@
|
||||
|
||||
parser/grammatical.d: parser/lexical.h |
||||
|
||||
parser/lexical.h parser/lexical.cpp: parser/lexical.l |
||||
cd parser && flex lexical.l
|
||||
|
||||
parser/grammatical.h parser/grammatical.cpp: parser/grammatical.y |
||||
cd parser && bison grammatical.y
|
||||
|
||||
clean: |
||||
rm -f *.o parser/*.o parser/lexical.{cpp,h}
|
||||
rm -f *.o *.d parser/*.{o,d} parser/{lexical,grammatical}.{cpp,h}
|
||||
|
||||
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 "init.h" |
||||
#include "globals.h" |
||||
|
||||
int main(int argc, char** argv) |
||||
{ |
||||
if(argc!=2) return 1; |
||||
|
||||
SetDebugLevel(DEBUG); |
||||
SetDebugLevel(INFO); |
||||
|
||||
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; |
||||
} |
||||
|
@ -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