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) set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c)
add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE} 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} ARGS -Wno-yacc -Wcounterexamples -d -o ${YACC_GENERATED_SOURCE_FILE} ${YACC_SOURCE_FILE}
COMMENT "generate C source file for parser" COMMENT "generate C source file for parser"
VERBATIM) VERBATIM)

View File

@ -33,8 +33,8 @@ void AST_init() {
DEBUG("initializing global syntax tree..."); DEBUG("initializing global syntax tree...");
INFO("filling lookup table..."); INFO("filling lookup table...");
lookup_table[AST_Stmt] = "stmt"; lookup_table[AST_Stmt] = "stmt";
lookup_table[AST_Module] = "module";
lookup_table[AST_Expr] = "expr"; lookup_table[AST_Expr] = "expr";
lookup_table[AST_Add] = "+"; lookup_table[AST_Add] = "+";
@ -69,9 +69,20 @@ void AST_init() {
lookup_table[AST_Box] = "box"; lookup_table[AST_Box] = "box";
lookup_table[AST_Fun] = "fun"; lookup_table[AST_Fun] = "fun";
lookup_table[AST_Call] = "funcall";
lookup_table[AST_Typecast] = "cast"; lookup_table[AST_Typecast] = "cast";
lookup_table[AST_Transmute] = "as"; lookup_table[AST_Transmute] = "as";
lookup_table[AST_Condition] = "condition"; 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) { 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_Ident:
case AST_Macro: case AST_Macro:
case AST_Import: case AST_Import:
case AST_Call: case AST_Storage:
case AST_Typekind:
case AST_Sign:
case AST_Scale:
case AST_Qualifyier:
string = node->value; string = node->value;
break; break;
default: default:

View File

@ -12,6 +12,7 @@
*/ */
enum AST_SyntaxElement_t { enum AST_SyntaxElement_t {
AST_Stmt = 0, AST_Stmt = 0,
AST_Module,
AST_Expr, AST_Expr,
// Literals // Literals
AST_Int, AST_Int,
@ -58,7 +59,22 @@ enum AST_SyntaxElement_t {
AST_Fun, AST_Fun,
AST_Import, AST_Import,
// amount of variants // 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 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]+ {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);}; [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); }; [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 */ }; [ \r\t] { /* ignore whitespace */ };
. { return yytext[0]; /* passthrough unknown token, let parser handle the error */ }; . { return yytext[0]; /* passthrough unknown token, let parser handle the error */ };
%% %%

View File

@ -7,6 +7,9 @@
#define LOG_LEVEL LOG_LEVEL_DEBUG #define LOG_LEVEL LOG_LEVEL_DEBUG
extern FILE *yyin;
AST_NODE_PTR root;
/** /**
* @brief Log a debug message to inform about beginning exit procedures * @brief Log a debug message to inform about beginning exit procedures
* *
@ -69,7 +72,12 @@ int main(int argc, char *argv[]) {
} }
yyin = file; yyin = file;
root = AST_new_node(AST_Module, NULL);
yyparse(); yyparse();
FILE *output = fopen("test.txt", "w");
AST_fprint_graphviz(output, root);
fclose(output);
AST_delete_node(root);
return 0; return 0;
} }

View File

@ -1,9 +1,12 @@
%locations %locations
%define parse.error verbose %define parse.error verbose
%{ %code requires {
#include <sys/log.h> #include <sys/log.h>
#include <ast/ast.h>
#include <sys/col.h> #include <sys/col.h>
extern int yylineno;
int yyerror(const char*); int yyerror(const char*);
@ -11,12 +14,58 @@
extern int yylineno; extern int yylineno;
extern int yylex(); extern int yylex();
%} extern AST_NODE_PTR root;
}
%union { %union {
char *string; 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 KeyInt
%token KeyFloat %token KeyFloat
%token KeySelf %token KeySelf
@ -64,169 +113,388 @@
%token Invalid %token Invalid
/* Operator associativity */ /* Operator associativity */
/* Operators at lower line number have lower precedence */
/* Operators in same line have same precedence */
%right '=' %right '='
%left '+' '-' '*' '/' %left OpOr
%left OpEquals OpNot '<' '>' %left OpXor
%left OpAnd OpOr OpXor %left OpAnd
%left OpBitand OpBitor OpBitxor OpBitnot %left OpBitor
%left OpBitxor
%left OpBitand
%left OpEquals '<' '>'
%left '+' '-'
%left '*' '/'
%left OpNot OpBitnot
%% %%
program: program programbody program: program programbody {AST_push_node(root, $2);}
| programbody; | programbody {AST_push_node(root, $1);};
programbody: moduleimport programbody: moduleimport {$$ = $1;}
| fundef | fundef{$$ = $1;}
| box | box{$$ = $1;}
| definition | definition{$$ = $1;}
| decl | decl{$$ = $1;}
| typedef; | typedef{$$ = $1;};
expr: ValFloat expr: ValFloat {$$ = AST_new_node(AST_Float, $1);}
| ValInt | ValInt {$$ = AST_new_node(AST_Int, $1);}
| ValMultistr | ValMultistr {$$ = AST_new_node(AST_String, $1);}
| ValStr | ValStr {$$ = AST_new_node(AST_String, $1);}
| Ident | Ident {$$ = AST_new_node(AST_Ident, $1);}
| operation | operation {$$ = $1;}
| boxaccess | boxaccess {$$ = $1;}
| boxselfaccess; | boxselfaccess{$$ = $1;};
exprlist: expr ',' exprlist exprlist: expr ',' exprlist {AST_push_node($3, $1);
| expr; $$ = $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: paramlist '(' params ')' {AST_push_node($1, $3);
| paramlist '(' ')' $$ = $1;}
| '(' params ')' | 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 params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL);
| IOqualifyier paramdecl; 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 IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
| KeyOut AST_NODE_PTR list = AST_new_node(AST_List, NULL);
| KeyIn KeyOut AST_push_node(list, in);
| KeyOut KeyIn $$ = 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"); } box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(AST_Box, NULL);
| KeyType KeyBox ':' Ident '{' '}'; 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 boxbody: boxbody boxcontent {AST_push_node($1, $2);
| boxcontent; $$ = $1;}
| boxcontent {AST_NODE_PTR list = AST_new_node(AST_List, NULL);
AST_push_node(list, $1);
$$ = list;};
boxcontent: decl { DEBUG("Box decl Content"); } boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); }
| definition { DEBUG("Box def Content"); } | definition { $$ = $1;DEBUG("Box def Content"); }
| fundef { DEBUG("Box fun Content"); }; | fundef { $$ = $1;DEBUG("Box fun Content"); };
boxselfaccess: KeySelf '.' Ident boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL);
| KeySelf '.' boxaccess; 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 boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL);
| Ident '.' boxaccess; 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 boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL);
| boxselfaccess argumentlist; 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 statementlist: statementlist statement {AST_push_node($1, $2);
| statement; $$ = $1;}
| statement {AST_NODE_PTR list = AST_new_node(AST_StmtList, NULL);
AST_push_node(list, $1);
$$ = list;};
statement: assign statement: assign {$$ = $1;}
| decl | decl {$$ = $1;}
| definition | definition {$$ = $1;}
| while | while {$$ = $1;}
| branch | branchfull {$$ = $1;}
| funcall | funcall {$$ = $1;}
| boxcall; | boxcall{$$ = $1;};
branchif: KeyIf expr '{' statementlist '}' { DEBUG("if"); }; branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_If, NULL);
branchelse: KeyElse '{' statementlist '}' { DEBUG("if-else"); }; AST_push_node(branch, $2);
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { DEBUG("else-if"); }; AST_push_node(branch, $4);
$$ = branch; };
branchelseifs: branchelseifs branchelseif branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_Else, NULL);
| branchelseif; AST_push_node(branch, $3);
$$ = branch; };
branch: branchif branchelseifs branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_IfElse, NULL);
| branchif branchelseifs branchelse; AST_push_node(branch, $3);
AST_push_node(branch, $5);
$$ = branch; };
while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; branchfull: branchhalf { $$ = $1;};
|branchhalf branchelse { AST_push_node($1 , $2);
identlist: Ident ',' identlist $$ = $1; }
| Ident; branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL);
AST_push_node(branch, $1);
decl: type ':' identlist $$ = branch; }
| storagequalifier type ':' identlist | 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 identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
| KeyStatic AST_push_node($3, ident);
| KeyLocal; $$ = $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 | boxaccess '=' expr
| boxselfaccess '=' expr ; | boxselfaccess '=' expr ;
sign: KeySigned sign: KeySigned {$$ = AST_new_node(AST_Sign, "signed");}
| KeyUnsigned; | 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: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short");
| scale KeyHalf AST_push_node($1, shortnode);
| scale KeyLong $$ = $1;}
| scale KeyDouble | scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half");
| KeyShort AST_push_node($1, shortnode);
| KeyHalf $$ = $1;}
| KeyLong | scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long");
| KeyDouble; 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 typekind: Ident {$$ = AST_new_node(AST_Typekind, $1);}
| KeyInt | KeyInt {$$ = AST_new_node(AST_Typekind, "int");}
| KeyFloat; | KeyFloat {$$ = AST_new_node(AST_Typekind, "float");};
type: typekind type: typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
| scale typekind AST_push_node(type, $1);
| sign typekind $$ = type;}
| sign scale typekind; | 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 operation: oparith {$$ = $1;}
| oplogic | oplogic {$$ = $1;}
| opbool | opbool {$$ = $1;}
| opbit; | opbit {$$ = $1;};
oparith: expr '+' expr oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(AST_Add, NULL);
| expr '-' expr AST_push_node(add, $1);
| expr '*' expr AST_push_node(add, $3);
| expr '/' expr $$ = add;}
| '-' expr %prec '*'; | 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 oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(AST_Eq, NULL);
| expr '<' expr AST_push_node(equals, $1);
| expr '>' expr; 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 opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(AST_BoolAnd, NULL);
| expr OpOr expr AST_push_node(and, $1);
| expr OpXor expr AST_push_node(and, $3);
| OpNot expr %prec OpAnd; $$ = 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 opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(AST_BitAnd, NULL);
| expr OpBitor expr AST_push_node(and, $1);
| expr OpBitxor expr AST_push_node(and, $3);
| OpBitnot expr %prec OpBitand; $$ = 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 p.returncode == 0
assert """0 stmt assert """0 stmt
1 expr 1 module
2 value 2 expr
3 value 3 value
4 value 4 value
5 while 5 value
6 if 6 while
7 else if 7 if
8 else 8 else if
9 condition 9 else
10 decl 10 condition
11 assign 11 decl
12 def 12 assign
13 value 13 def
14 + 14 value
15 - 15 +
16 * 16 -
17 / 17 *
18 & 18 /
19 | 19 &
20 ^ 20 |
21 ! 21 ^
22 && 22 !
23 || 23 &&
24 ^^ 24 ||
25 !! 25 ^^
26 == 26 !!
27 > 27 ==
28 < 28 >
29 cast 29 <
30 as 30 cast
31 value 31 as
32 value 32 funcall
33 typedef 33 value
34 box 34 typedef
35 fun 35 box
36 value 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 """ == p.stdout