%locations %define parse.error verbose %code requires { #include #include #include #include extern int yylineno; extern ModuleFile* current_file; int yyerror(const char*); extern char* buffer; extern int yylineno; extern int yylex(); extern AST_NODE_PTR root; #define new_loc() new_location(yylloc.first_line, yylloc.first_column, yylloc.last_line, yylloc.last_column) } %union { char *string; AST_NODE_PTR node_ptr; } %type operation %type boxaccess %type boxselfaccess %type statement %type statementlist %type assign %type oparith %type decl %type definition %type while %type funcall %type boxcall %type branchhalf %type branchfull %type branchelse %type branchelseif %type branchif %type type %type identlist %type storagequalifier %type typekind %type scale %type sign %type expr %type oplogic %type opbool %type opbit %type moduleimport %type programbody %type fundef %type box %type typedef %type exprlist %type argumentlist %type paramlist %type params %type IOqualifyier %type paramdecl %type boxbody %type boxcontent %type typecast %type reinterpretcast %type program %token KeyInt %token KeyFloat %token KeySelf %token KeyAs %token KeyTo %token ValInt %token Ident %token ValFloat %token ValStr %token ValMultistr %token KeyShort %token KeyLong %token KeyHalf %token KeyDouble %token KeySigned %token KeyUnsigned %token KeyRef %token KeyType %token KeyLocal %token KeyGlobal %token KeyStatic %token KeyIf %token KeyElse %token KeyWhile %token KeyIn %token KeyOut %token KeyFun %token OpEquals %token OpAnd %token OpOr %token OpNot %token OpXor %token OpBitand %token OpBitor %token OpBitnot %token OpBitxor %token KeyImport %token KeySilent %token KeyBox %token FunTypeof %token FunSizeof %token FunFilename %token FunFunname %token FunLineno %token FunExtsupport %token Invalid /* Operator associativity */ /* Operators at lower line number have lower precedence */ /* Operators in same line have same precedence */ %right '=' %left OpOr %left OpXor %left OpAnd %left OpBitor %left OpBitxor %left OpBitand %left OpEquals '<' '>' %left '+' '-' %left '*' '/' %left OpNot OpBitnot %left KeyAs KeyTo %left '(' ')' '[' ']' %% program: program programbody {AST_push_node(root, $2);} | programbody {AST_push_node(root, $1);}; programbody: moduleimport {$$ = $1;} | fundef{$$ = $1;} | box{$$ = $1;} | definition{$$ = $1;} | decl{$$ = $1;} | typedef{$$ = $1;}; expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);} | ValInt {$$ = AST_new_node(new_loc(), AST_Int, $1);} | ValMultistr {$$ = AST_new_node(new_loc(), AST_String, $1);} | ValStr {$$ = AST_new_node(new_loc(), AST_String, $1);} | Ident {$$ = AST_new_node(new_loc(), AST_Ident, $1);} | operation {$$ = $1;} | boxaccess {$$ = $1;} | boxselfaccess{$$ = $1;} | typecast{$$ = $1;} | reinterpretcast{$$ = $1;} | '(' expr ')' {$$=$2;} | KeyRef Ident {AST_NODE_PTR addrof = AST_new_node(new_loc(), AST_AddressOf, NULL); AST_push_node(addrof, AST_new_node(new_loc(), AST_Ident, $2)); $$ = addrof;} | expr '[' expr ']' {AST_NODE_PTR deref = AST_new_node(new_loc(), AST_Dereference, NULL); AST_push_node(deref, $1); AST_push_node(deref, $3); $$ = deref;}; exprlist: expr ',' exprlist {AST_push_node($3, $1); $$ = $3;} | expr {AST_NODE_PTR list = AST_new_node(new_loc(), AST_ExprList, NULL); AST_push_node(list, $1); $$ = list;}; argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3); $$ = $1;} | '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(new_loc(), AST_ArgList, NULL); AST_push_node(list, $2); $$ = list;} | argumentlist '(' ')' | '(' ')'{AST_NODE_PTR list = AST_new_node(new_loc(), AST_ArgList, NULL); $$ = list;}; fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2); AST_push_node(fun, ident); AST_push_node(fun, $3); AST_push_node(fun, $5); $$ = fun; DEBUG("Function");}; paramlist: paramlist '(' params ')' {AST_push_node($1, $3); $$ = $1;} | paramlist '(' ')'{$$ = $1;} | '(' params ')' {AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL); AST_push_node(list, $2); $$ = list;} | '(' ')' {$$ = AST_new_node(new_loc(), AST_List, NULL);}; params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(new_loc(), AST_Parameter, NULL); AST_push_node(parameter, $1); AST_push_node(parameter, $2); AST_push_node($4, parameter); $$ = $4;} | IOqualifyier paramdecl {AST_NODE_PTR list = AST_new_node(new_loc(), AST_ParamList, NULL); AST_NODE_PTR parameter = AST_new_node(new_loc(), AST_Parameter, NULL); AST_push_node(parameter, $1); AST_push_node(parameter, $2); AST_push_node(list, parameter); $$ = list;}; IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in"); AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL); AST_push_node(list, in); $$ = list;} | KeyOut{ AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out"); AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL); AST_push_node(list, out); $$ = list;} | KeyIn KeyOut{ AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in"); AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out"); AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL); AST_push_node(list, in); AST_push_node(list, out); $$ = list;} | KeyOut KeyIn{ AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in"); AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out"); AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL); AST_push_node(list, in); AST_push_node(list, out); $$ = list;} | {$$ = AST_new_node(new_loc(), AST_List, NULL);}; paramdecl: type ':' Ident { AST_NODE_PTR paramdecl = AST_new_node(new_loc(), AST_ParamDecl, NULL); AST_push_node(paramdecl, $1); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $3); AST_push_node(paramdecl, ident); $$ = paramdecl; DEBUG("Param-Declaration"); }; box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(new_loc(), AST_Box, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4); AST_push_node(box, ident); AST_push_node(box, $6); $$ = box; DEBUG("Box"); } | KeyType KeyBox ':' Ident '{' '}' {AST_NODE_PTR box = AST_new_node(new_loc(), AST_Box, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4); AST_push_node(box, ident); $$ = box;}; boxbody: boxbody boxcontent {AST_push_node($1, $2); $$ = $1;} | boxcontent {AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL); AST_push_node(list, $1); $$ = list;}; boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); } | definition { $$ = $1;DEBUG("Box def Content"); } | fundef { $$ = $1;DEBUG("Box fun Content"); }; boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(new_loc(), AST_List, NULL); AST_NODE_PTR self = AST_new_node(new_loc(), AST_Ident, "self"); AST_push_node(boxselfaccess, self); AST_NODE_PTR identlist = AST_new_node(new_loc(), AST_IdentList, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $3); AST_push_node(identlist,ident); AST_push_node(boxselfaccess, identlist); $$ = boxselfaccess;} | KeySelf '.' boxaccess {AST_NODE_PTR boxselfaccess = AST_new_node(new_loc(), AST_List, NULL); AST_NODE_PTR self = AST_new_node(new_loc(), AST_Ident, "self"); AST_push_node(boxselfaccess, self); AST_push_node(boxselfaccess, $3); $$ = boxselfaccess;}; boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(new_loc(), AST_IdentList, NULL); AST_NODE_PTR ident1 = AST_new_node(new_loc(), AST_Ident, $1); AST_NODE_PTR ident2 = AST_new_node(new_loc(), AST_Ident, $3); AST_push_node(identlist,ident1); AST_push_node(identlist,ident2); $$ = identlist;} | Ident '.' boxaccess {AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1); AST_push_node($3,ident); $$ = $3;}; boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(new_loc(), AST_Call, NULL); AST_push_node(boxcall, $1); AST_push_node(boxcall, $2); $$ = boxcall;} | boxselfaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(new_loc(), AST_Call, NULL); AST_push_node(boxcall, $1); AST_push_node(boxcall, $2); $$ = boxcall;}; typecast: expr KeyAs type %prec KeyAs {AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Typecast, NULL); AST_push_node(cast, $1); AST_push_node(cast, $3); $$ = cast; DEBUG("Type-Cast"); }; reinterpretcast: expr KeyTo type %prec KeyTo { AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Transmute, NULL); AST_push_node(cast, $1); AST_push_node(cast, $3); $$ = cast; DEBUG("Reinterpret-Cast"); }; funcall: Ident argumentlist {AST_NODE_PTR funcall = AST_new_node(new_loc(), AST_Call, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1); AST_push_node(funcall, ident); AST_push_node(funcall, $2); $$ = funcall; DEBUG("Function call"); }; moduleimport: KeyImport ValStr {$$ = AST_new_node(new_loc(), AST_Import, $2); DEBUG("Module-Import"); }; statementlist: statementlist statement {AST_push_node($1, $2); $$ = $1;} | statement {AST_NODE_PTR list = AST_new_node(new_loc(), AST_StmtList, NULL); AST_push_node(list, $1); $$ = list;}; statement: assign {$$ = $1;} | decl {$$ = $1;} | definition {$$ = $1;} | while {$$ = $1;} | branchfull {$$ = $1;} | funcall {$$ = $1;} | boxcall{$$ = $1;}; branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_If, NULL); AST_push_node(branch, $2); AST_push_node(branch, $4); $$ = branch; }; branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_Else, NULL); AST_push_node(branch, $3); $$ = branch; }; branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_IfElse, NULL); AST_push_node(branch, $3); AST_push_node(branch, $5); $$ = branch; }; branchfull: branchhalf { $$ = $1;}; |branchhalf branchelse { AST_push_node($1 , $2); $$ = $1; } branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_Stmt, NULL); AST_push_node(branch, $1); $$ = branch; } | branchhalf branchelseif { AST_push_node($1 , $2); $$ = $1; }; while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(new_loc(), AST_While, NULL); AST_push_node(whilenode, $2); AST_push_node(whilenode, $4); $$ = whilenode;}; identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1); AST_push_node($3, ident); $$ = $3;} | Ident {AST_NODE_PTR list = AST_new_node(new_loc(), AST_IdentList, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1); AST_push_node(list, ident); $$ = list;}; decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(new_loc(), AST_Decl, NULL); AST_push_node(decl, $1); AST_push_node(decl, $3); $$ = decl;} | storagequalifier type ':' identlist {AST_NODE_PTR decl = AST_new_node(new_loc(), AST_Decl, NULL); AST_push_node(decl, $1); AST_push_node(decl, $2); AST_push_node(decl, $4); $$ = decl;} definition: decl '=' expr { AST_NODE_PTR def = AST_new_node(new_loc(), AST_Def, NULL); AST_push_node(def, $1); AST_push_node(def, $3); $$ = def; DEBUG("Definition"); }; storagequalifier: KeyGlobal {$$ = AST_new_node(new_loc(), AST_Storage, "global");} | KeyStatic {$$ = AST_new_node(new_loc(), AST_Storage, "static");} | KeyLocal {$$ = AST_new_node(new_loc(), AST_Storage, "local");}; assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(new_loc(), AST_Assign, NULL); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1); AST_push_node(assign, ident); AST_push_node(assign, $3); $$ = assign; DEBUG("Assignment"); } | boxaccess '=' expr | boxselfaccess '=' expr ; sign: KeySigned {$$ = AST_new_node(new_loc(), AST_Sign, "signed");} | KeyUnsigned{$$ = AST_new_node(new_loc(), AST_Sign, "unsigned");}; typedef: KeyType type':' Ident {AST_NODE_PTR typeDef = AST_new_node(new_loc(), AST_Typedef, NULL); AST_push_node(typeDef, $2); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4); AST_push_node(typeDef, ident); $$ = typeDef;}; scale: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "short"); AST_push_node($1, shortnode); $$ = $1;} | scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "half"); AST_push_node($1, shortnode); $$ = $1;} | scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "long"); AST_push_node($1, shortnode); $$ = $1;} | scale KeyDouble {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "double"); AST_push_node($1, shortnode); $$ = $1;} | KeyShort {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL); AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "short"); AST_push_node(scale, shortnode); $$ = scale;} | KeyHalf {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL); AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "half"); AST_push_node(scale, shortnode); $$ = scale;} | KeyLong {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL); AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "long"); AST_push_node(scale, shortnode); $$ = scale;} | KeyDouble {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL); AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "double"); AST_push_node(scale, shortnode); $$ = scale;}; typekind: Ident {$$ = AST_new_node(new_loc(), AST_Typekind, $1);} | KeyInt {$$ = AST_new_node(new_loc(), AST_Typekind, "int");} | KeyFloat {$$ = AST_new_node(new_loc(), AST_Typekind, "float");}; type: typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL); AST_push_node(type, $1); $$ = type;} | scale typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL); AST_push_node(type, $1); AST_push_node(type, $2); $$ = type;} | sign typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL); AST_push_node(type, $1); AST_push_node(type, $2); $$ = type;} | sign scale typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL); AST_push_node(type, $1); AST_push_node(type, $2); AST_push_node(type, $3); $$ = type;} | KeyRef type {AST_NODE_PTR reftype = AST_new_node(new_loc(), AST_Reference, NULL); AST_push_node(reftype, $2); $$ = reftype; }; operation: oparith {$$ = $1;} | oplogic {$$ = $1;} | opbool {$$ = $1;} | opbit {$$ = $1;}; oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(new_loc(), AST_Add, NULL); AST_push_node(add, $1); AST_push_node(add, $3); $$ = add;} | expr '-' expr {AST_NODE_PTR subtract = AST_new_node(new_loc(), AST_Sub, NULL); AST_push_node(subtract, $1); AST_push_node(subtract, $3); $$ = subtract;} | expr '*' expr {AST_NODE_PTR mul = AST_new_node(new_loc(), AST_Mul, NULL); AST_push_node(mul, $1); AST_push_node(mul, $3); $$ = mul;} | expr '/' expr {AST_NODE_PTR div = AST_new_node(new_loc(), AST_Div, NULL); AST_push_node(div, $1); AST_push_node(div, $3); $$ = div;} | '-' expr %prec '*'{AST_NODE_PTR negator = AST_new_node(new_loc(), AST_Negate, NULL); AST_push_node(negator, $2); $$ = negator;}; oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(new_loc(), AST_Eq, NULL); AST_push_node(equals, $1); AST_push_node(equals, $3); $$ = equals;} | expr '<' expr {AST_NODE_PTR less = AST_new_node(new_loc(), AST_Less, NULL); AST_push_node(less, $1); AST_push_node(less, $3); $$ = less;} | expr '>' expr{AST_NODE_PTR greater = AST_new_node(new_loc(), AST_Greater, NULL); AST_push_node(greater, $1); AST_push_node(greater, $3); $$ = greater;}; opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(new_loc(), AST_BoolAnd, NULL); AST_push_node(and, $1); AST_push_node(and, $3); $$ = and;} | expr OpOr expr{AST_NODE_PTR or = AST_new_node(new_loc(), AST_BoolOr, NULL); AST_push_node(or, $1); AST_push_node(or, $3); $$ = or;} | expr OpXor expr{AST_NODE_PTR xor = AST_new_node(new_loc(), AST_BoolXor, NULL); AST_push_node(xor, $1); AST_push_node(xor, $3); $$ = xor;} | OpNot expr %prec OpAnd{AST_NODE_PTR not = AST_new_node(new_loc(), AST_BoolNot, NULL); AST_push_node(not, $2); $$ = not;}; opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(new_loc(), AST_BitAnd, NULL); AST_push_node(and, $1); AST_push_node(and, $3); $$ = and;} | expr OpBitor expr{AST_NODE_PTR or = AST_new_node(new_loc(), AST_BitOr, NULL); AST_push_node(or, $1); AST_push_node(or, $3); $$ = or;} | expr OpBitxor expr{AST_NODE_PTR xor = AST_new_node(new_loc(), AST_BitXor, NULL); AST_push_node(xor, $1); AST_push_node(xor, $3); $$ = xor;} | OpBitnot expr %prec OpBitand{AST_NODE_PTR not = AST_new_node(new_loc(), AST_BitNot, NULL); AST_push_node(not, $2); $$ = not;}; %% int yyerror(const char *s) { TokenLocation location = new_loc(); print_diagnostic(current_file, &location, Error, s); return 0; }