diff --git a/CMakeLists.txt b/CMakeLists.txt index be613ed..213143c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,10 @@ set(YACC_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.y) set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE} - COMMAND yacc + + COMMAND bison ARGS -Wno-yacc -Wcounterexamples -d -o ${YACC_GENERATED_SOURCE_FILE} ${YACC_SOURCE_FILE} + COMMENT "generate C source file for parser" VERBATIM) diff --git a/src/ast/ast.c b/src/ast/ast.c index 233e8da..e503e1e 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -33,8 +33,8 @@ void AST_init() { DEBUG("initializing global syntax tree..."); INFO("filling lookup table..."); - lookup_table[AST_Stmt] = "stmt"; + lookup_table[AST_Module] = "module"; lookup_table[AST_Expr] = "expr"; lookup_table[AST_Add] = "+"; @@ -69,9 +69,20 @@ void AST_init() { lookup_table[AST_Box] = "box"; lookup_table[AST_Fun] = "fun"; + lookup_table[AST_Call] = "funcall"; lookup_table[AST_Typecast] = "cast"; lookup_table[AST_Transmute] = "as"; lookup_table[AST_Condition] = "condition"; + lookup_table[AST_List] = "list"; + lookup_table[AST_ExprList] = "expr list"; + lookup_table[AST_ArgList] = "arg list"; + lookup_table[AST_ParamList] = "param list"; + lookup_table[AST_StmtList] = "stmt list"; + lookup_table[AST_IdentList] = "ident list"; + lookup_table[AST_Type] = "type"; + lookup_table[AST_Negate] = "-"; + lookup_table[AST_Parameter] = "parameter"; + lookup_table[AST_ParamDecl] = "parameter-declaration"; } const char* AST_node_to_string(const struct AST_Node_t* node) { @@ -87,7 +98,11 @@ const char* AST_node_to_string(const struct AST_Node_t* node) { case AST_Ident: case AST_Macro: case AST_Import: - case AST_Call: + case AST_Storage: + case AST_Typekind: + case AST_Sign: + case AST_Scale: + case AST_Qualifyier: string = node->value; break; default: diff --git a/src/ast/ast.h b/src/ast/ast.h index 5129765..ff8297b 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -12,6 +12,7 @@ */ enum AST_SyntaxElement_t { AST_Stmt = 0, + AST_Module, AST_Expr, // Literals AST_Int, @@ -58,7 +59,22 @@ enum AST_SyntaxElement_t { AST_Fun, AST_Import, // amount of variants - // in this enum + // in this enums + AST_List, + AST_ExprList, + AST_ArgList, + AST_ParamList, + AST_StmtList, + AST_IdentList, + AST_Storage, + AST_Type, + AST_Typekind, + AST_Sign, + AST_Scale, + AST_Negate, + AST_Parameter, + AST_Qualifyier, + AST_ParamDecl, AST_ELEMENT_COUNT }; diff --git a/src/lex/lexer.l b/src/lex/lexer.l index b93499a..7c0cc0c 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -91,8 +91,17 @@ [0-9]+ {DEBUG("\"%s\" tokenized with \'ValInt\'", yytext); yylval.string = strdup(yytext); return(ValInt); }; [0-9]*\.[0-9]+ {DEBUG("\"%s\" tokenized with \'ValFloat\'", yytext); yylval.string = strdup(yytext); return(ValFloat);}; [a-zA-Z_0-9]+ {DEBUG("\"%s\" tokenized with \'Ident\'", yytext); yylval.string = strdup(yytext); return(Ident); }; -\"([^\"\n])*\" {DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);}; -\"\"\"([^\"\n]|\\\n)*\"\"\" {DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);}; + +\"([^\"\n])*\" { + yytext = yytext +1; + yytext[yyleng - 2] = 0; + + DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);}; +\"\"\"([^\"\n]|\\\n)*\"\"\" { + yytext = yytext +3; + yytext[yyleng - 4] = 0; + + DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);}; [ \r\t] { /* ignore whitespace */ }; . { return yytext[0]; /* passthrough unknown token, let parser handle the error */ }; %% diff --git a/src/main.c b/src/main.c index 5f1c8ab..27bca44 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,9 @@ #define LOG_LEVEL LOG_LEVEL_DEBUG +extern FILE *yyin; +AST_NODE_PTR root; + /** * @brief Log a debug message to inform about beginning exit procedures * @@ -69,7 +72,12 @@ int main(int argc, char *argv[]) { } yyin = file; + root = AST_new_node(AST_Module, NULL); yyparse(); + FILE *output = fopen("test.txt", "w"); + AST_fprint_graphviz(output, root); + fclose(output); + AST_delete_node(root); return 0; } diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 19d8aa1..d8bf1a1 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -1,9 +1,12 @@ %locations %define parse.error verbose -%{ +%code requires { #include + #include #include + extern int yylineno; + int yyerror(const char*); @@ -11,12 +14,58 @@ extern int yylineno; extern int yylex(); -%} + extern AST_NODE_PTR root; + +} %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 program + + %token KeyInt %token KeyFloat %token KeySelf @@ -64,169 +113,388 @@ %token Invalid /* Operator associativity */ +/* Operators at lower line number have lower precedence */ +/* Operators in same line have same precedence */ %right '=' -%left '+' '-' '*' '/' -%left OpEquals OpNot '<' '>' -%left OpAnd OpOr OpXor -%left OpBitand OpBitor OpBitxor OpBitnot +%left OpOr +%left OpXor +%left OpAnd +%left OpBitor +%left OpBitxor +%left OpBitand +%left OpEquals '<' '>' +%left '+' '-' +%left '*' '/' +%left OpNot OpBitnot %% -program: program programbody - | programbody; +program: program programbody {AST_push_node(root, $2);} + | programbody {AST_push_node(root, $1);}; -programbody: moduleimport - | fundef - | box - | definition - | decl - | typedef; +programbody: moduleimport {$$ = $1;} + | fundef{$$ = $1;} + | box{$$ = $1;} + | definition{$$ = $1;} + | decl{$$ = $1;} + | typedef{$$ = $1;}; -expr: ValFloat - | ValInt - | ValMultistr - | ValStr - | Ident - | operation - | boxaccess - | boxselfaccess; +expr: ValFloat {$$ = AST_new_node(AST_Float, $1);} + | ValInt {$$ = AST_new_node(AST_Int, $1);} + | ValMultistr {$$ = AST_new_node(AST_String, $1);} + | ValStr {$$ = AST_new_node(AST_String, $1);} + | Ident {$$ = AST_new_node(AST_Ident, $1);} + | operation {$$ = $1;} + | boxaccess {$$ = $1;} + | boxselfaccess{$$ = $1;}; -exprlist: expr ',' exprlist - | expr; +exprlist: expr ',' exprlist {AST_push_node($3, $1); + $$ = $3;} + | expr {AST_NODE_PTR list = AST_new_node(AST_ExprList, NULL); + AST_push_node(list, $1); + $$ = list;}; -argumentlist: argumentlist '(' exprlist ')' - | ; +argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3); + $$ = $1;} + | '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL); + AST_push_node(list, $2); + $$ = list;} + | argumentlist '(' ')' + | '(' ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL); + $$ = list;}; -fundef: KeyFun Ident paramlist '{' statementlist'}' { DEBUG("Function");}; +fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(AST_Fun, NULL); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $2); + AST_push_node(fun, ident); + AST_push_node(fun, $3); + AST_push_node(fun, $5); + $$ = fun; + DEBUG("Function");}; -paramlist: paramlist '(' params ')' - | paramlist '(' ')' - | '(' params ')' - | '(' ')'; +paramlist: paramlist '(' params ')' {AST_push_node($1, $3); + $$ = $1;} + | paramlist '(' ')'{$$ = $1;} + | '(' params ')' {AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, $2); + $$ = list;} + | '(' ')' {$$ = AST_new_node(AST_List, NULL);}; -params: IOqualifyier paramdecl ',' params - | IOqualifyier paramdecl; +params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(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(AST_ParamList, NULL); + AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL); + AST_push_node(parameter, $1); + AST_push_node(parameter, $2); + AST_push_node(list, parameter); + $$ = list;}; -IOqualifyier: KeyIn - | KeyOut - | KeyIn KeyOut - | KeyOut KeyIn - | ; +IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in"); + AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, in); + $$ = list;} + | KeyOut{ AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out"); + AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, out); + $$ = list;} + | KeyIn KeyOut{ AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in"); + AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out"); + AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, in); + AST_push_node(list, out); + $$ = list;} + | KeyOut KeyIn{ AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in"); + AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out"); + AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, in); + AST_push_node(list, out); + $$ = list;} + | {$$ = AST_new_node(AST_List, NULL);}; -paramdecl: type ':' Ident { DEBUG("Param-Declaration"); }; +paramdecl: type ':' Ident { AST_NODE_PTR paramdecl = AST_new_node(AST_ParamDecl, NULL); + AST_push_node(paramdecl, $1); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $3); + AST_push_node(paramdecl, ident); + $$ = paramdecl; + DEBUG("Param-Declaration"); }; -box: KeyType KeyBox ':' Ident '{' boxbody '}' { DEBUG("Box"); } - | KeyType KeyBox ':' Ident '{' '}'; +box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(AST_Box, NULL); + AST_NODE_PTR ident = AST_new_node(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(AST_Box, NULL); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $4); + AST_push_node(box, ident); + $$ = box;}; -boxbody: boxbody boxcontent - | boxcontent; +boxbody: boxbody boxcontent {AST_push_node($1, $2); + $$ = $1;} + | boxcontent {AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, $1); + $$ = list;}; -boxcontent: decl { DEBUG("Box decl Content"); } - | definition { DEBUG("Box def Content"); } - | fundef { DEBUG("Box fun Content"); }; +boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); } + | definition { $$ = $1;DEBUG("Box def Content"); } + | fundef { $$ = $1;DEBUG("Box fun Content"); }; -boxselfaccess: KeySelf '.' Ident - | KeySelf '.' boxaccess; +boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL); + AST_NODE_PTR self = AST_new_node(AST_Ident, "self"); + AST_push_node(boxselfaccess, self); + AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $3); + AST_push_node(identlist,ident); + AST_push_node(boxselfaccess, identlist); + $$ = boxselfaccess;} + | KeySelf '.' boxaccess {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL); + AST_NODE_PTR self = AST_new_node(AST_Ident, "self"); + AST_push_node(boxselfaccess, self); + AST_push_node(boxselfaccess, $3); + $$ = boxselfaccess;}; -boxaccess: Ident '.' Ident - | Ident '.' boxaccess; +boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL); + AST_NODE_PTR ident1 = AST_new_node(AST_Ident, $1); + AST_NODE_PTR ident2 = AST_new_node(AST_Ident, $3); + AST_push_node(identlist,ident1); + AST_push_node(identlist,ident2); + $$ = identlist;} + | Ident '.' boxaccess {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); + AST_push_node($3,ident); + $$ = $3;}; -boxcall: boxaccess argumentlist - | boxselfaccess argumentlist; +boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL); + AST_push_node(boxcall, $1); + AST_push_node(boxcall, $2); + $$ = boxcall;} + | boxselfaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL); + AST_push_node(boxcall, $1); + AST_push_node(boxcall, $2); + $$ = boxcall;}; -funcall: Ident argumentlist { DEBUG("Function call"); }; +funcall: Ident argumentlist {AST_NODE_PTR funcall = AST_new_node(AST_Call, NULL); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); + AST_push_node(funcall, ident); + AST_push_node(funcall, $2); + $$ = funcall; + DEBUG("Function call"); }; -moduleimport: KeyImport ValStr { DEBUG("Module-Import"); }; +moduleimport: KeyImport ValStr {$$ = AST_new_node(AST_Import, $2); + DEBUG("Module-Import"); }; -statementlist: statement statementlist - | statement; +statementlist: statementlist statement {AST_push_node($1, $2); + $$ = $1;} + | statement {AST_NODE_PTR list = AST_new_node(AST_StmtList, NULL); + AST_push_node(list, $1); + $$ = list;}; -statement: assign - | decl - | definition - | while - | branch - | funcall - | boxcall; +statement: assign {$$ = $1;} + | decl {$$ = $1;} + | definition {$$ = $1;} + | while {$$ = $1;} + | branchfull {$$ = $1;} + | funcall {$$ = $1;} + | boxcall{$$ = $1;}; -branchif: KeyIf expr '{' statementlist '}' { DEBUG("if"); }; -branchelse: KeyElse '{' statementlist '}' { DEBUG("if-else"); }; -branchelseif: KeyElse KeyIf expr '{' statementlist '}' { DEBUG("else-if"); }; +branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_If, NULL); + AST_push_node(branch, $2); + AST_push_node(branch, $4); + $$ = branch; }; -branchelseifs: branchelseifs branchelseif - | branchelseif; +branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_Else, NULL); + AST_push_node(branch, $3); + $$ = branch; }; -branch: branchif branchelseifs - | branchif branchelseifs branchelse; +branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_IfElse, NULL); + AST_push_node(branch, $3); + AST_push_node(branch, $5); + $$ = branch; }; -while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; - -identlist: Ident ',' identlist - | Ident; - -decl: type ':' identlist - | storagequalifier type ':' identlist +branchfull: branchhalf { $$ = $1;}; + |branchhalf branchelse { AST_push_node($1 , $2); + $$ = $1; } +branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); + AST_push_node(branch, $1); + $$ = branch; } + | branchhalf branchelseif { AST_push_node($1 , $2); + $$ = $1; }; -definition: decl '=' expr { DEBUG("Definition"); }; +while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(AST_While, NULL); + AST_push_node(whilenode, $2); + AST_push_node(whilenode, $4); + $$ = whilenode;}; -storagequalifier: KeyGlobal - | KeyStatic - | KeyLocal; +identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); + AST_push_node($3, ident); + $$ = $3;} + | Ident {AST_NODE_PTR list = AST_new_node(AST_IdentList, NULL); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); + AST_push_node(list, ident); + $$ = list;}; -assign: Ident '=' expr { DEBUG("Assignment"); } +decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL); + AST_push_node(decl, $1); + AST_push_node(decl, $3); + $$ = decl;} + | storagequalifier type ':' identlist {AST_NODE_PTR decl = AST_new_node(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(AST_Def, NULL); + AST_push_node(def, $1); + AST_push_node(def, $3); + $$ = def; + DEBUG("Definition"); }; + +storagequalifier: KeyGlobal {$$ = AST_new_node(AST_Storage, "global");} + | KeyStatic {$$ = AST_new_node(AST_Storage, "static");} + | KeyLocal {$$ = AST_new_node(AST_Storage, "local");}; + +assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(AST_Assign, NULL); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); + AST_push_node(assign, ident); + AST_push_node(assign, $3); + $$ = assign; + DEBUG("Assignment"); } | boxaccess '=' expr | boxselfaccess '=' expr ; -sign: KeySigned - | KeyUnsigned; +sign: KeySigned {$$ = AST_new_node(AST_Sign, "signed");} + | KeyUnsigned{$$ = AST_new_node(AST_Sign, "unsigned");}; -typedef: KeyType type':' Ident; +typedef: KeyType type':' Ident {AST_NODE_PTR typeDef = AST_new_node(AST_Typedef, NULL); + AST_push_node(typeDef, $2); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $4); + AST_push_node(typeDef, ident); + $$ = typeDef;}; -scale: scale KeyShort - | scale KeyHalf - | scale KeyLong - | scale KeyDouble - | KeyShort - | KeyHalf - | KeyLong - | KeyDouble; +scale: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short"); + AST_push_node($1, shortnode); + $$ = $1;} + | scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half"); + AST_push_node($1, shortnode); + $$ = $1;} + | scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long"); + AST_push_node($1, shortnode); + $$ = $1;} + | scale KeyDouble {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "double"); + AST_push_node($1, shortnode); + $$ = $1;} + | KeyShort {AST_NODE_PTR scale = AST_new_node(AST_List, NULL); + AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short"); + AST_push_node(scale, shortnode); + $$ = scale;} + | KeyHalf {AST_NODE_PTR scale = AST_new_node(AST_List, NULL); + AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half"); + AST_push_node(scale, shortnode); + $$ = scale;} + | KeyLong {AST_NODE_PTR scale = AST_new_node(AST_List, NULL); + AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long"); + AST_push_node(scale, shortnode); + $$ = scale;} + | KeyDouble {AST_NODE_PTR scale = AST_new_node(AST_List, NULL); + AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "double"); + AST_push_node(scale, shortnode); + $$ = scale;}; -typekind: Ident - | KeyInt - | KeyFloat; +typekind: Ident {$$ = AST_new_node(AST_Typekind, $1);} + | KeyInt {$$ = AST_new_node(AST_Typekind, "int");} + | KeyFloat {$$ = AST_new_node(AST_Typekind, "float");}; -type: typekind - | scale typekind - | sign typekind - | sign scale typekind; +type: typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL); + AST_push_node(type, $1); + $$ = type;} + | scale typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL); + AST_push_node(type, $1); + AST_push_node(type, $2); + $$ = type;} + | sign typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL); + AST_push_node(type, $1); + AST_push_node(type, $2); + $$ = type;} + | sign scale typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL); + AST_push_node(type, $1); + AST_push_node(type, $2); + AST_push_node(type, $3); + $$ = type;}; -operation: oparith - | oplogic - | opbool - | opbit; +operation: oparith {$$ = $1;} + | oplogic {$$ = $1;} + | opbool {$$ = $1;} + | opbit {$$ = $1;}; -oparith: expr '+' expr - | expr '-' expr - | expr '*' expr - | expr '/' expr - | '-' expr %prec '*'; +oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(AST_Add, NULL); + AST_push_node(add, $1); + AST_push_node(add, $3); + $$ = add;} + | expr '-' expr {AST_NODE_PTR subtract = AST_new_node(AST_Sub, NULL); + AST_push_node(subtract, $1); + AST_push_node(subtract, $3); + $$ = subtract;} + | expr '*' expr {AST_NODE_PTR mul = AST_new_node(AST_Mul, NULL); + AST_push_node(mul, $1); + AST_push_node(mul, $3); + $$ = mul;} + | expr '/' expr {AST_NODE_PTR div = AST_new_node(AST_Div, NULL); + AST_push_node(div, $1); + AST_push_node(div, $3); + $$ = div;} + | '-' expr %prec '*'{AST_NODE_PTR negator = AST_new_node(AST_Negate, NULL); + AST_push_node(negator, $2); + $$ = negator;}; -oplogic: expr OpEquals expr - | expr '<' expr - | expr '>' expr; +oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(AST_Eq, NULL); + AST_push_node(equals, $1); + AST_push_node(equals, $3); + $$ = equals;} + | expr '<' expr {AST_NODE_PTR less = AST_new_node(AST_Less, NULL); + AST_push_node(less, $1); + AST_push_node(less, $3); + $$ = less;} + | expr '>' expr{AST_NODE_PTR greater = AST_new_node(AST_Greater, NULL); + AST_push_node(greater, $1); + AST_push_node(greater, $3); + $$ = greater;}; -opbool: expr OpAnd expr - | expr OpOr expr - | expr OpXor expr - | OpNot expr %prec OpAnd; +opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(AST_BoolAnd, NULL); + AST_push_node(and, $1); + AST_push_node(and, $3); + $$ = and;} + | expr OpOr expr{AST_NODE_PTR or = AST_new_node(AST_BoolOr, NULL); + AST_push_node(or, $1); + AST_push_node(or, $3); + $$ = or;} + | expr OpXor expr{AST_NODE_PTR xor = AST_new_node(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(AST_BoolNot, NULL); + AST_push_node(not, $2); + $$ = not;}; -opbit: expr OpBitand expr - | expr OpBitor expr - | expr OpBitxor expr - | OpBitnot expr %prec OpBitand; +opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(AST_BitAnd, NULL); + AST_push_node(and, $1); + AST_push_node(and, $3); + $$ = and;} + | expr OpBitor expr{AST_NODE_PTR or = AST_new_node(AST_BitOr, NULL); + AST_push_node(or, $1); + AST_push_node(or, $3); + $$ = or;} + | expr OpBitxor expr{AST_NODE_PTR xor = AST_new_node(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(AST_BitNot, NULL); + AST_push_node(not, $2); + $$ = not;}; %% diff --git a/tests/ast/test_ast.py b/tests/ast/test_ast.py index 0f9b757..28407f9 100644 --- a/tests/ast/test_ast.py +++ b/tests/ast/test_ast.py @@ -29,42 +29,58 @@ def run_check_print_node(): assert p.returncode == 0 assert """0 stmt -1 expr -2 value +1 module +2 expr 3 value 4 value -5 while -6 if -7 else if -8 else -9 condition -10 decl -11 assign -12 def -13 value -14 + -15 - -16 * -17 / -18 & -19 | -20 ^ -21 ! -22 && -23 || -24 ^^ -25 !! -26 == -27 > -28 < -29 cast -30 as -31 value -32 value -33 typedef -34 box -35 fun -36 value +5 value +6 while +7 if +8 else if +9 else +10 condition +11 decl +12 assign +13 def +14 value +15 + +16 - +17 * +18 / +19 & +20 | +21 ^ +22 ! +23 && +24 || +25 ^^ +26 !! +27 == +28 > +29 < +30 cast +31 as +32 funcall +33 value +34 typedef +35 box +36 fun +37 value +38 list +39 expr list +40 arg list +41 param list +42 stmt list +43 ident list +44 value +45 type +46 value +47 value +48 value +49 - +50 parameter +51 value +52 parameter-declaration """ == p.stdout