Merge pull request #79 from Servostar/68-generate-ast-from-parser-rules

68 generate ast from parser rules
This commit is contained in:
Filleo 2024-05-15 21:37:54 +02:00 committed by GitHub
commit a3e3e25e18
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 494 additions and 160 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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
};

View File

@ -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 */ };
%%

View File

@ -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;
}

View File

@ -1,9 +1,12 @@
%locations
%define parse.error verbose
%{
%code requires {
#include <sys/log.h>
#include <ast/ast.h>
#include <sys/col.h>
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 <node_ptr> operation
%type <node_ptr> boxaccess
%type <node_ptr> boxselfaccess
%type <node_ptr> statement
%type <node_ptr> statementlist
%type <node_ptr> assign
%type <node_ptr> oparith
%type <node_ptr> decl
%type <node_ptr> definition
%type <node_ptr> while
%type <node_ptr> funcall
%type <node_ptr> boxcall
%type <node_ptr> branchhalf
%type <node_ptr> branchfull
%type <node_ptr> branchelse
%type <node_ptr> branchelseif
%type <node_ptr> branchif
%type <node_ptr> type
%type <node_ptr> identlist
%type <node_ptr> storagequalifier
%type <node_ptr> typekind
%type <node_ptr> scale
%type <node_ptr> sign
%type <node_ptr> expr
%type <node_ptr> oplogic
%type <node_ptr> opbool
%type <node_ptr> opbit
%type <node_ptr> moduleimport
%type <node_ptr> programbody
%type <node_ptr> fundef
%type <node_ptr> box
%type <node_ptr> typedef
%type <node_ptr> exprlist
%type <node_ptr> argumentlist
%type <node_ptr> paramlist
%type <node_ptr> params
%type <node_ptr> IOqualifyier
%type <node_ptr> paramdecl
%type <node_ptr> boxbody
%type <node_ptr> boxcontent
%type <node_ptr> 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;};
%%

View File

@ -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