Facebook
From Walloping Coyote, 3 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 47
  1. %{
  2.   #include <stdio.h>
  3.   #include <stdlib.h>
  4.   #include "defs.h"
  5.   #include "symtab.h"
  6.   #include "codegen.h"
  7.  
  8.   int yyparse(void);
  9.   int yylex(void);
  10.   int yyerror(char *s);
  11.   void warning(char *s);
  12.  
  13.   extern int yylineno;
  14.   int out_lin = 0;
  15.   char char_buffer[CHAR_BUFFER_LENGTH];
  16.   int error_count = 0;
  17.   int warning_count = 0;
  18.   int var_num = 0;
  19.   int fun_idx = -1;
  20.   int fcall_idx = -1;
  21.         int pamti;
  22.   int lab_num = -1;
  23.   FILE *output;
  24. %}
  25.  
  26. %union {
  27.   int i;
  28.   char *s;
  29. }
  30.  
  31. %token <i> _TYPE
  32. %token _IF
  33. %token _ELSE
  34. %token _RETURN
  35. %token <s> _ID
  36. %token <s> _INT_NUMBER
  37. %token <s> _UINT_NUMBER
  38. %token _LPAREN
  39. %token _RPAREN
  40. %token _LBRACKET
  41. %token _RBRACKET
  42. %token _ASSIGN
  43. %token _SEMICOLON
  44. %token <i> _AROP
  45. %token <i> _RELOP
  46. %token _COMMA
  47. %token _INC
  48. %token _HANA
  49. %token _LOOP
  50. %token _HOPAU
  51. %token _OIAI
  52. %token _OTVORENO
  53. %token _ZATVORENO
  54.  
  55. %token _SWITCH
  56. %token _CASE
  57. %token _BREAK
  58. %token _DEFAULT
  59. %token _END_SWITCH
  60.  
  61. %type <i> num_exp if_part exp literal function_call argument rel_exp increment increment_stmt return_statement
  62.  
  63. %nonassoc ONLY_IF
  64. %nonassoc _ELSE
  65.  
  66. %%
  67.  
  68. program
  69.   : global_list function_list
  70.       { // proverimo da li postoji main funkcija, ukoliko ne postoji izbacujemo gresku
  71.         if(lookup_symbol("main", FUN) == NO_INDEX)
  72.           err("undefined reference to 'main'");
  73.        }
  74.   ;
  75.  
  76. global_list
  77.         : /* prazno */
  78.         | global_list global_var
  79.         ;
  80.  
  81. global_var
  82.         : _TYPE _ID _SEMICOLON
  83.         {
  84.                 int idx = lookup_symbol($2, GVAR);
  85.                 if (idx != NO_INDEX)
  86.                 {
  87.                                 err("redefinition of '%s'", $2);
  88.                 } else {
  89.                         insert_symbol($2, GVAR, $1, NO_ATR, NO_ATR);
  90.                         code("\n%s:\n\t\tWORD\t1", $2);
  91.                 }
  92.         }
  93.         ;
  94.  
  95. function_list
  96.   : function
  97.   | function_list function
  98.   ;
  99.  
  100. function
  101.   : _TYPE _ID
  102.       {
  103.         fun_idx = lookup_symbol($2, FUN);
  104.         if(fun_idx == NO_INDEX)
  105.           fun_idx = insert_symbol($2, FUN, $1, NO_ATR, NO_ATR);
  106.         else
  107.           err("redefinition of function '%s'", $2);
  108.  
  109.                 code("\n%s:", $2);
  110.         code("\n\t\tPUSH\t%%14");
  111.         code("\n\t\tMOV \t%%15,%%14");
  112.       }
  113.     _LPAREN parameter _RPAREN body
  114.       {
  115.         clear_symbols(fun_idx + 1);
  116.         var_num = 0;
  117.  
  118.                 code("\n@%s_exit:", $2);
  119.         code("\n\t\tMOV \t%%14,%%15");
  120.         code("\n\t\tPOP \t%%14");
  121.         code("\n\t\tRET");
  122.       }
  123.   ;
  124.  
  125. parameter
  126.   : /* empty */
  127.       { set_atr1(fun_idx, 0); }
  128.  
  129.   | _TYPE _ID
  130.       {
  131.                 if ($1 == VOID)
  132.                 err("Ne moze biti tipa void");
  133.         insert_symbol($2, PAR, $1, 1, NO_ATR);
  134.         set_atr1(fun_idx, 1);
  135.         set_atr2(fun_idx, $1);
  136.       }
  137.   ;
  138.  
  139. body
  140.   : _LBRACKET variable_list
  141.           {
  142.         if(var_num)
  143.           code("\n\t\tSUBS\t%%15,$%d,%%15", 4*var_num);
  144.         code("\n@%s_body:", get_name(fun_idx));
  145.       }
  146.     statement_list return_statement _RBRACKET
  147.   ;
  148.  
  149. variable_list
  150.   : /* empty */
  151.   | variable_list variable
  152.   ;
  153.  
  154. variable
  155.   : variabla_ponavljanja _SEMICOLON
  156.   ;
  157.  
  158. variabla_ponavljanja //zadatak 3.
  159.         : _TYPE _ID {
  160.                                 if ($1 == VOID)
  161.                                         err("ne moze biti void");
  162.                                 pamti = lookup_symbol($2, VAR|PAR);
  163.         if(pamti == -1)
  164.            pamti = insert_symbol($2, VAR, $1, ++var_num, NO_ATR);
  165.         else
  166.            err("redefinition of '%s'", $2);
  167.       }
  168.         | variabla_ponavljanja _COMMA _ID {
  169.         if(lookup_symbol($3, VAR|PAR) == NO_INDEX)
  170.            insert_symbol($3, VAR, get_type(pamti), ++var_num, NO_ATR);
  171.         else
  172.            err("redefinition of '%s'", $3);
  173.       }
  174.         ;
  175.  
  176. statement_list
  177.   : /* empty */
  178.   | statement_list statement
  179.   ;
  180.  
  181. statement
  182.   : compound_statement
  183.   | assignment_statement
  184.   | if_statement
  185.   | increment_stmt
  186.   | hana_oiai
  187.   | switch_case
  188.   ;
  189.  
  190. switch_case
  191.   :  _SWITCH _ID
  192.         {
  193.                                         int r = lookup_symbol($2,VAR|PAR);
  194.                                         if( r  == NO_INDEX)
  195.                                                 err("nedefinisana varijabla '%s'", $2);
  196.                                 }
  197.       case_body
  198.                                 {
  199.                                         int r = lookup_symbol($2,VAR|PAR);
  200.                                         if(get_type(r) != get_type($<i>4)) err("nekompatibilan tip u case naredbi");
  201.                                 }
  202.      _DEFAULT  statement _END_SWITCH
  203.   ;
  204.  
  205. case_body
  206.   : _CASE literal statement _BREAK _SEMICOLON
  207.                 {
  208.                         $<i>$ = $<i>2;
  209.                 }
  210.   | case_body _CASE literal statement
  211.                 {
  212.                         if(get_type($<i>3) != get_type($<i>1)) err("nekompatibilan tip u case naredbi");
  213.                         $<i>$ = $<i>1;
  214.                 }
  215.   ;
  216.  
  217. hana_oiai
  218.         : _OTVORENO _HANA _LOOP statement _HOPAU _OIAI _LPAREN rel_exp _RPAREN _ZATVORENO _SEMICOLON
  219.         ;
  220.  
  221. compound_statement
  222.   : _LBRACKET statement_list _RBRACKET
  223.   ;
  224.  
  225. assignment_statement
  226.   : _ID _ASSIGN num_exp _SEMICOLON
  227.       {
  228.         int idx = lookup_symbol($1, VAR|PAR|GVAR);
  229.         if(idx == NO_INDEX)
  230.           err("invalid lvalue '%s' in assignment", $1);
  231.         else
  232.           if(get_type(idx) != get_type($3))
  233.             err("incompatible types in assignment");
  234.                 set_atr2(idx, 1);
  235.                 gen_mov($3, idx);
  236.       }
  237.   ;
  238.  
  239. increment_stmt
  240.        
  241.         :increment _SEMICOLON
  242.         ;
  243.  
  244. increment
  245.         : _ID _INC
  246.                         {
  247.                                 int idx = lookup_symbol($1, VAR|PAR|GVAR|FUN);
  248.         if( idx == -1)
  249.                                         err("nedeklarisana vrednost '%s' za inkrementovanje", $1);              // ne postoji varijabla
  250.                           else if (get_kind(idx) == FUN)
  251.                                 err("ne moze se inkrementovati funkcija");   // nije moguce inkrementovati funkciju
  252.                                
  253.                 int reg = take_reg();
  254.  
  255.                  gen_mov(idx, reg);
  256.                
  257.                   if(get_type(idx) == INT)
  258.                    code("\n\t\tADDS\t");
  259.                  else
  260.                    code("\n\t\tADDU\t");
  261.    
  262.                   gen_sym_name(idx);
  263.                  code(", $1, ");
  264.                   gen_sym_name(idx);
  265.  
  266.                           $$=reg;
  267.                         }
  268.         ;
  269.  
  270.  
  271. num_exp
  272.   : exp
  273.   | num_exp _AROP exp
  274.       {
  275.         if(get_type($1) != get_type($3))
  276.           err("invalid operands: arithmetic operation");
  277.                                 int t1 = get_type($1);    
  278.         code("\n\t\t%s\t", ar_instructions[$2 + (t1 - 1) * AROP_NUMBER]);
  279.         gen_sym_name($1);
  280.         code(",");
  281.         gen_sym_name($3);
  282.         code(",");
  283.           free_if_reg($1);
  284.         free_if_reg($3);
  285.    
  286.         $$ = take_reg();
  287.         gen_sym_name($$);
  288.         set_type($$, t1);
  289.  
  290.              
  291.       }
  292.   ;
  293.  
  294. exp
  295.   : literal
  296.   | _ID
  297.       {
  298.         $$ = lookup_symbol($1, VAR|PAR|GVAR);
  299.         if($$ == NO_INDEX)
  300.           err("'%s' undeclared", $1);
  301.       }
  302.         | increment
  303.                         {
  304.                                 $$ = 1;
  305.                                
  306.                         }
  307.   | function_call
  308.          {
  309.         $$ = take_reg();
  310.         gen_mov(FUN_REG, $$);
  311.       }
  312.   | _LPAREN num_exp _RPAREN
  313.       { $$ = $2; }
  314.   ;
  315.  
  316. literal
  317.   : _INT_NUMBER
  318.       { $$ = insert_literal($1, INT); }
  319.  
  320.   | _UINT_NUMBER
  321.       { $$ = insert_literal($1, UINT); }
  322.   ;
  323.  
  324. function_call
  325.   : _ID
  326.       {
  327.         fcall_idx = lookup_symbol($1, FUN);
  328.         if(fcall_idx == NO_INDEX)
  329.           err("'%s' is not a function", $1);
  330.       }
  331.     _LPAREN argument _RPAREN
  332.       {
  333.         if(get_atr1(fcall_idx) != $4)
  334.           err("wrong number of args to function '%s'", get_name(fcall_idx));
  335.                                         code("\n\t\t\tCALL\t%s", get_name(fcall_idx));
  336.         if($4 > 0)
  337.           code("\n\t\t\tADDS\t%%15,$%d,%%15", $4 * 4);
  338.         set_type(FUN_REG, get_type(fcall_idx));
  339.         $$ = FUN_REG;
  340.       }
  341.   ;
  342.  
  343. argument
  344.   : /* empty */
  345.     { $$ = 0; }
  346.  
  347.   | num_exp
  348.     {
  349.        if(get_atr2(fcall_idx) != get_type($1))
  350.         err("incompatible type for argument");
  351.       free_if_reg($1);
  352.       code("\n\t\t\tPUSH\t");
  353.       gen_sym_name($1);
  354.       $$ = 1;
  355.     }
  356.   ;
  357.  
  358. if_statement
  359.   : if_part %prec ONLY_IF
  360.           { code("\n@exit%d:", $1); }
  361.   | if_part _ELSE statement
  362.       { code("\n@exit%d:", $1); }
  363.   ;
  364.  
  365. if_part
  366.   : _IF _LPAREN
  367.           {
  368.         $<i>$ = ++lab_num;
  369.         code("\n@if%d:", lab_num);
  370.       }
  371.   rel_exp
  372.           {
  373.         code("\n\t\t%s\t@false%d", opp_jumps[$4], $<i>3);
  374.         code("\n@true%d:", $<i>3);
  375.       }
  376.   _RPAREN statement
  377.           {
  378.         code("\n\t\tJMP \t@exit%d", $<i>3);
  379.         code("\n@false%d:", $<i>3);
  380.         $$ = $<i>3;
  381.       }
  382.   ;
  383.  
  384. rel_exp
  385.   : num_exp _RELOP num_exp
  386.       {
  387.         if(get_type($1) != get_type($3))
  388.           err("invalid operands: relational operator");
  389.                  $$ = $2 + ((get_type($1) - 1) * RELOP_NUMBER);
  390.         gen_cmp($1, $3);
  391.       }
  392.   ;
  393.  
  394. return_statement
  395.   : _RETURN num_exp _SEMICOLON
  396.       {
  397.                                 if (get_type($2) == VOID)
  398.                                         err("void funkcija ne vraca vrednost");
  399.         else if(get_type(fun_idx) != get_type($2))
  400.           err("incompatible types in return");
  401.        
  402.                                 gen_mov($2, FUN_REG);
  403.         code("\n\t\tJMP \t@%s_exit", get_name(fun_idx));        
  404.                        
  405.                 }
  406.         | _RETURN _SEMICOLON //9. zad
  407.             {
  408.                                                                 if(get_type(fun_idx) == UINT || get_type(fun_idx) == INT)
  409.                 warning("za int i uint funkcije treba vratiti vrednost");
  410.             }
  411.         | //prazno
  412.         {
  413.           if(get_type(fun_idx) != VOID)
  414.            {
  415.                 warn("funkcije koje nisu void treba da vracaju vrednost");
  416.            }
  417.         }
  418.   ;
  419.  
  420.  
  421. %%
  422.  
  423. int yyerror(char *s) {
  424.   fprintf(stderr, "\nline %d: ERROR: %s", yylineno, s);
  425.   error_count++;
  426.   return 0;
  427. }
  428.  
  429. void warning(char *s) {
  430.   fprintf(stderr, "\nline %d: WARNING: %s", yylineno, s);
  431.   warning_count++;
  432. }
  433.  
  434. int main() {
  435.   int synerr;
  436.   init_symtab();
  437.   output = fopen("output.asm", "w+");
  438.  
  439.   synerr = yyparse();
  440.  
  441.   clear_symtab();
  442.   fclose(output);
  443.  
  444.   if(warning_count)
  445.     printf("\n%d warning(s).\n", warning_count);
  446.  
  447.   if(error_count) {
  448.     remove("output.asm");
  449.     printf("\n%d error(s).\n", error_count);
  450.   }
  451.  
  452.   if(synerr)
  453.     return -1;  //syntax error
  454.   else if(error_count)
  455.     return error_count & 127; //semantic errors
  456.   else if(warning_count)
  457.     return (warning_count & 127) + 127; //warnings
  458.   else
  459.     return 0; //OK
  460. }
  461.