123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- %{
- #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;
- // init data, parse, exit
- int main(int argc, char *argv[])
- {
- if (argc <= 1) {
- printf("arg 1 should be output file\n");
- return -1;
- }
- // init data
- linenum = 1;
- symtable_init();
- symtable_insert("DD_WIDTH", DD_INTERNAL_WIDTH);
- symtable_insert("DD_HEIGHT", DD_INTERNAL_HEIGHT);
- 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);
- struct_print();
- // print debug data and clean everything
- symtable_print();
- symtable_clean();
- ast_print(game_node);
- 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 '>' '<' 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:
- { ast_push( ast_create(AST_GROUP, 0) ); }
- | statements statement {
- // add statement to game
- //ast_child_add(game_node, ast_pop());
- struct ast_node *n;
- struct ast_node *c;
- c = ast_pop();
- n = ast_pop();
- ast_child_add(n, c);
- ast_push(n);
- }
- 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);
- // 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 = symtable_entryat($2)->lexptr;
- se.parent = 0;//struct_lookup(se.name);
- // 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);
- }
- |
- /* assign
- * change the value of a variable
- * error if variable is not defined yet
- */
- variable '=' expression ';' {
- // get symbol in symbol table
- struct entry *e = symtable_entryat($1);
- // if variable is not defined, error
- if (e->token == DD_CONSTANT_SYMBOL && strcmp(e->lexptr, "this") != 0) {
- snprintf(buffer, DD_BUFFER_SIZE, "'%s' is not defined", e->lexptr);
- yyerror(buffer);
- }
- // create an 'assign' node
- struct ast_node *n = ast_create(AST_ASSIGNMENT, 0);
- // with first child the variable to be assigned some value
- struct ast_node *c2 = ast_pop();
- struct ast_node *c1 = ast_pop();
- ast_child_add(n, c1);
- // and second child the result (probably an expression)
- ast_child_add(n, c2);
- // add to game
- ast_push(n);
- }
- |
- /* function call */
- variable '(' ')' ';' {
- struct ast_node *variable = ast_pop();
- struct ast_node *n = ast_create(AST_FUNCTION_CALL, 0);
- ast_child_add(n, variable);
- 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);
- }
- ;
- 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);
- // 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 ')' '{' statements '}' ';' {
- // get variable type
- struct ast_node *statements = ast_pop();
- struct ast_node *arguments = ast_pop();
- struct ast_node *vartype = ast_pop();
- 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 ')' '{' 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);
- 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 {
- int operator = AST_MORE_THAN;
- struct ast_node *n = ast_create(operator, 0);
- 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 {
- int operator = AST_LESS_THAN;
- struct ast_node *n = ast_create(operator, 0);
- 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 {
- int operator = AST_EQUAL;
- struct ast_node *n = ast_create(operator, 0);
- 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 {
- int operator = AST_LESS_EQUAL;
- struct ast_node *n = ast_create(operator, 0);
- 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 {
- int operator = AST_MORE_EQUAL;
- struct ast_node *n = ast_create(operator, 0);
- 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_ADDITION, 0);
- 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_SUBSTRACTION, 0);
- 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_MULTIPLICATION, 0);
- 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_DIVISION, 0);
- 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) ); }
- |
- variable
- |
- DD_CONSTANT_STRING { ast_push( ast_create(AST_STRING, $1) ); }
- ;
- 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; ast_push( ast_create(AST_VARTYPE_STRUCT, struct_lookup(symtable_entryat($2)->lexptr)) ); }
- ;
- struct_parent:
- { ast_push( ast_create(AST_EMPTY, 0) ); }
- |
- ':' DD_CONSTANT_SYMBOL { ast_push( ast_create(AST_STRUCT_PARENT, struct_lookup(symtable_entryat($2)->lexptr)) ); }
- ;
- 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:
- { ast_push( ast_create(AST_EMPTY, 0) ); }
- | variable_type DD_CONSTANT_SYMBOL function_additional_argument {
- struct entry *e = symtable_entryat($2);
- e->token = $1;
- struct ast_node *n = ast_pop();
- ast_pop(); // waste variable_type for now
- ast_child_add(n, ast_create(AST_ARGUMENT, $2));
- ast_push(n);
- }
- ;
- function_additional_argument:
- { ast_push( ast_create(AST_ARGUMENTS, 0) ); }
- | ',' variable_type DD_CONSTANT_SYMBOL function_additional_argument {
- struct ast_node *n = ast_pop();
- ast_pop(); // waste variable_type for now
- ast_child_add(n, ast_create(AST_ARGUMENT, $3));
- ast_push(n);
- }
- ;
|