From bb474d75ad9c1c34a1aac5ae7549304b38f3cc4e Mon Sep 17 00:00:00 2001 From: Filleo Date: Sun, 12 May 2024 23:33:15 +0200 Subject: [PATCH 01/20] start of the syntax tree --- src/ast/ast.c | 1 + src/ast/ast.h | 1 + src/yacc/parser.y | 114 ++++++++++++++++++++++++++++++------------ tests/ast/test_ast.py | 67 +++++++++++++------------ 4 files changed, 117 insertions(+), 66 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 233e8da..b36d191 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -35,6 +35,7 @@ void AST_init() { INFO("filling lookup table..."); lookup_table[AST_Stmt] = "stmt"; + lookup_table[AST_Module] = "module"; lookup_table[AST_Expr] = "expr"; lookup_table[AST_Add] = "+"; diff --git a/src/ast/ast.h b/src/ast/ast.h index 5129765..abd60bc 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, diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 36c5931..0fdffd4 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -1,5 +1,6 @@ %{ #include + #include extern int yylineno; int yyerror(char*); @@ -11,6 +12,29 @@ char *string; } +%type expr +%type operation +%type boxaccess +%type boxselfaccess +%type statement +%type statementlist +%type assign +%type oparith +%type decl +%type definition +%type while +%type branch +%type funcall +%type boxcall +%type branchelseifs +%type branchelse +%type branchelseif +%type branchif +%type type +%type identlist +%type storagequalifier + + %token KeyInt %token KeyFloat %token KeySelf @@ -65,7 +89,8 @@ %% program: program programbody - | programbody; + | programbody {AST_NODE_PTR daineMudda = AST_new_node(AST_Module, NULL); + AST_fprint_graphviz(stdout, daineMudda); }; programbody: moduleimport | fundef @@ -76,17 +101,17 @@ programbody: moduleimport -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; + | expr ; argumentlist: argumentlist '(' exprlist ')' | ; @@ -120,11 +145,11 @@ boxcontent: decl { DEBUG("Box decl Content"); } | definition { DEBUG("Box def Content"); } | fundef { DEBUG("Box fun Content"); }; -boxselfaccess: KeySelf '.' Ident - | KeySelf '.' boxaccess; +boxselfaccess: KeySelf '.' Ident {$$ = AST_new_node(AST_Call, NULL);} + | KeySelf '.' boxaccess {$$ = AST_new_node(AST_Call, NULL);}; -boxaccess: Ident '.' Ident - | Ident '.' boxaccess; +boxaccess: Ident '.' Ident {$$ = AST_new_node(AST_Call, NULL);} + | Ident '.' boxaccess {$$ = AST_new_node(AST_Ident, $1);}; boxcall: boxaccess argumentlist | boxselfaccess argumentlist; @@ -134,33 +159,48 @@ funcall: Ident argumentlist { DEBUG("Function call"); }; moduleimport: KeyImport ValStr { DEBUG("Module-Import"); }; statementlist: statement statementlist - | statement; + | statement {$$ = $1;}; -statement: assign - | decl - | definition - | while - | branch - | funcall - | boxcall; +statement: assign {$$ = $1;} + | decl {$$ = $1;} + | definition {$$ = $1;} + | while {$$ = $1;} + | branch {$$ = $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"); }; -branchelseifs: branchelseifs branchelseif - | branchelseif; +branchelseifs: branchelseifs branchelseif {AST_NODE_PTR ifelse = AST_new_node(AST_IfElse, NULL); + AST_push_node(ifelse, $1); + AST_push_node(ifelse, $2); + $$ = ifelse;} + | branchelseif {$$ = $1;}; -branch: branchif branchelseifs - | branchif branchelseifs branchelse; +branch: branchif branchelseifs {AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); + AST_push_node(branch, $1); + AST_push_node(branch, $2); + $$ = branch;} + + | branchif branchelseifs branchelse { AST_NODE_PTR branch = AST_new_node(AST_IF, NULL);}; while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; -identlist: Ident ',' identlist - | Ident; +identlist: Ident ',' identlist {AST_push_node($3, $1); + $$ = $3;} + | Ident; -decl: type ':' identlist - | storagequalifier type ':' identlist +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 { DEBUG("Definition"); }; @@ -169,7 +209,12 @@ storagequalifier: KeyGlobal | KeyStatic | KeyLocal; -assign: Ident '=' expr { DEBUG("Assignment"); } +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 ; @@ -196,12 +241,15 @@ type: typekind | sign typekind | sign scale typekind; -operation: oparith +operation: oparith {$$ = $1;} | oplogic | opbool | opbit; -oparith: expr '+' expr +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 | expr '*' expr | expr '/' expr diff --git a/tests/ast/test_ast.py b/tests/ast/test_ast.py index 0f9b757..926671d 100644 --- a/tests/ast/test_ast.py +++ b/tests/ast/test_ast.py @@ -29,42 +29,43 @@ 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 +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 value -33 typedef -34 box -35 fun -36 value +33 value +34 typedef +35 box +36 fun +37 value """ == p.stdout From 0e5736e50c0efe428234bb97d634f356f0431706 Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 13 May 2024 11:33:23 +0200 Subject: [PATCH 02/20] AST implementation WIP --- CMakeLists.txt | 2 +- src/ast/ast.c | 6 +++ src/ast/ast.h | 8 +++- src/yacc/parser.y | 109 ++++++++++++++++++++++++++++++------------ tests/ast/test_ast.py | 2 + 5 files changed, 95 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12e8c66..0ffa084 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ 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 -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 b36d191..69d48fb 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -73,6 +73,8 @@ void AST_init() { lookup_table[AST_Typecast] = "cast"; lookup_table[AST_Transmute] = "as"; lookup_table[AST_Condition] = "condition"; + lookup_table[AST_List] = "list"; + lookup_table[AST_Type] = "type"; } const char* AST_node_to_string(const struct AST_Node_t* node) { @@ -89,6 +91,10 @@ const char* AST_node_to_string(const struct AST_Node_t* node) { case AST_Macro: case AST_Import: case AST_Call: + case AST_Storage: + case AST_Typekind: + case AST_Sign: + case AST_Scale: string = node->value; break; default: diff --git a/src/ast/ast.h b/src/ast/ast.h index abd60bc..430f284 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -60,7 +60,13 @@ enum AST_SyntaxElement_t { AST_Import, // amount of variants // in this enum - AST_ELEMENT_COUNT + AST_ELEMENT_COUNT, + AST_List, + AST_Storage, + AST_Type, + AST_Typekind, + AST_Sign, + AST_Scale }; /** diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 0fdffd4..ce25bc4 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -33,6 +33,12 @@ %type type %type identlist %type storagequalifier +%type typekind +%type scale +%type sign +%type oplogic +%type opbool +%type opbit %token KeyInt @@ -89,8 +95,8 @@ %% program: program programbody - | programbody {AST_NODE_PTR daineMudda = AST_new_node(AST_Module, NULL); - AST_fprint_graphviz(stdout, daineMudda); }; + | programbody {AST_NODE_PTR program = AST_new_node(AST_Module, NULL); + AST_fprint_graphviz(stdout, program); }; programbody: moduleimport | fundef @@ -190,7 +196,9 @@ while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; identlist: Ident ',' identlist {AST_push_node($3, $1); $$ = $3;} - | Ident; + | Ident {AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, $1); + $$ = list;}; decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL); AST_push_node(decl, $1); @@ -205,9 +213,9 @@ decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL); definition: decl '=' expr { DEBUG("Definition"); }; -storagequalifier: KeyGlobal - | KeyStatic - | KeyLocal; +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); @@ -218,41 +226,82 @@ assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(AST_Assign, NULL); | 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; -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 {$$ = $1;} - | oplogic - | opbool - | opbit; + | oplogic {$$ = $1;} + | opbool {$$ = $1;} + | opbit {$$ = $1;}; -oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node{AST_add, NULL}; +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 - | expr '*' expr - | expr '/' expr + | 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 '*'; oplogic: expr OpEquals expr diff --git a/tests/ast/test_ast.py b/tests/ast/test_ast.py index 926671d..91d637a 100644 --- a/tests/ast/test_ast.py +++ b/tests/ast/test_ast.py @@ -66,6 +66,8 @@ def run_check_print_node(): 35 box 36 fun 37 value +38 list +39 storage """ == p.stdout From 02e7c2775b4074822aad2842e2bcc08b54803506 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 13 May 2024 16:13:49 +0200 Subject: [PATCH 03/20] added better parser error messages --- src/lex/lexer.l | 15 +++++++- src/lex/util.c | 79 ++++++++++++++++++++++++++++++++++++++++++ src/lex/util.h | 37 ++++++++++++++++++++ src/main.c | 8 +++-- src/sys/col.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++ src/sys/col.h | 43 +++++++++++++++++++++++ src/yacc/parser.y | 73 +++++++++++++++++++++++++++++++++++++-- 7 files changed, 337 insertions(+), 5 deletions(-) create mode 100644 src/lex/util.c create mode 100644 src/lex/util.h create mode 100644 src/sys/col.c create mode 100644 src/sys/col.h diff --git a/src/lex/lexer.l b/src/lex/lexer.l index c9bf739..d0e6d10 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -2,9 +2,21 @@ %{ #include #include + #include int yyLineNumber = 1; + int yylex(); + + extern int yyerror(char* s); + + #define YY_USER_ACTION beginToken(yytext); + + #define YY_INPUT(buf,result,max_size) {\ + result = nextChar(buf); \ + if ( result <= 0 ) \ + result = YY_NULL; \ + } %} /* disable the following functions */ @@ -81,5 +93,6 @@ [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);}; -.; +[ \r\t] { /* ignore whitespace */ }; +. { }; %% diff --git a/src/lex/util.c b/src/lex/util.c new file mode 100644 index 0000000..b5b92ac --- /dev/null +++ b/src/lex/util.c @@ -0,0 +1,79 @@ + +#include +#include +#include + +// implementation based on: +// https://github.com/sunxfancy/flex-bison-examples/blob/master/error-handling/ccalc.c + +char* buffer = NULL; + +static int eof = 0; +static int nRow = 0; +static int nBuffer = 0; +static int lBuffer = 0; +static int nTokenStart = 0; +static int nTokenLength = 0; +static int nTokenNextStart = 0; + +static void lex_deinit(void) { + free(buffer); +} + +void lex_init(void) { + buffer = malloc(MAX_READ_BUFFER_SIZE); + atexit(lex_deinit); +} + +void beginToken(char *t) { + nTokenStart = nTokenNextStart; + nTokenLength = (int) strlen(t); + nTokenNextStart = nBuffer + 1; + + yylloc.first_line = nRow; + yylloc.first_column = nTokenStart; + yylloc.last_line = nRow; + yylloc.last_column = nTokenStart + nTokenLength - 1; +} + +int nextChar(char *dst) { + int frc; + + if (eof) + return 0; + + while (nBuffer >= lBuffer) { + frc = getNextLine(); + if (frc != 0) { + return 0; + } + } + + dst[0] = buffer[nBuffer]; + nBuffer += 1; + + return dst[0] != 0; +} + +int getNextLine(void) { + char *p; + + nBuffer = 0; + nTokenStart = -1; + nTokenNextStart = 1; + eof = 0; + + p = fgets(buffer, MAX_READ_BUFFER_SIZE, yyin); + if (p == NULL) { + if (ferror(yyin)) { + return -1; + } + eof = 1; + return 1; + } + + nRow += 1; + lBuffer = (int) strlen(buffer); + + return 0; +} diff --git a/src/lex/util.h b/src/lex/util.h new file mode 100644 index 0000000..12e0837 --- /dev/null +++ b/src/lex/util.h @@ -0,0 +1,37 @@ + +#ifndef LEX_UTIL_H_ +#define LEX_UTIL_H_ + +#include +#include + +#define MAX_READ_BUFFER_SIZE 1000 + +extern FILE* yyin; +extern YYLTYPE yylloc; +extern char* buffer; + +/** + * @brief Initialize global state needed for the lexer + */ +void lex_init(void); + +/** + * @brief Begin counting a new token. This will fill the global struct yylloc. + * @param t the text of the token. Must be null terminated + */ +[[gnu::nonnull(1)]] +void beginToken(char *t); + +/** + * @brief Stores the next character into the supplied buffer + * @param dst the buffer to store character in + */ +int nextChar(char *dst); + +/** + * @brief Reads the next line from yyin into a global buffer + */ +int getNextLine(void); + +#endif // LEX_UTIL_H_ diff --git a/src/main.c b/src/main.c index 03ab6b9..5f1c8ab 100644 --- a/src/main.c +++ b/src/main.c @@ -2,11 +2,11 @@ #include #include #include +#include +#include #define LOG_LEVEL LOG_LEVEL_DEBUG -extern FILE *yyin; - /** * @brief Log a debug message to inform about beginning exit procedures * @@ -41,6 +41,10 @@ void setup(void) { // actual setup AST_init(); + col_init(); + + lex_init(); + DEBUG("finished starting up gemstone..."); } diff --git a/src/sys/col.c b/src/sys/col.c new file mode 100644 index 0000000..76260ec --- /dev/null +++ b/src/sys/col.c @@ -0,0 +1,87 @@ + +#include +#include +#include +#include + +#ifdef __unix__ +#include +#elif defined(_WIN32) || defined(WIN32) +#include +#endif + +char *RED; +char *YELLOW; +char *MAGENTA; +char *CYAN; +char *GREEN; +char *RESET; +char *BOLD; +char *FAINT; + +void col_init(void) { + if (stdout_supports_ansi_esc()) { + enable_ansi_colors(); + } else { + disable_ansi_colors(); + } +} + +void disable_ansi_colors() { + DEBUG("disabling ANSI escape codes"); + + RED = ""; + YELLOW = ""; + MAGENTA = ""; + CYAN = ""; + GREEN = ""; + RESET = ""; + BOLD = ""; + FAINT = ""; +} + +void enable_ansi_colors() { + DEBUG("enabling ANSI escape codes"); + + RED = "\x1b[31m"; + YELLOW = "\x1b[33m"; + MAGENTA = "\x1b[35m"; + CYAN = "\x1b[36m"; + GREEN = "\x1b[32m"; + RESET = "\x1b[0m"; + BOLD = "\x1b[1m"; + FAINT = "\x1b[2m"; +} + +int stdout_supports_ansi_esc() { + +#ifdef __unix__ + // check if TTY + if (isatty(STDOUT_FILENO)) { + const char *colors = getenv("COLORTERM"); + // check if colors are set and allowed + if (colors != NULL && (strcmp(colors, "truecolor") == 0 || strcmp(colors, "24bit") == 0)) { + return ANSI_ENABLED; + } + } +#elif defined(_WIN32) || defined(WIN32) + // see: + // https://stackoverflow.com/questions/63913005/how-to-test-if-console-supports-ansi-color-codes + DWORD mode; + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + if (!GetConsoleMode(hConsole, &mode)) { + ERROR("failed to get console mode"); + return ANSI_ENABLED; + } + + if ((mode & ENABLE_VIRTUAL_TERMINAL_INPUT) | + (mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { + return ANSI_ENABLED; + } +#else +#warning "unsupported platform, ASNI escape codes disabled by default" +#endif + + return ASNI_DISABLED; +} diff --git a/src/sys/col.h b/src/sys/col.h new file mode 100644 index 0000000..125d0d6 --- /dev/null +++ b/src/sys/col.h @@ -0,0 +1,43 @@ + +#ifndef COLORS_H_ +#define COLORS_H_ + +#define ANSI_ENABLED 1 +#define ASNI_DISABLED 0 + +// Common escape codes +// can be used to print colored text +extern char *RED; +extern char *YELLOW; +extern char *MAGENTA; +extern char *CYAN; +extern char *GREEN; +extern char *RESET; +extern char *BOLD; +extern char *FAINT; + +/** + * @brief Initialize global state + */ +void col_init(void); + +/** + * @brief Enable ANSI escape codes. This will set the correct escape codes to + * the global strings above. + */ +void enable_ansi_colors(); + +/** + * @brief Disable ANSI escape codes. This will set all the above global strings to be empty. + */ +void disable_ansi_colors(); + +/** + * @brief Check if stdout may support ANSI escape codes. + * @attention This function may report escape codes to be unavailable even if they actually are. + * @return ANSI_ENABLED if escape sequences are supported ASNI_DISABLED otherwise + */ +[[nodiscard]] +int stdout_supports_ansi_esc(); + +#endif // COLORS_H_ diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 36c5931..6221d8b 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -1,9 +1,15 @@ +%locations +%define parse.error verbose + %{ #include - extern int yylineno; + #include int yyerror(char*); + extern char* buffer; + extern int yylineno; + extern int yylex(); %} @@ -55,6 +61,7 @@ %token FunFunname %token FunLineno %token FunExtsupport +%token Invalid /* Operator associativity */ %right '=' @@ -222,7 +229,69 @@ opbit: expr OpBitand expr | OpBitnot expr %prec OpBitand; %% + +const char* ERROR = "error"; +const char* WARNING = "warning"; +const char* NOTE = "note"; + +int print_message(const char* kind, char* message) { + // number of characters written + int char_count = 0; + // highlight to use + char* HIGHLIGHT = CYAN; + + // convert message kind into color + if (kind == ERROR) { + HIGHLIGHT = RED; + } else if (kind == WARNING) { + HIGHLIGHT = YELLOW; + } + + // print message + char_count += printf("%sfilename:%d:%d%s:%s%s %s: %s%s\n", BOLD, yylloc.first_line, yylloc.first_column, RESET, HIGHLIGHT, BOLD, kind, RESET, message); + + // print line in which error occurred + + char_count += printf(" %4d | ", yylloc.first_line); + + for (int i = 0; i < yylloc.first_column - 1; i++) { + if (buffer[i] == '\n') { + break; + } + printf("%c", buffer[i]); + } + + char_count += printf("%s%s", BOLD, HIGHLIGHT); + + for (int i = yylloc.first_column - 1; i < yylloc.last_column; i++) { + if (buffer[i] == '\n') { + break; + } + char_count += printf("%c", buffer[i]); + } + + char_count += printf("%s", RESET); + + for (int i = yylloc.last_column; buffer[i] != '\0' && buffer[i] != '\n'; i++) { + printf("%c", buffer[i]); + } + + char_count += printf("\n | "); + + for (int i = 0; i < yylloc.first_column - 1; i++) { + char_count += printf(" "); + } + + char_count += printf("%s^", HIGHLIGHT); + + for (int i = 0; i < yylloc.last_column - yylloc.first_column; i++) { + printf("~"); + } + + char_count += printf("%s\n\n", RESET); +} + int yyerror(char *s) { - ERROR("%s", s); + print_message(ERROR, s); return 0; } \ No newline at end of file From 3d3083c8948c4fb148aedd2d887f5184c1fa0373 Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 13 May 2024 22:17:43 +0200 Subject: [PATCH 04/20] first functional state of syntax tree --- src/ast/ast.c | 6 +- src/ast/ast.h | 10 +- src/yacc/parser.y | 360 +++++++++++++++++++++++++++++++++------------- 3 files changed, 271 insertions(+), 105 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 69d48fb..a554b35 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -70,11 +70,15 @@ 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_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) { @@ -90,11 +94,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 430f284..e42e0c9 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -59,14 +59,18 @@ enum AST_SyntaxElement_t { AST_Fun, AST_Import, // amount of variants - // in this enum - AST_ELEMENT_COUNT, + // in this enums AST_List, AST_Storage, AST_Type, AST_Typekind, AST_Sign, - AST_Scale + AST_Scale, + AST_Negate, + AST_Parameter, + AST_Qualifyier, + AST_ParamDecl, + AST_ELEMENT_COUNT }; /** diff --git a/src/yacc/parser.y b/src/yacc/parser.y index ce25bc4..e654eff 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -1,4 +1,4 @@ -%{ +%code requires { #include #include extern int yylineno; @@ -6,39 +6,56 @@ int yyerror(char*); extern int yylex(); -%} + + +} %union { char *string; + AST_NODE_PTR node_ptr; } -%type expr -%type operation -%type boxaccess -%type boxselfaccess -%type statement -%type statementlist -%type assign -%type oparith -%type decl -%type definition -%type while -%type branch -%type funcall -%type boxcall -%type branchelseifs -%type branchelse -%type branchelseif -%type branchif -%type type -%type identlist -%type storagequalifier -%type typekind -%type scale -%type sign -%type oplogic -%type opbool -%type opbit +%type operation +%type boxaccess +%type boxselfaccess +%type statement +%type statementlist +%type assign +%type oparith +%type decl +%type definition +%type while +%type branch +%type funcall +%type boxcall +%type branchelseifs +%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 @@ -94,78 +111,172 @@ %left OpBitand OpBitor OpBitxor OpBitnot %% -program: program programbody +program: program programbody {AST_push_node($1, $2); + FILE *file = fopen("test.txt", "w"); + AST_fprint_graphviz(file, $1); + fclose(file);} | programbody {AST_NODE_PTR program = AST_new_node(AST_Module, NULL); - AST_fprint_graphviz(stdout, program); }; + AST_push_node(program, $1); + FILE *file = fopen("test.txt", "w"); + AST_fprint_graphviz(file, program); + fclose(file); }; -programbody: moduleimport - | fundef - | box - | definition - | decl - | typedef; +programbody: moduleimport {$$ = $1;} + | fundef{$$ = $1;} + | box{$$ = $1;} + | definition{$$ = $1;} + | decl{$$ = $1;} + | typedef{$$ = $1;}; -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};} +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_List, 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_List, NULL); + AST_push_node(list, $2); + $$ = 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);} + | '(' ')' {$$ = 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_List, 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 {$$ = AST_new_node(AST_Call, NULL);} - | KeySelf '.' boxaccess {$$ = AST_new_node(AST_Call, NULL);}; +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_List, 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 {$$ = AST_new_node(AST_Call, NULL);} - | Ident '.' boxaccess {$$ = AST_new_node(AST_Ident, $1);}; +boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(AST_List, 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 {$$ = $1;}; +statementlist: statementlist statement {AST_push_node($1, $2); + $$ = $1;} + | statement {AST_NODE_PTR list = AST_new_node(AST_List, NULL); + AST_push_node(list, $1); + $$ = list;}; statement: assign {$$ = $1;} | decl {$$ = $1;} @@ -190,14 +301,20 @@ branch: branchif branchelseifs {AST_NODE_PTR branch = AST_new_node(AST_Stmt, NUL AST_push_node(branch, $2); $$ = branch;} - | branchif branchelseifs branchelse { AST_NODE_PTR branch = AST_new_node(AST_IF, NULL);}; + | branchif branchelseifs branchelse { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); + AST_push_node(branch, $1); + AST_push_node(branch, $2); + AST_push_node(branch, $3); + $$ = branch;}; while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; -identlist: Ident ',' identlist {AST_push_node($3, $1); +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_List, NULL); - AST_push_node(list, $1); + AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); + AST_push_node(list, ident); $$ = list;}; decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL); @@ -211,7 +328,11 @@ decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL); $$ = decl;} -definition: decl '=' expr { DEBUG("Definition"); }; +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");} @@ -229,7 +350,11 @@ assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(AST_Assign, NULL); 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 {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short"); AST_push_node($1, shortnode); @@ -264,18 +389,18 @@ typekind: Ident {$$ = AST_new_node(AST_Typekind, $1);} | KeyInt {$$ = AST_new_node(AST_Typekind, "int");} | KeyFloat {$$ = AST_new_node(AST_Typekind, "float");}; -type: typekind {AST_NODE_PTR type = AST_new_node(AST_type, NULL); +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); + | 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); + | 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); + | 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); @@ -286,37 +411,70 @@ operation: oparith {$$ = $1;} | opbool {$$ = $1;} | opbit {$$ = $1;}; -oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node{AST_Add, NULL}; +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}; + | 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}; + | 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}; + | 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 '*'; + | '-' 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;}; %% int yyerror(char *s) { From fa8c97d84f847c503532b36e44b5e904888077a1 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 14 May 2024 12:27:21 +0200 Subject: [PATCH 05/20] lexer unknown token passthrough --- .gitignore | 3 +++ src/lex/lexer.l | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bb676ce..10613c6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ parser.tab.c parser.tab.h build /Testing/ +CTestTestfile.cmake +DartConfiguration.tcl +*.cmake diff --git a/src/lex/lexer.l b/src/lex/lexer.l index d0e6d10..2c96d23 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -94,5 +94,5 @@ \"([^\"\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);}; [ \r\t] { /* ignore whitespace */ }; -. { }; +. { return yytext[0]; /* passthrough unknown token, let parser handle the error */ }; %% From 5aa192871badc14a75a5a4b5c855e05b30252391 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 14 May 2024 12:37:52 +0200 Subject: [PATCH 06/20] fixed bison build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12e8c66..be613ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE} COMMAND yacc - ARGS -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" VERBATIM) From 4c61851a487523ceb5f0a43f0a1d934effe381fd Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 14 May 2024 13:28:05 +0200 Subject: [PATCH 07/20] fixed build errors --- src/lex/lexer.l | 2 +- src/yacc/parser.y | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lex/lexer.l b/src/lex/lexer.l index 2c96d23..b93499a 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -8,7 +8,7 @@ int yylex(); - extern int yyerror(char* s); + extern int yyerror(const char* s); #define YY_USER_ACTION beginToken(yytext); diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 6221d8b..19d8aa1 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -5,7 +5,7 @@ #include #include - int yyerror(char*); + int yyerror(const char*); extern char* buffer; extern int yylineno; @@ -234,7 +234,7 @@ const char* ERROR = "error"; const char* WARNING = "warning"; const char* NOTE = "note"; -int print_message(const char* kind, char* message) { +int print_message(const char* kind, const char* message) { // number of characters written int char_count = 0; // highlight to use @@ -289,9 +289,10 @@ int print_message(const char* kind, char* message) { } char_count += printf("%s\n\n", RESET); + + return char_count; } -int yyerror(char *s) { - print_message(ERROR, s); - return 0; +int yyerror(const char *s) { + return print_message(ERROR, s); } \ No newline at end of file From b3ad82cc49cc92b7d97b57a086894d9f7633d1be Mon Sep 17 00:00:00 2001 From: Filleo Date: Tue, 14 May 2024 14:03:45 +0200 Subject: [PATCH 08/20] moved root node to main moved output code to main removed '"' from string literals --- src/lex/lexer.l | 12 ++++++++++-- src/main.c | 5 +++++ src/yacc/parser.y | 13 +++---------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/lex/lexer.l b/src/lex/lexer.l index c9bf739..2307af7 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -79,7 +79,15 @@ [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);}; .; %% diff --git a/src/main.c b/src/main.c index 03ab6b9..fab7659 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,7 @@ #define LOG_LEVEL LOG_LEVEL_DEBUG extern FILE *yyin; +AST_NODE_PTR root; /** * @brief Log a debug message to inform about beginning exit procedures @@ -65,7 +66,11 @@ 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(file, root); + fclose(output); return 0; } diff --git a/src/yacc/parser.y b/src/yacc/parser.y index e654eff..89c4433 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -6,7 +6,7 @@ int yyerror(char*); extern int yylex(); - + extern AST_NODE_PTR root; } @@ -111,15 +111,8 @@ %left OpBitand OpBitor OpBitxor OpBitnot %% -program: program programbody {AST_push_node($1, $2); - FILE *file = fopen("test.txt", "w"); - AST_fprint_graphviz(file, $1); - fclose(file);} - | programbody {AST_NODE_PTR program = AST_new_node(AST_Module, NULL); - AST_push_node(program, $1); - FILE *file = fopen("test.txt", "w"); - AST_fprint_graphviz(file, program); - fclose(file); }; +program: program programbody {AST_push_node(root, $2);} + | programbody {AST_push_node(root, $1);}; programbody: moduleimport {$$ = $1;} | fundef{$$ = $1;} From 8c063d701622e1a4e1b0beff44220579526f3343 Mon Sep 17 00:00:00 2001 From: Filleo Date: Tue, 14 May 2024 14:57:15 +0200 Subject: [PATCH 09/20] changed little error in main --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index fab7659..0591208 100644 --- a/src/main.c +++ b/src/main.c @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) { yyparse(); FILE *output = fopen("test.txt", "w"); - AST_fprint_graphviz(file, root); + AST_fprint_graphviz(output, root); fclose(output); return 0; } From a14faeeee7d080266fdd1cfd64e46d4d6ff2b0a2 Mon Sep 17 00:00:00 2001 From: Filleo Date: Tue, 14 May 2024 15:30:13 +0200 Subject: [PATCH 10/20] added specific lists solved bug in Funcall --- src/ast/ast.c | 5 +++++ src/ast/ast.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/ast/ast.c b/src/ast/ast.c index a554b35..742bb73 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -75,6 +75,11 @@ void AST_init() { 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"; diff --git a/src/ast/ast.h b/src/ast/ast.h index e42e0c9..ff8297b 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -61,6 +61,11 @@ enum AST_SyntaxElement_t { // amount of variants // in this enums AST_List, + AST_ExprList, + AST_ArgList, + AST_ParamList, + AST_StmtList, + AST_IdentList, AST_Storage, AST_Type, AST_Typekind, From 1055aa0f73371cbc4cbc91683cb531cc391063b3 Mon Sep 17 00:00:00 2001 From: Filleo Date: Tue, 14 May 2024 17:01:42 +0200 Subject: [PATCH 11/20] add identlist --- src/yacc/parser.y | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 89c4433..1084112 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -134,15 +134,18 @@ expr: ValFloat {$$ = AST_new_node(AST_Float, $1);} exprlist: expr ',' exprlist {AST_push_node($3, $1); $$ = $3;} - | expr {AST_NODE_PTR list = AST_new_node(AST_List, NULL); + | expr {AST_NODE_PTR list = AST_new_node(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(AST_List, NULL); + | '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL); AST_push_node(list, $2); - $$ = list;}; + $$ = list;} + | argumentlist '(' ')' + | '(' ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL); + $$ = list;}; fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(AST_Fun, NULL); @@ -158,14 +161,14 @@ paramlist: paramlist '(' params ')' {AST_push_node($1, $3); | paramlist '(' ')'{$$ = $1;} | '(' params ')' {AST_NODE_PTR list = AST_new_node(AST_List, NULL); AST_push_node(list, $2);} - | '(' ')' {$$ = AST_new_node(AST_List, NULL);}; + | '(' ')' {$$ = AST_new_node(AST_ParamList, NULL);}; 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_List, NULL); + | 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); @@ -225,7 +228,7 @@ boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); } 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_List, NULL); + 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); @@ -236,7 +239,7 @@ boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(AST_ AST_push_node(boxselfaccess, $3); $$ = boxselfaccess;}; -boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(AST_List, NULL); +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); @@ -267,7 +270,7 @@ moduleimport: KeyImport ValStr {$$ = AST_new_node(AST_Import, $2); statementlist: statementlist statement {AST_push_node($1, $2); $$ = $1;} - | statement {AST_NODE_PTR list = AST_new_node(AST_List, NULL); + | statement {AST_NODE_PTR list = AST_new_node(AST_StmtList, NULL); AST_push_node(list, $1); $$ = list;}; @@ -305,7 +308,7 @@ while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; 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_List, NULL); + | 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;}; From 3ea179b4a9a60631a366701a4a8647a77847bae8 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 14 May 2024 19:08:42 +0200 Subject: [PATCH 12/20] added precedence for +,-,*,/ --- src/yacc/parser.y | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 1084112..9224fb4 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -105,7 +105,8 @@ /* Operator associativity */ %right '=' -%left '+' '-' '*' '/' +%left '+' '-' +%left '*' '/' %left OpEquals OpNot '<' '>' %left OpAnd OpOr OpXor %left OpBitand OpBitor OpBitxor OpBitnot From 32b964444a32db659f1fc51f5c6154092f66b2e7 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 14 May 2024 19:20:58 +0200 Subject: [PATCH 13/20] added C like precedence for operators --- src/yacc/parser.y | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 9224fb4..ee219e9 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -104,12 +104,19 @@ %token FunExtsupport /* 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 OpEquals OpNot '<' '>' -%left OpAnd OpOr OpXor -%left OpBitand OpBitor OpBitxor OpBitnot +%left OpNot OpBitnot %% program: program programbody {AST_push_node(root, $2);} From c24a430fd28bd6267130ccff7d555ff462c08a61 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 14 May 2024 20:23:29 +0200 Subject: [PATCH 14/20] fixed if statement --- src/yacc/parser.y | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index ee219e9..aef70f3 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -290,26 +290,40 @@ statement: assign {$$ = $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 {AST_NODE_PTR ifelse = AST_new_node(AST_IfElse, NULL); - AST_push_node(ifelse, $1); - AST_push_node(ifelse, $2); - $$ = ifelse;} - | branchelseif {$$ = $1;}; +branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_Else, NULL); + AST_push_node(branch, $3); + $$ = branch; }; -branch: branchif branchelseifs {AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); +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; }; + +branchelseifs: branchelseifs branchelseif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); + AST_push_node(branch, $1); + AST_push_node(branch, $2); + $$ = branch; } + | branchelseif { $$ = $1; }; + +branch: branchif { $$ = $1; } + | branchif branchelseifs { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); AST_push_node(branch, $1); AST_push_node(branch, $2); - $$ = branch;} - - | branchif branchelseifs branchelse { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); - AST_push_node(branch, $1); - AST_push_node(branch, $2); - AST_push_node(branch, $3); - $$ = branch;}; + $$ = branch; } + | branchif branchelseifs branchelse { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); + AST_push_node(branch, $1); + AST_push_node(branch, $2); + AST_push_node(branch, $3); + $$ = branch; } + | branchif branchelse { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); + AST_push_node(branch, $1); + AST_push_node(branch, $2); + $$ = branch; }; while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; From f11ade2ef20a7c07bd3d5b8c9194df1cc686f1af Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 15 May 2024 10:29:47 +0200 Subject: [PATCH 15/20] changed If else branches, so that the whole branch is under one stmt node --- src/yacc/parser.y | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index aef70f3..db70070 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -25,10 +25,10 @@ %type decl %type definition %type while -%type branch %type funcall %type boxcall -%type branchelseifs +%type branchhalf +%type branchfull %type branchelse %type branchelseif %type branchif @@ -286,7 +286,7 @@ statement: assign {$$ = $1;} | decl {$$ = $1;} | definition {$$ = $1;} | while {$$ = $1;} - | branch {$$ = $1;} + | branchfull {$$ = $1;} | funcall {$$ = $1;} | boxcall{$$ = $1;}; @@ -304,26 +304,15 @@ branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = A AST_push_node(branch, $5); $$ = branch; }; -branchelseifs: branchelseifs branchelseif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); - AST_push_node(branch, $1); - AST_push_node(branch, $2); - $$ = branch; } - | branchelseif { $$ = $1; }; +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; } -branch: branchif { $$ = $1; } - | branchif branchelseifs { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); - AST_push_node(branch, $1); - AST_push_node(branch, $2); - $$ = branch; } - | branchif branchelseifs branchelse { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); - AST_push_node(branch, $1); - AST_push_node(branch, $2); - AST_push_node(branch, $3); - $$ = branch; } - | branchif branchelse { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); - AST_push_node(branch, $1); - AST_push_node(branch, $2); - $$ = branch; }; while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; From ac7ceaab9b489f9ee93d2b9bf648f902833bab58 Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 15 May 2024 10:41:08 +0200 Subject: [PATCH 16/20] added while to the syntax tree --- src/yacc/parser.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index db70070..811f222 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -314,7 +314,10 @@ branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL); $$ = $1; } -while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); }; +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;}; identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1); AST_push_node($3, ident); From f2317c78ce69a3f80a40fecd022858c11b708989 Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 15 May 2024 16:14:55 +0200 Subject: [PATCH 17/20] solved bug from fun def --- src/yacc/parser.y | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 811f222..5c15452 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -168,8 +168,9 @@ 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);} - | '(' ')' {$$ = AST_new_node(AST_ParamList, NULL);}; + AST_push_node(list, $2); + $$ = list;} + | '(' ')' {$$ = AST_new_node(AST_List, NULL);}; params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL); AST_push_node(parameter, $1); @@ -311,7 +312,7 @@ 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; } + $$ = $1; }; while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(AST_While, NULL); From d7b690ec8a893a1a4b4515886cd93426ba85123d Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 15 May 2024 16:26:40 +0200 Subject: [PATCH 18/20] solved error in test --- src/ast/ast.c | 1 - tests/ast/test_ast.py | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 742bb73..e503e1e 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -33,7 +33,6 @@ 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"; diff --git a/tests/ast/test_ast.py b/tests/ast/test_ast.py index 91d637a..28407f9 100644 --- a/tests/ast/test_ast.py +++ b/tests/ast/test_ast.py @@ -60,14 +60,27 @@ def run_check_print_node(): 29 < 30 cast 31 as -32 value +32 funcall 33 value 34 typedef 35 box 36 fun 37 value 38 list -39 storage +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 From 7789c7e597e1a23f3a2c00fb236d249511139efe Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 15 May 2024 17:03:18 +0200 Subject: [PATCH 19/20] added removal of root node after output generation --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index 0591208..ac54e76 100644 --- a/src/main.c +++ b/src/main.c @@ -72,5 +72,6 @@ int main(int argc, char *argv[]) { FILE *output = fopen("test.txt", "w"); AST_fprint_graphviz(output, root); fclose(output); + AST_delete_node(root); return 0; } From addaff4818c214669163d3f65340d4efdd3b9049 Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 15 May 2024 19:30:29 +0200 Subject: [PATCH 20/20] i am not a smart man --- src/yacc/parser.y | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 5667d24..d8bf1a1 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -4,6 +4,7 @@ %code requires { #include #include + #include extern int yylineno;