diff options
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | Readme.txt | 1 | ||||
-rw-r--r-- | ast.c | 18 | ||||
-rw-r--r-- | ast.h | 17 | ||||
-rw-r--r-- | grammar.y | 89 | ||||
-rw-r--r-- | lex.l | 10 | ||||
-rw-r--r-- | test/test.test | 6 |
7 files changed, 138 insertions, 18 deletions
@@ -1,4 +1,13 @@ build: grammar.y lex.l - bison -o build/grammar.tab.c -d grammar.y - flex -o build/lex.yy.c lex.l - gcc -o build/henshin build/grammar.tab.c build/lex.yy.c -lfl -ly + bison \ + -o build/grammar.tab.c \ + -d grammar.y \ + #-Wcounterexamples + flex \ + -o build/lex.yy.c \ + lex.l + gcc \ + -o build/henshin \ + build/grammar.tab.c build/lex.yy.c \ + -I ./ \ + -lfl -ly @@ -5,3 +5,4 @@ - https://www.ecosia.org/search?q=transpiler%20with%20bison%20and%20lex - https://github.com/labis7/Flex_Bison_Transpiler - https://gnuu.org/2009/09/18/writing-your-own-toy-compiler/ +- https://lloydrochester.com/post/flex-bison/json-parse-ast/ @@ -0,0 +1,18 @@ +#include "ast.h" + + +ast_node* create_node() { + ast_node* node = malloc(sizeof(ast_node)); + + return node; +} + +ast_node* create_program_node(ast_node* previous_node, ast_node* current_node) { + ast_node* node = malloc(sizeof(ast_node)); + + node->type = PROGRAM_NODE; + node->left = previous_node; + node->right = current_node; + + return node; +} @@ -0,0 +1,17 @@ +#ifndef AST_H +#define AST_H + +#include <stdlib.h> + +#define PROGRAM_NODE 0 + +typedef struct ast_node { + int type; + void* value; + struct ast_node* left; + struct ast_node* right; +} ast_node; + +ast_node* create_program_node(ast_node* previous_node, ast_node* current_node); + +#endif // AST_H @@ -1,13 +1,24 @@ %{ #include <stdio.h> +#include "ast.c" + extern FILE *yyin; + extern int yylex(); extern void yyerror(); + +ast_node* yyast = NULL; %} %define parse.error verbose +%union { + char* string; + int number; + ast_node* node; +} + %token OPERATOR_PLUS %token OPERATOR_MINUS %token ASSIGN @@ -19,6 +30,10 @@ extern void yyerror(); %token CONST %token VAR +%token TYPE_INTEGER +%token TYPE_STRING +%token TYPE_VOID + %token PARENTHESIS_LEFT %token PARENTHESIS_RIGHT %token BRACE_LEFT @@ -27,6 +42,7 @@ extern void yyerror(); %token BRACKET_RIGHT %token COMMA; +%token COLON; %token NUMBER; %token IDENTIFIER @@ -34,20 +50,65 @@ extern void yyerror(); %token END_OF_LINE; +%type <node> program +%type <node> function +%type <node> arguments +%type <node> argument +%type <node> return_type +%type <node> variable_type +%type <node> statements +%type <node> statement +%type <node> expression + +%type <node> IDENTIFIER +%type <node> RETURN + +%start program + %% -program: - | program statement END_OF_LINE - ; - -statement: expression - | RETURN expression - | CONST IDENTIFIER ASSIGN expression - | VAR IDENTIFIER ASSIGN expression - ; - -expression: NUMBER - | IDENTIFIER - ; +program: { $$ = NULL; } + | program statement END_OF_LINE { $$ = create_program_node($1, $2); } + + +// function henshin(): void {} +// function henshin(hen: integer, shin: integer): void {} +function: + | FUNCTION IDENTIFIER PARENTHESIS_LEFT PARENTHESIS_RIGHT COLON return_type BRACE_LEFT statements BRACE_RIGHT + | FUNCTION IDENTIFIER PARENTHESIS_LEFT arguments PARENTHESIS_RIGHT COLON return_type BRACE_LEFT statements BRACE_RIGHT { $$ = create_node(); $$->value = $2; } + +arguments: + | argument + | arguments COMMA argument + +argument: + | IDENTIFIER COLON variable_type + + +return_type: + | TYPE_INTEGER + | TYPE_STRING + | TYPE_VOID + +variable_type: + | TYPE_INTEGER + | TYPE_STRING + + +statements: + | statement + | statements END_OF_LINE statement + +statement: + // const henshin: integer = 2 + | CONST IDENTIFIER COLON variable_type ASSIGN expression + | RETURN expression { $$ = create_node(); $$->left = $1; $$->right = $2; } + | IDENTIFIER PARENTHESIS_LEFT PARENTHESIS_RIGHT + | function + + +expression: + | NUMBER + | IDENTIFIER %% void main (int argc, char **argv) @@ -55,4 +116,6 @@ void main (int argc, char **argv) //henshin_lex(); yyin = fopen(argv[1], "r"); yyparse(); + + printf("%s", yyast); } @@ -1,4 +1,5 @@ %{ +#include "ast.h" #include "grammar.tab.h" %} @@ -14,6 +15,10 @@ "const" { return CONST; } "var" { return VAR; } +"integer" { return TYPE_INTEGER; } +"string" { return TYPE_STRING; } +"void" { return TYPE_VOID; } + "(" { return PARENTHESIS_LEFT; } ")" { return PARENTHESIS_RIGHT; } "{" { return BRACE_LEFT; } @@ -22,9 +27,10 @@ "]" { return BRACKET_RIGHT; } "," { return COMMA; } +":" { return COLON; } -[0-9]+ { yylval = atoi(yytext); return NUMBER; } -[a-zA-Z]+[a-zA-Z0-9]* { return IDENTIFIER; } +[a-zA-Z][a-zA-Z0-9]* { yylval.string = yytext; return IDENTIFIER; } +[0-9]+ { yylval.number = atoi(yytext); return NUMBER; } "//".* { return COMMENT; } \n { return END_OF_LINE; } diff --git a/test/test.test b/test/test.test new file mode 100644 index 0000000..44580c7 --- /dev/null +++ b/test/test.test @@ -0,0 +1,6 @@ +function henshin(hen: integer, shin: integer): void { + const x: integer = 2 + const b: string = x + + return b +} |