123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- %{
- #include <stdio.h>
- #include <string.h>
- #include "yacc.tab.h"
- #include "symtable.h"
- #include "ast_node.h"
- #include "parser.h"
- #include <unistd.h>
- #include "structtable.h"
- #include <stdlib.h>
-
- // line number (got from lex.l)
- extern int linenum;
- // buffer for general use
- #define DD_BUFFER_SIZE 1000
- char buffer[DD_BUFFER_SIZE];
- // error
- void yyerror(const char *str)
- {
- fprintf(stderr,"error: line %d: %s\n", linenum, str);
- _exit(-1);
- }
-
- // game node, parent of all nodes
- struct ast_node *game_node;
- /* compiler flags
- * debug_symbol_table: print details of the symbol table
- * debug_struct_table: print details of the struct table
- * debug_ast: print the abstract syntax tree
- */
- int debug_symbol_table = 0;
- int debug_struct_table = 0;
- int debug_ast = 0;
- char *srcfile = 0;
- // init data, parse, exit
- int main(int argc, char *argv[])
- {
- /* handle arguments
- * currently they can only allow printing of debugging information
- */
- int i = 1;
- while (i < argc) {
- if (strcmp(argv[i], "--debug") == 0) {
- debug_symbol_table = 1;
- debug_struct_table = 1;
- debug_ast = 1;
- }
- else if (strcmp(argv[i], "--debug-symbol-table") == 0) {
- debug_symbol_table = 1;
- }
- else if (strcmp(argv[i], "--debug-struct-table") == 0) {
- debug_struct_table = 1;
- }
- else if (strcmp(argv[i], "--debug-ast") == 0) {
- debug_ast = 1;
- }
- // no specific argument found, assume that's source file
- else {
- srcfile = argv[i];
- }
- // next argument
- i++;
- } // done parsing arguments
- if (srcfile == 0) {
- printf("please supply a source file!\n");
- return -1;
- }
- // init data
- linenum = 1;
- // initial symbols
- if (!symtable_init()) {
- fprintf(stderr, "yacc: unable to initialise symbol table\n");
- return -1;
- }
- if (symtable_insert("DD_WIDTH", DD_INTERNAL_WIDTH) == -1
- || symtable_insert("DD_HEIGHT", DD_INTERNAL_HEIGHT) == -1) {
- fprintf(stderr, "yacc: unable to add symbol to symbol table\n");
- return -1;
- }
- game_node = ast_create(AST_GAME, 0);
- // init structs
- struct struct_entry *temp_entry = malloc(sizeof(struct struct_entry));
- temp_entry->name = "dd_world";
- struct_insert(temp_entry);
- temp_entry = malloc(sizeof(struct struct_entry));
- temp_entry->name = "dd_sprite";
- struct_insert(temp_entry);
- temp_entry = malloc(sizeof(struct struct_entry));
- temp_entry->name = "dd_vector2d";
- struct_insert(temp_entry);
- // parse!
- yyparse();
- // parse resulting ast tree to a file
- parse(argv[1], game_node);
- // print debug data
- if (debug_symbol_table) {
- symtable_print();
- }
- if (debug_struct_table) {
- struct_print();
- }
- if (debug_ast) {
- ast_print(game_node);
- }
- // clean everything
- symtable_clean();
- ast_delete(game_node);
- // success!
- return 0;
- }
- %}
- /* keywords */
- %token DD_KEYWORD_INT DD_KEYWORD_FLOAT DD_KEYWORD_STRUCT DD_KEYWORD_OVERRIDE DD_KEYWORD_IF DD_KEYWORD_VOID
- /* internal variables */
- %token DD_INTERNAL_WIDTH DD_INTERNAL_HEIGHT
- /* constants */
- %token DD_CONSTANT_SYMBOL DD_CONSTANT_STRING DD_CONSTANT_NUMBER
- /* operators */
- %token DD_OPERATOR_EQ DD_OPERATOR_LE DD_OPERATOR_GE
- /* associativity */
- %left '='
- %left '+' '-'
- %left '*' '/'
- %left '>' '<' DD_OPERATOR_EQ DD_OPERATOR_LE DD_OPERATOR_GE
- %%
- /* each rule creates a node,
- * possibly with children nodes,
- * all non-terminals are nodes that can be obtained with ast_pop() (left to right)
- */
- /* the game itself, contains statements
- */
- game:
- statements {
- ast_child_add(game_node, ast_pop());
- }
- ;
- statements:
- statement statements_additional {
- // add statement to group
- struct ast_node *group = ast_pop();
- struct ast_node *statement = ast_pop();
- ast_child_add_first(group, statement);
- ast_push(group);
- }
- ;
- statements_additional:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- | statement statements_additional {
- // add statement to group
- struct ast_node *group = ast_pop();
- struct ast_node *statement = ast_pop();
- ast_child_add_first(group, statement);
- ast_push(group);
- }
- ;
- statement:
- /* definition statement
- */
- definition
- |
- /* define struct
- * takes all definitions, and adds them to the struct table
- */
- DD_KEYWORD_STRUCT DD_CONSTANT_SYMBOL struct_parent '{' definitions '}' ';' {
- // get symbol in symbol table
- struct entry *e = symtable_entryat($2);
- if (!e) {
- fprintf(stderr, "yacc: struct definition: could not find symtable entry at %d\n", $2);
- exit(-1);
- }
- // check if its already defined, if not define it, if yes error
- if (e->token == DD_CONSTANT_SYMBOL) {
- e->token = DD_KEYWORD_STRUCT;
- }
- else {
- snprintf(buffer, DD_BUFFER_SIZE, "'%s' is already defined", e->lexptr);
- yyerror(buffer);
- }
- // create new struct entry based on symbol table
- struct struct_entry se;
- se.name = e->lexptr;
- se.parent = 0;
- // group node has all definitions
- struct ast_node *group = ast_pop();
- // if parent exists
- struct ast_node *parent = ast_pop();
- if (parent->node_type == AST_STRUCT_PARENT) {
- se.parent = parent->value;
- }
- else {
- se.parent = -1;
- }
- int struct_index = struct_insert(&se);
- // create struct node and add definitions as child
- /*
- group->node_type = AST_STRUCT;
- group->value = struct_index;
- */
- struct ast_node *n = ast_create(AST_STRUCT, struct_index);
- ast_child_add(n, group);
- // push to ast tree
- ast_push(n);
- }
- |
- /* if statement */
- DD_KEYWORD_IF '(' expression ')' '{' statements '}' {
- struct ast_node *expression;
- struct ast_node *statements;
- struct ast_node *ifnode = ast_create(AST_IF, 0);
- statements = ast_pop();
- expression = ast_pop();
- ast_child_add(ifnode, expression);
- ast_child_add(ifnode, statements);
- ast_push(ifnode);
- }
- |
- expression ';' {
- struct ast_node *group = ast_create(AST_GROUP_STATEMENTS, 0);
- ast_child_add(group, ast_pop());
- ast_push(group);
- }
- ;
- definitions:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- | definitions definition {
- struct ast_node *n;
- struct ast_node *c;
- c = ast_pop();
- n = ast_pop();
- ast_child_add(n, c);
- ast_push(n);
- }
- ;
- definition:
- /* definition
- * define a new variable
- * error if variable is already defined
- */
- variable_type DD_CONSTANT_SYMBOL ';' {
- // get variable type
- struct ast_node *vartype = ast_pop();
- // get symbol in symbol table
- struct entry *e = symtable_entryat($2);
- if (!e) {
- fprintf(stderr, "yacc: variable definition: could not find symtable entry at %d\n", $2);
- exit(-1);
- }
- // check if its already defined, if not define it, if yes error
- if (e->token == DD_CONSTANT_SYMBOL) {
- // variable type is void
- if (vartype->node_type == AST_VARTYPE_VOID) {
- e->token = DD_KEYWORD_VOID;
- }
- else
- // variable type is an int
- if (vartype->node_type == AST_VARTYPE_INT) {
- e->token = DD_KEYWORD_INT;
- }
- else
- // variable type is a float
- if (vartype->node_type == AST_VARTYPE_FLOAT) {
- e->token = DD_KEYWORD_FLOAT;
- }
- else
- // variable type is a struct
- if (vartype->node_type == AST_VARTYPE_STRUCT) {
- e->token = DD_KEYWORD_STRUCT;
- e->value = vartype->value;
- }
- }
- else {
- snprintf(buffer, DD_BUFFER_SIZE, "'%s' is already defined", e->lexptr);
- yyerror(buffer);
- }
- // create a definition node
- struct ast_node *n = ast_create(AST_DEFINITION, 0);
- // that has the to-be defined variable as child
- struct ast_node *c = ast_create(AST_IDENTIFIER, $2);
- ast_child_add(n, c);
- // add it to the game
- ast_push(n);
- }
- |
- /* function definition */
- variable_type DD_CONSTANT_SYMBOL '(' function_arguments_decleration ')' '{' statements '}' ';' {
- // get variable type
- struct ast_node *statements = ast_pop();
- struct ast_node *arguments = ast_pop();
- struct ast_node *vartype = ast_pop();
- struct entry *function = symtable_entryat($2);
- if (!function) {
- fprintf(stderr, "yacc: function definition: could not find symtable entry at %d\n", $2);
- exit(-1);
- }
- function->value = 0;
- struct ast_node *n = ast_create(AST_FUNCTION_DEFINITION, $2);
- ast_child_add(n, arguments);
- ast_child_add(n, statements);
- ast_push(n);
- }
- |
- DD_KEYWORD_OVERRIDE variable_type DD_CONSTANT_SYMBOL '(' function_arguments_decleration ')' '{' statements '}' ';' {
- // get variable type
- struct ast_node *statements = ast_pop();
- struct ast_node *arguments = ast_pop();
- struct ast_node *vartype = ast_pop();
- struct entry *function = symtable_entryat($3);
- if (!function) {
- fprintf(stderr, "yacc: override function definition: could not find symtable entry at %d\n", $3);
- exit(-1);
- }
- function->value = 1;
- struct ast_node *n = ast_create(AST_FUNCTION_DEFINITION, $3);
- ast_child_add(n, arguments);
- ast_child_add(n, statements);
- ast_push(n);
- }
- ;
- expression:
- expression '=' expression {
- struct ast_node *n = ast_create(AST_ASSIGNMENT, '=');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression '>' expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, '>');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression '<' expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, '<');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression DD_OPERATOR_EQ expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, DD_OPERATOR_EQ);
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression DD_OPERATOR_LE expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, DD_OPERATOR_LE);
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression DD_OPERATOR_GE expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, DD_OPERATOR_GE);
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression '+' expression {
- struct ast_node *n = ast_create( AST_OPERATOR_BINARY, '+');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression '-' expression {
- struct ast_node *n = ast_create( AST_OPERATOR_BINARY, '-');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression '*' expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, '*');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- expression '/' expression {
- struct ast_node *n = ast_create(AST_OPERATOR_BINARY, '/');
- struct ast_node *exp = ast_pop();
- struct ast_node *term = ast_pop();
- ast_child_add(n, term);
- ast_child_add(n, exp);
- ast_push(n);
- }
- |
- '(' expression ')' {
- struct ast_node *n = ast_create(AST_GROUP_EXPRESSIONS, 0);
- struct ast_node *child = ast_pop();
- ast_child_add(n, child);
- ast_push(n);
- }
- |
- factor
- ;
- factor:
- DD_CONSTANT_NUMBER { ast_push( ast_create(AST_NUMBER, $1) ); }
- |
- DD_CONSTANT_STRING { ast_push( ast_create(AST_STRING, $1) ); }
- |
- variable optional_variable_function {
- struct ast_node *arguments = ast_pop();
- struct ast_node *variable = ast_pop();
- if (arguments->node_type == AST_EMPTY) {
- ast_push(variable);
- }
- else {
- struct ast_node *n = ast_create(AST_FUNCTION_CALL, variable->value);
- ast_child_add(n, variable);
- ast_child_add(n, arguments);
- ast_push(n);
- }
- }
- ;
- variable_type:
- DD_KEYWORD_VOID { $$ = DD_KEYWORD_VOID; ast_push( ast_create(AST_VARTYPE_VOID, 0) ); }
- |
- DD_KEYWORD_INT { $$ = DD_KEYWORD_INT; ast_push( ast_create(AST_VARTYPE_INT, 0) ); }
- |
- DD_KEYWORD_FLOAT { $$ = DD_KEYWORD_FLOAT; ast_push( ast_create(AST_VARTYPE_FLOAT, 0) ); }
- |
- DD_KEYWORD_STRUCT DD_CONSTANT_SYMBOL {
- $$ = DD_KEYWORD_STRUCT;
- struct entry *e = symtable_entryat($2);
- if (!e) {
- fprintf(stderr, "yacc: struct variable type: could not find symtable entry at %d\n", $2);
- exit(-1);
- }
- ast_push( ast_create(AST_VARTYPE_STRUCT, struct_lookup(e->lexptr)) );
- }
- ;
- struct_parent:
- { ast_push( ast_create(AST_EMPTY, 0) ); }
- |
- ':' DD_CONSTANT_SYMBOL {
- struct entry *e = symtable_entryat($2);
- if (!e) {
- fprintf(stderr, "yacc: struct parent variable type: could not find symtable entry at %d\n", $2);
- exit(-1);
- }
- ast_push( ast_create(AST_STRUCT_PARENT, struct_lookup(e->lexptr)) );
- }
- ;
- optional_variable_function:
- { ast_push( ast_create(AST_EMPTY, 0) ); }
- |
- '(' function_arguments_call ')' {
- }
- ;
- variable:
- DD_CONSTANT_SYMBOL {
- ast_push( ast_create(AST_IDENTIFIER, $1 ));
- }
- variable_additional
- ;
- variable_additional:
- | variable_additional '.' DD_CONSTANT_SYMBOL {
- struct ast_node *n = ast_pop();
- ast_child_add(n, ast_create(AST_IDENTIFIER, $3));
- ast_push(n);
- $$ = $3;
- }
- ;
- function_arguments_decleration:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- |
- variable_type DD_CONSTANT_SYMBOL function_arguments_decleration_additional {
- struct ast_node *n = ast_pop();
- struct ast_node *vartype = ast_pop();
- struct entry *esymbol = symtable_entryat($2);
- if (!esymbol) {
- fprintf(stderr, "yacc: function arguments declaration: could not find symtable entry at %d\n", $2);
- exit(-1);
- }
- esymbol->token = $1;
- ast_child_add_first(n, ast_create(AST_IDENTIFIER, $2));
- ast_push(n);
- }
- ;
- function_arguments_decleration_additional:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- |
- ',' variable_type DD_CONSTANT_SYMBOL function_arguments_decleration_additional {
- struct ast_node *n = ast_pop();
- struct ast_node *vartype = ast_pop();
- struct entry *esymbol = symtable_entryat($3);
- if (!esymbol) {
- fprintf(stderr, "yacc: function arguments declaration: could not find symtable entry at %d\n", $3);
- exit(-1);
- }
- esymbol->token = $2;
- ast_child_add_first(n, ast_create(AST_IDENTIFIER, $3));
- ast_push(n);
- }
- ;
- function_arguments_call:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- |
- expression function_arguments_call_additional {
- struct ast_node *n = ast_pop();
- struct ast_node *expression = ast_pop();
- ast_child_add_first(n, expression);
- ast_push(n);
- }
- ;
- function_arguments_call_additional:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- |
- ',' expression function_arguments_call_additional {
- struct ast_node *n = ast_pop();
- struct ast_node *expression = ast_pop();
- ast_child_add_first(n, expression);
- ast_push(n);
- }
- ;
|