%language "c"
%output "grammatical.cpp"
%defines "grammatical.h"
%param {yyscan_t scanner}
%define api.prefix {conf}
%define api.pure full
%define lr.type ielr
%define parse.lac full
%define parse.error verbose
//%define parse.trace
%locations
//%no-lines
// Get name of initial parsed file
%initial-action {@$.filename=confget_extra(scanner)->state.curdir+confget_extra(scanner)->state.filename;}
%{
#include <inttypes.h>
#include <algorithm>
#include "parser.h"
#include "../debug.h"
#include "../object.h"
#include "../globals.h"
// We can't include lexical.h before grammatical.h, because of strange errors, but grammatical.h only needs definition of yyscan_t
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
#include "grammatical.h"
#include "lexical.h"
inline void conferror(const YYLTYPE* locp, yyscan_t sc, const char* str)
{
COUT(ERROR)<<std::endl<<" Grammatical parser: "<<str<<std::endl<<" in file "<<locp->filename;
if(locp->first_line==locp->last_line) COUT(ERROR)<<" at line "<<locp->last_line<<", from position "<<locp->first_column<<" to "<<locp->last_column<<std::endl;
else COUT(ERROR)<<" from line "<<locp->first_line<<", position "<<locp->first_column<<" to line "<<locp->last_line<<", position "<<locp->last_column<<std::endl;
}
inline void conferror(const YYLTYPE& locp, yyscan_t sc, const std::string& str)
{
conferror(&locp,sc,str.c_str());
}
%}
%union
{
bool b;
int64_t i;
double r;
std::string* str;
ObjectBase* ob;
}
%token ASSIGN OBRACE CBRACE ENDL DELIM
%token <r> REAL
%token <b> BOOL
%token <i> INTEGER
%token <str> NAME
%token <str> IDENTIFIER
%token <str> STRING
%left DELIM
%precedence ASSIGN
%precedence IDENTIFIER /* low-priority for just identifier */
%left '-' '+'
%left '*' '/'
%precedence UNARY /* negation--unary minus */
%right '^' /* exponentiation */
%left '.'
%precedence OBRACE CBRACE
%type <ob> longidentifier
%type <ob> expression
%type <ob> object
%type <ob> pair
%type <ob> list
%destructor {} REAL INTEGER BOOL
%destructor {delete $$;} <*>
%%
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);
ObjectList* ol=dynamic_cast<ObjectList*>($3);
if(*$1=="save") G_tosave.push_back(ol);
else if(*$1=="print") G_toprint.push_back(ol);
else
{
conferror(@1,scanner,"unknown statement "+(*$1));
delete ol;
delete $1;
YYABORT;
}
delete $1;}
| NAME OBRACE object CBRACE ENDL {COUT(DEBUG)<<" NAME OBRACE object CBRACE ENDL\n";
transform($1->begin(),$1->end(),$1->begin(),::tolower);
ObjectList* ol=new ObjectList($3);
if(*$1=="save") G_tosave.push_back(ol);
else if(*$1=="print") G_toprint.push_back(ol);
else
{
conferror(@1,scanner,"unknown statement "+(*$1));
delete ol;
delete $1;
YYABORT;
}
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); delete $1;}
;
object:
STRING {COUT(DEBUG)<<" STRING\n"; $$=new ObjectString($1); delete $1;}
| BOOL {COUT(DEBUG)<<" BOOL\n"; $$=new ObjectBool($1);}
| OBRACE list CBRACE {COUT(DEBUG)<<" OBRACE list CBRACE\n"; $$=$2;}
| expression %prec ASSIGN {COUT(DEBUG)<<" expression\n"; $$=$1;}
| pair {COUT(DEBUG)<<" pair\n"; $$=$1;}
| OBRACE object CBRACE {COUT(DEBUG)<<" OBRACE object CBRACE\n"; $$=$2;}
| object DELIM {COUT(DEBUG)<<" OBJECT DELIM\n"; $$=$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;}
| 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 {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));}
| 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;}
;