%{ #include #include #include #include "forthlib.c" #include "symtab.h" #include "strlist.h" int yylex() ; void yyerror(const char *s) { fprintf(stderr, "yyerror: %s\n", s) ; exit(1) ; } FILE *of ; int global_var_no = 0 ; int global_str_no = 0 ; int global_label_no = 0 ; %} %union { char *strval ; int ival ; st_type tval ; } %token NAME STRING PROGRAM %token NUMBER BOOLEAN %token PRINT PRINTLN %token VAR BOOL INT FLOAT %token ASSIGN %left AND OR %nonassoc LT LE GT GE EQ NE %left '+' '-' %left '*' '/' %nonassoc UMINUS %nonassoc '!' %type assignment %type print_statement %type expression declaration type %% program : PROGRAM { fprintf(of,": __Main__\n" ) ; } statement_list { fprintf(of, ";\n\n") ; fprintf(of, "__Main__\n") ; fprintf(of, "bye\n") ; } ; statement_list : statement_list statement | statement ; statement: declaration | assignment | print_statement ; declaration: VAR '{' type '}' NAME ';' { // fprintf(stderr, "Variable %s delcared.\n", $5) ; st_entry s ; s.type = $3 ; s.var_no = global_var_no++ ; st_insert($5, s) ; // fprintf(of, "VARIABLE %s\n", $5) ; free($5) ; } ; type : BOOL { $$ = bool_type ; } | INT { $$ = int_type ; } ; /* Assignment rules */ assignment: NAME ASSIGN expression ';' { st_entry *p ; /* fprintf(stderr, "Assignment for variable %s.\n", $1) ; st_dump() ; */ p = st_find($1) ; if (p == NULL) { fprintf(stderr, "Error! Undeclared variable: %s\n", $1) ; } else if ($3 != p->type) { fprintf(stderr, "Error! Incompatible types\n") ; } else { fprintf(of, "__Local_Vars__ %d CELLS + ( %s ) !\n", p->var_no, $1) ; } free($1) ; } ; /* End Assignment expression rules */ print_statement: PRINT expression ';' { if ($2 == bool_type) { fprintf(of, "0= IF .\" false\" ELSE .\" true\" THEN\n") ; } else { fprintf(of, ".\n") ; } } | PRINTLN expression ';' { if ($2 == bool_type) { fprintf(of, "0= IF .\" false\" ELSE .\" true\" THEN CR\n") ; } else { fprintf(of, ". CR\n") ; } } | PRINT STRING ';' { // fprintf(stderr, "Printing literal string %s.\n", $2) ; strlist_append(global_str_no, $2) ; global_str_no++ ; fprintf(of, ".\" %s\"\n", $2) ; free($2) ; } | PRINTLN STRING ';' { // fprintf(stderr, "Printing literal string %s.\n", $2) ; strlist_append(global_str_no, $2) ; global_str_no++ ; fprintf(of, ".\" %s\" CR\n", $2) ; free($2) ; } ; /* Arithmetic expression rules */ expression: '(' expression ')' { $$ = $2 ; } | expression '+' expression { if ($1 == int_type && $3 == int_type) { fprintf (of, "+ ") ; $$ = int_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } | expression '-' expression { if ($1 == int_type && $3 == int_type) { fprintf (of, "- ") ; $$ = int_type ; } else { fprintf(stderr, "Error: types not compatible with binary '-' operation.\n") ; } } | expression '*' expression { if ($1 == int_type && $3 == int_type) { fprintf (of, "* ") ; $$ = int_type ; } else { fprintf(stderr, "Error: types not compatible with '*' operation.\n") ; } } | expression '/' expression { if ($1 == int_type && $3 == int_type) { fprintf (of, "/ ") ; $$ = int_type ; } else { fprintf(stderr, "Error: types not compatible with '/' operation.\n") ; } } | '-' expression %prec UMINUS { if ($2 == int_type) { fprintf (of, " negate ") ; $$ = int_type ; } else { fprintf(stderr, "Error: types not compatible with unary '-' operation.\n") ; } } | NUMBER { $$ = int_type ; fprintf (of, "%d ", $1) ; } | BOOLEAN { $$ = bool_type ; fprintf (of, "%d ", $1) ; } | NAME { st_entry *p ; p = st_find($1) ; if (p == NULL) { fprintf(stderr, "Error: Undeclared variable: %s\n", $1) ; } else { fprintf(of, "__Local_Vars__ %d CELLS + ( %s ) @ ", p->var_no, $1) ; $$ = p->type ; } free($1) ; } ; /* End Arithmetic expression rules */ /* Comparison expression rules */ expression: expression LE expression { if ($1 == int_type && $3 == int_type) { fprintf(of, "<= ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } | expression LT expression { if ($1 == int_type && $3 == int_type) { fprintf(of, "< ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } | expression GE expression { if ($1 == int_type && $3 == int_type) { fprintf(of, ">= ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } | expression GT expression { if ($1 == int_type && $3 == int_type) { fprintf(of, "> ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } | expression EQ expression { if ($1 == int_type && $3 == int_type) { fprintf(of, "= ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } | expression NE expression { if ($1 == int_type && $3 == int_type) { fprintf(of, "<> ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '+' operation.\n") ; } } ; /* End Comparison expression rules */ /* Logical expression rules */ expression: expression AND expression { if ($1 == bool_type && $3 == bool_type) { fprintf(of, "AND ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '&&' operation.\n") ; } } | expression OR expression { if ($1 == bool_type && $3 == bool_type) { fprintf(of, "OR ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '||' operation.\n") ; } } | '!' expression { if ($2 == bool_type) { fprintf(of, "0= ") ; $$ = bool_type ; } else { fprintf(stderr, "Error: types not compatible with '!' operation.\n") ; } } ; /* End Logical expression rules */ %% int main () { /* Set up symbol table and string list */ st_init() ; /* Currently does nothing */ strlist_init() ; // fprintf (stderr, "Type in a program\n") ; of = fopen ("out.fs", "w") ; assert(of != NULL) ; fprintf (of, "%s\n", forth_prolog) ; yyparse() ; fclose(of) ; strlist_destroy() ; return 0 ; } /* End of main() */