Facebook
From Soft Ostrich, 3 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 65
  1. %{
  2.   #include <stdio.h>
  3.   #include <stdlib.h>
  4.   #include <string.h>
  5.   #include "defs.h"
  6.   #include "symtab.h"
  7.   #include "codegen.h"
  8.  
  9.   int yyparse(void);
  10.   int yylex(void);
  11.   int yyerror(char *s);
  12.   void warning(char *s);
  13.  
  14.   extern int yylineno;
  15.   int out_lin = 0;
  16.   char char_buffer[CHAR_BUFFER_LENGTH];
  17.   int error_count = 0;
  18.   int warning_count = 0;
  19.   int var_num = 0;
  20.   int fun_idx = -1;
  21.   int fcall_idx = -1;
  22.   int lab_num = -1;
  23.   FILE *output;
  24.   int tip;
  25.   int isReturn=0;
  26.   int reg = -1;
  27.   int checkId = -1;
  28.   int checkVar = -1;
  29.   int caseVal = -1;
  30.   int current_block_var = -1;
  31.   int block_idx = -1;
  32.   int param_cnt = 0;
  33.   int args_cnt = 0;
  34.   int arg_val = 0;
  35.   int declarationIdx = -1;
  36.   int check_type = 0;
  37.   int checkIdx = 0;
  38.   char checkLiteralts[100][10];
  39.   int numberOfLitInCheck = -1;
  40. %}
  41.  
  42. %union {
  43.   int i;
  44.   char *s;
  45. }
  46.  
  47. %token <i> _TYPE
  48. %token _IF
  49. %token _ELSE
  50. %token _RETURN
  51. %token <s> _ID
  52. %token <s> _INT_NUMBER
  53. %token <s> _UINT_NUMBER
  54. %token _LPAREN
  55. %token _RPAREN
  56. %token _LBRACKET
  57. %token _RBRACKET
  58. %token _ASSIGN
  59. %token _SEMICOLON
  60. %token _COMMA
  61. %token _INC
  62.  
  63. %token _DVOTACKA
  64. %token _LOOP
  65. %token _PUKA
  66. %token _MANAWA
  67. %token _HOPAU
  68. %token _CHECK
  69. %token _LSQBRACKET
  70. %token _RSQBRACKET
  71. %token _WHEN
  72. %token _ARROW
  73. %token _BREAK
  74. %token _DEFAULT
  75.  
  76. %token _QMARK
  77.  
  78. %token <i> _AROP
  79. %token <i> _RELOP
  80.  
  81. %type <i> num_exp cond_operator exp literal argument_list post_increment when when_list
  82. %type <i> function_call argument rel_exp if_part
  83.  
  84. %nonassoc ONLY_IF
  85. %nonassoc _ELSE
  86.  
  87. %%
  88.  
  89. program
  90.   : global_variable_list function_list
  91.     {  
  92.       if(lookup_symbol("main", FUN) == NO_INDEX)
  93.         err("undefined reference to 'main'");
  94.     }
  95.   ;
  96.  
  97. global_variable_list
  98.   : /*empty*/
  99.   | global_variable_list global_variable
  100.   ;
  101.  
  102. global_variable
  103.   : _TYPE _ID _SEMICOLON
  104.   {
  105.     if(lookup_symbol($2, GVAR) == NO_INDEX)
  106.       insert_symbol($2, GVAR, $1, NO_ATR, NO_ATR);
  107.     else
  108.       err("redefinition of '%s'", $2);
  109.    
  110.     code("\n%s:", $2);
  111.     code("\n\tWORD 1");
  112.   }
  113.   ;
  114.  
  115. function_list
  116.   : function
  117.   | function_list function
  118.   ;
  119.  
  120. function
  121.   : _TYPE _ID
  122.       {
  123.         fun_idx = lookup_symbol($2, FUN);
  124.         if(fun_idx == NO_INDEX)
  125.           fun_idx = insert_symbol($2, FUN, $1, NO_ATR, NO_ATR);
  126.         else
  127.           err("redefinition of function '%s'", $2);
  128.  
  129.         code("\n%s:", $2);
  130.         code("\n\t\tPUSH\t%%14");
  131.         code("\n\t\tMOV \t%%15,%%14");
  132.         param_cnt = 0;
  133.       }
  134.     _LPAREN parameter _RPAREN body
  135.       {
  136.         if(isReturn == 2 && get_type(fun_idx) == VOID)
  137.           err("function should not return value");
  138.  
  139.         else if(isReturn == 1 && get_type(fun_idx) != VOID)
  140.           warn("function should return value");
  141.        
  142.         else if(isReturn == 0 && get_type(fun_idx) != VOID)
  143.           warn("function should return value");
  144.        
  145.         isReturn = 0;
  146.  
  147.         for(int i = fun_idx + 1; i < get_last_element(); i++)
  148.         {
  149.           if(get_atr2(i) == 0 && (get_kind(i) == VAR || get_kind(i) == PAR))
  150.           {
  151.             printf("Variable '%s' not assigned", get_name(i));
  152.           }
  153.         }
  154.  
  155.         clear_symbols(fun_idx + 1);
  156.         var_num = 0;
  157.        
  158.         code("\n@%s_exit:", $2);
  159.         code("\n\t\tMOV \t%%14,%%15");
  160.         code("\n\t\tPOP \t%%14");
  161.         code("\n\t\tRET");
  162.        
  163.       }
  164.   ;
  165.  
  166. parameter
  167.   : /* empty */
  168.       { set_atr1(fun_idx, param_cnt); }
  169.  
  170.   | parametar_list
  171.   ;
  172.  
  173. parametar_list
  174.   : _TYPE _ID
  175.       {
  176.         int idx = insert_symbol($2, PAR, $1, ++param_cnt, NO_ATR);
  177.         set_atr1(fun_idx, param_cnt);
  178.         set_atr2(fun_idx, get_atr2(fun_idx) * 10 + $1);
  179.       }
  180.   | parametar_list _COMMA _TYPE _ID
  181.           {
  182.       int idx = lookup_symbol($4, PAR);
  183.       if(idx == NO_INDEX)
  184.         idx = insert_symbol($4, PAR, $3, ++param_cnt, NO_ATR);
  185.       else
  186.         err("redefinition of '%s'", $4);
  187.  
  188.       set_atr1(fun_idx, param_cnt);
  189.       set_atr2(fun_idx, get_atr2(fun_idx) * 10 + $3);
  190.     }
  191.   ;
  192.  
  193. body
  194.   : _LBRACKET variable_list
  195.       {
  196.         if(var_num)
  197.           code("\n\t\tSUBS\t%%15,$%d,%%15", 4*var_num);
  198.         code("\n@%s_body:", get_name(fun_idx));
  199.       }
  200.     statement_list _RBRACKET
  201.   ;
  202.  
  203.  
  204. variable_list
  205.   : /* empty */
  206.   | variable_list variables
  207.   ;
  208.  
  209. vars
  210.   : _TYPE _ID
  211.   {
  212.     int idx = lookup_symbol($2, VAR|PAR);
  213.     if(idx == NO_INDEX)
  214.       current_block_var = insert_symbol($2, VAR, $1, ++var_num, block_idx);
  215.     else if(idx != NO_INDEX && get_atr2(idx) == block_idx)
  216.       err("redefinition of '%s'", $2);
  217.     else
  218.       current_block_var = insert_symbol($2, VAR, $1, ++var_num, block_idx);
  219.  
  220.     if($1 == VOID)
  221.     {
  222.       err("type of variable cannot be 'void'");
  223.     }
  224.  
  225.     tip = $1;
  226.     declarationIdx = idx;
  227.   }
  228.   | vars _COMMA _ID
  229.   {
  230.     if(lookup_symbol($3, VAR|PAR) == NO_INDEX)
  231.       current_block_var = insert_symbol($3, VAR, tip, ++var_num, block_idx);
  232.     else
  233.       err("redefinition of '%s'", $3);
  234.   }
  235.   ;
  236.  
  237. variables
  238.   : vars _SEMICOLON
  239.   {
  240.    
  241.   }
  242.   |vars _SEMICOLON _ASSIGN literal
  243.   {
  244.     for(int i = declarationIdx; i < get_last_element(); i++)
  245.     {
  246.       set_atr2(i, 1);  //setovana je promenljiva
  247.     }
  248.   }
  249.   ;
  250.  
  251.  
  252. statement_list
  253.   : /* empty */
  254.   | statement_list statement
  255.   ;
  256.  
  257. statement
  258.   : compound_statement
  259.   | assignment_statement
  260.   | if_statement
  261.   | increment_statement
  262.   | return_statement
  263.   | loop_statement
  264.   | check_statement
  265.   ;
  266.  
  267. compound_statement
  268.   : _LBRACKET statement_list _RBRACKET
  269.   ;
  270.  
  271.  
  272. check_statement
  273.   : _CHECK _LSQBRACKET _ID _RSQBRACKET _LBRACKET
  274.         {
  275.           int idx = lookup_symbol($3, VAR|PAR);
  276.  
  277.     if(idx == NO_INDEX)
  278.       err("invalid lvalue '%s' in check", $3);
  279.  
  280.     checkIdx= idx;
  281.  
  282.     code("\n@check%d:",checkIdx);
  283.  
  284.     for(int i = 0; i < 100; i++)
  285.       strcpy(checkLiteralts[i], "");
  286.  
  287.     numberOfLitInCheck = 0;
  288.  
  289.   }
  290.   when_list default _RBRACKET
  291.   {
  292.     code("\n@check_exit%d:",checkIdx);
  293.   }
  294.   ;
  295.  
  296. default
  297.   : /*empty*/
  298.   {
  299.     code("\n@default%d:", checkIdx);
  300.   }
  301.   | _DEFAULT _ARROW
  302.   {
  303.     code("\n@default%d:", checkIdx);
  304.   }
  305.   statement
  306.   ;
  307.  
  308. when
  309.   : _WHEN literal _ARROW
  310.         {
  311.           if(get_type(checkIdx) != get_type($2))
  312.                 err("invalid when expresion in check");
  313.        
  314.           $<i>$ = $2;
  315.     int lit = atoi(get_name($2));
  316.     code("\n@check%d_when%d:", checkIdx, lit);
  317.     gen_cmp(checkIdx, $2);
  318.     code("\n\t\tJEQ\t@check%d_stmt%d", checkIdx, lit);
  319.     code("\n\t\tJMP\t@check%d_stmt%d_exit", checkIdx, lit);
  320.     code("\n@check%d_stmt%d:", checkIdx, lit);
  321.  
  322.     for(int i = 0; i < numberOfLitInCheck; i++)
  323.     {
  324.       if(strcmp(get_name($2), checkLiteralts[i]) == 0)
  325.       {
  326.         err("literal alredy defined.");
  327.         break;
  328.       }
  329.     }
  330.     strcpy(checkLiteralts[numberOfLitInCheck], get_name($2));
  331.     numberOfLitInCheck++;
  332.   }
  333.   statement break
  334.   {
  335.     int lit = atoi(get_name($2));
  336.     $$ = $<i>4;
  337.     code("\n@check%d_stmt%d_exit:", checkIdx, lit);
  338.   }
  339.   ;
  340.  
  341. when_list
  342.   : when
  343.         {
  344.         }
  345.   | when_list when
  346.         {
  347.         }
  348.   ;
  349.  
  350. break
  351.   : /*empty*/
  352.   | _BREAK _SEMICOLON
  353.   {
  354.     code("\n\t\tJMP @check_exit%d", checkIdx);
  355.   }
  356.   ;
  357.  
  358.  
  359. assignment_statement
  360.   : _ID _ASSIGN num_exp _SEMICOLON
  361.       {
  362.         int idx = lookup_symbol($1, VAR|PAR|GVAR);
  363.         if(idx == NO_INDEX)
  364.           err("invalid lvalue '%s' in assignment", $1);
  365.         else
  366.           if(get_type(idx) != get_type($3))
  367.             err("incompatible types in assignment");
  368.         gen_mov($3, idx);
  369.         set_atr2(idx, 1);
  370.       }
  371.   ;
  372.  
  373. loop_statement
  374.   : _LOOP
  375.   {
  376.     code("\nloop_statement%d:", ++lab_num);
  377.     $<i>$ = lab_num;
  378.   }
  379.   statement _PUKA _MANAWA _LPAREN
  380.   {
  381.     code("\nloop_condition%d:", $<i>2);
  382.  
  383.   }
  384.   rel_exp _RPAREN _HOPAU _LOOP _SEMICOLON
  385.   {
  386.     code("\n\t\t%s loop_statement%d", jumps[$8], $<i>2);
  387.   }
  388.   ;
  389.  
  390.  
  391.  
  392. post_increment
  393.   : _ID _INC
  394.   {
  395.     int idx = lookup_symbol($1, VAR|PAR|FUN|GVAR);
  396.     if(idx == NO_INDEX)
  397.       err("invalid lvalue '%s' in increment", $1);
  398.  
  399.     if(get_kind(idx) == FUN)
  400.     {
  401.                   err("increment can't be called on function");
  402.     }
  403.    
  404.     int reg = take_reg();
  405.  
  406.     gen_mov(idx, reg);
  407.  
  408.     if(get_type(idx) == INT)
  409.       code("\n\t\tADDS\t");
  410.     else
  411.       code("\n\t\tADDU\t");
  412.    
  413.     gen_sym_name(idx);
  414.     code(", $1, ");
  415.     gen_sym_name(idx);
  416.  
  417.           $$=reg;
  418.   }
  419.   ;
  420.  
  421. increment_statement
  422.   : post_increment _SEMICOLON
  423.   ;
  424.  
  425. num_exp
  426.   : exp
  427.  
  428.   | num_exp _AROP exp
  429.       {
  430.         if(get_type($1) != get_type($3))
  431.           err("invalid operands: arithmetic operation");
  432.         int t1 = get_type($1);    
  433.         code("\n\t\t%s\t", ar_instructions[$2 + (t1 - 1) * AROP_NUMBER]);
  434.         gen_sym_name($1);
  435.         code(",");
  436.         gen_sym_name($3);
  437.         code(",");
  438.         free_if_reg($3);
  439.         free_if_reg($1);
  440.         $$ = take_reg();
  441.         gen_sym_name($$);
  442.         set_type($$, t1);
  443.       }
  444.   ;
  445.  
  446. exp
  447.   : literal
  448.   | _ID
  449.       {
  450.         $$ = lookup_symbol($1, VAR|PAR|GVAR);
  451.         if($$ == NO_INDEX)
  452.           err("'%s' undeclared", $1);
  453.       }
  454.  
  455.   | function_call
  456.       {
  457.         $$ = take_reg();
  458.         gen_mov(FUN_REG, $$);
  459.       }
  460.  
  461.   | _LPAREN num_exp _RPAREN
  462.       { $$ = $2; }
  463.   | post_increment
  464.   {
  465.     $$ = $1;
  466.   }
  467.   | cond_operator
  468.   {
  469.     $$ = reg;
  470.   }
  471.   ;
  472.  
  473. literal
  474.   : _INT_NUMBER
  475.       { $$ = insert_literal($1, INT); }
  476.  
  477.   | _UINT_NUMBER
  478.       { $$ = insert_literal($1, UINT); }
  479.   ;
  480.  
  481. function_call
  482.   : _ID
  483.       {
  484.         fcall_idx = lookup_symbol($1, FUN);
  485.         if(fcall_idx == NO_INDEX)
  486.           err("'%s' is not a function", $1);
  487.       }
  488.     _LPAREN argument_list _RPAREN
  489.       {
  490.         if(get_atr1(fcall_idx) != args_cnt)
  491.           err("wrong number of arguments");
  492.        
  493.         if(get_atr2(fcall_idx) != arg_val)
  494.           err("wrong argument types.");
  495.        
  496.         code("\n\t\t\tCALL\t%s", get_name(fcall_idx));
  497.         if(args_cnt > 0)
  498.           code("\n\t\t\tADDS\t%%15,$%d,%%15", args_cnt * 4);
  499.        
  500.         set_type(FUN_REG, get_type(fcall_idx));
  501.         $$ = FUN_REG;
  502.         args_cnt = 0;
  503.         arg_val = 0;
  504.       }
  505.   ;
  506.  
  507. argument
  508.   : /* empty */
  509.     { $$ = 0; }
  510.  
  511.   | num_exp
  512.     {
  513.       free_if_reg($1);
  514.       code("\n\t\t\tPUSH\t");
  515.       gen_sym_name($1);
  516.       arg_val = arg_val * 10 + get_type($1);
  517.       args_cnt++;
  518.       $$ = 1;
  519.     }
  520.   ;
  521.  
  522. argument_list
  523.   : argument
  524.   {
  525.     $$ = $1;
  526.   }
  527.   | argument_list _COMMA argument
  528.   {
  529.     $$ = $3;
  530.   }
  531.   ;
  532.  
  533. cond_operator
  534.   : _LPAREN rel_exp _RPAREN _QMARK
  535.   {
  536.     int lab = ++lab_num;
  537.     reg = take_reg();
  538.     code("\n\t\t%s\t@false%d", opp_jumps[$2], lab_num);
  539.     code("\n@true%d:", lab_num);
  540.   }
  541.   exp
  542.   {
  543.     gen_mov($6, reg);
  544.     code("\nJMP\t\t@exit%d",lab_num);
  545.     code("\n@false%d:", lab_num);
  546.   }
  547.   _DVOTACKA exp
  548.   {
  549.     gen_mov($9, reg);
  550.     code("\n@exit%d:", lab_num);
  551.     $$ = reg;
  552.   }
  553.   ;
  554.  
  555.  
  556. if_statement
  557.   : if_part %prec ONLY_IF
  558.       { code("\n@exit%d:", $1); }
  559.  
  560.   | if_part _ELSE statement
  561.       { code("\n@exit%d:", $1); }
  562.   ;
  563.  
  564. if_part
  565.   : _IF _LPAREN
  566.       {
  567.         $<i>$ = ++lab_num;
  568.         code("\n@if%d:", lab_num);
  569.       }
  570.     rel_exp
  571.       {
  572.         code("\n\t\t%s\t@false%d", opp_jumps[$4], $<i>3);
  573.         code("\n@true%d:", $<i>3);
  574.       }
  575.     _RPAREN statement
  576.       {
  577.         code("\n\t\tJMP \t@exit%d", $<i>3);
  578.         code("\n@false%d:", $<i>3);
  579.         $$ = $<i>3;
  580.       }
  581.   ;
  582.  
  583. rel_exp
  584.   : num_exp _RELOP num_exp
  585.       {
  586.         if(get_type($1) != get_type($3))
  587.           err("invalid operands: relational operator");
  588.         $$ = $2 + ((get_type($1) - 1) * RELOP_NUMBER);
  589.         gen_cmp($1, $3);
  590.       }
  591.   ;
  592.  
  593.  
  594.  
  595. return_statement
  596.   :
  597.   _RETURN num_exp _SEMICOLON
  598.   {
  599.     if(get_type(fun_idx) != get_type($2))
  600.       err("incompatible types in return");
  601.  
  602.     isReturn = 2;
  603.  
  604.     gen_mov($2, FUN_REG);
  605.     code("\n\t\tJMP \t@%s_exit", get_name(fun_idx));
  606.  
  607.   }
  608.   | _RETURN _SEMICOLON
  609.   {
  610.     isReturn = 1;
  611.   }
  612.   /*empty*/
  613.   {
  614.     isReturn = 0;
  615.   }
  616.   ;
  617.  
  618. %%
  619.  
  620. int yyerror(char *s) {
  621.   fprintf(stderr, "\nline %d: ERROR: %s", yylineno, s);
  622.   error_count++;
  623.   return 0;
  624. }
  625.  
  626. void warning(char *s) {
  627.   fprintf(stderr, "\nline %d: WARNING: %s", yylineno, s);
  628.   warning_count++;
  629. }
  630.  
  631. int main() {
  632.   int synerr;
  633.   init_symtab();
  634.   output = fopen("output.asm", "w+");
  635.  
  636.   synerr = yyparse();
  637.  
  638.   clear_symtab();
  639.   fclose(output);
  640.  
  641.   if(warning_count)
  642.     printf("\n%d warning(s).\n", warning_count);
  643.  
  644.   if(error_count) {
  645.     remove("output.asm");
  646.     printf("\n%d error(s).\n", error_count);
  647.   }
  648.  
  649.   if(synerr)
  650.     return -1;  //syntax error
  651.   else if(error_count)
  652.     return error_count & 127; //semantic errors
  653.   else if(warning_count)
  654.     return (warning_count & 127) + 127; //warnings
  655.   else
  656.     return 0; //OK
  657. }
  658.  
  659.