Advertisement
What_Ever

Untitled

May 11th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.91 KB | None | 0 0
  1. %{
  2. #include <cstdio>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <iomanip>
  6. using namespace std;
  7.  
  8. // Stuff from flex that bison needs to know about
  9. extern "C" int yylex();
  10. extern "C" int yyparse();
  11. extern "C" FILE *yyin;
  12. extern int line_num;
  13.  
  14. // Output files declarations
  15. std::ofstream token_file;
  16. std::ofstream log_file;
  17. std::ofstream bytecode_file;
  18.  
  19. int vars_cnt = 1;
  20. int constants_cnt = 1;
  21. int program_counter = 0;
  22. enum type {I_TYPE, F_TYPE};
  23. map<string, pair<type, int>> symbol_table;
  24. map<string, int> constant_table;
  25.  
  26. // Function to handle parsing errors
  27. void yyerror(const char *s);
  28.  
  29. void add_to_symb_table(string sym_name, type sym_type);
  30. void add_to_const_table(string const_name);
  31.  
  32. %}
  33.  
  34. // Bison fundamentally works by asking flex to get the next token, which it
  35. // returns as an object of type "yystype".  But tokens could be of any
  36. // arbitrary data type!  So we deal with that in Bison by defining a C union
  37. // holding each of the types of tokens that Flex could return, and have Bison
  38. // use that union instead of "int" for the definition of "yystype"
  39. %union {
  40.     int ival;
  41.     float fval;
  42.     bool bval;
  43.     char *id_name;
  44.     type declaration_type;
  45.     struct id_struct {
  46.       char *id_name;
  47.       int val;
  48.       typ
  49.     }
  50.     yylval.id_struct.id_name =
  51. }
  52.  
  53. // Define the "terminal symbol" token types I'm going to use (in CAPS
  54. // by convention), and associate each with a field of the union:
  55. %token <ival> INT
  56. %token <fval> FLOAT
  57. %token TOK_INT
  58. %token TOK_FLOAT
  59. %token TOK_BOOLEAN
  60. %token TOK_IF
  61. %token TOK_WHILE
  62. %token TOK_ELSE
  63. %token TOK_ASSIGN
  64. %token <id_struct> TOK_ID
  65. %token TOK_RELOP
  66. %token TOK_ADDOP
  67. %token TOK_MULOP
  68. %token UNRECOGNIZED_TOKEN
  69.  
  70. %type <declaration_type> primitive_type;
  71. %type <> expression;
  72.  
  73. // Precedence is downwards
  74. %left '+' '-'
  75. %left '*' '/'
  76.  
  77. %%
  78. // Grammar
  79. method_body: statement_list;
  80.  
  81. statement_list: statement | statement_list statement;
  82.  
  83. statement: declaration | if | while | assignment;
  84.  
  85. declaration: primitive_type TOK_ID ';'
  86.     {
  87.         // Declaring a variable named "TOK_ID.name" with type primitive_type
  88.         string id_name($2);
  89.         add_to_symb_table(id_name, $1);
  90.     };
  91.  
  92. primitive_type: TOK_INT
  93.                 {
  94.                     $$ = type::I_TYPE;
  95.                 }
  96.                 | TOK_FLOAT
  97.                 {
  98.                     $$ = type::F_TYPE;
  99.                 }    
  100.                 | TOK_BOOLEAN
  101.                 {
  102.  
  103.                 };
  104.  
  105. if: TOK_IF '(' expression ')' '{' statement '}' TOK_ELSE '{' statement '}';
  106.  
  107. while: TOK_WHILE '(' expression ')' '{' statement '}';
  108.  
  109. assignment: TOK_ID TOK_ASSIGN expression ';'
  110.     {
  111.         // istore or fstore token_ind
  112.         expression.value
  113.     };
  114.  
  115. expression: simple_expression {$$ = $1}| simple_expression TOK_RELOP simple_expression {$$ = $1 operation(relop.get_type()) $3};
  116.  
  117. simple_expression: term {$$ = $1}| sign term {$$ = get_sign() * $1}| simple_expression TOK_ADDOP term {$$ = $1 +/- $3};
  118.  
  119. term: factor {$$ = $1}| term TOK_MULOP factor {$$ = $1 $2.getOper $3};
  120.  
  121. factor: TOK_ID
  122.         {
  123.             string str($1);
  124.             if (symbol_table.find(str) == symbol_table.end()) {
  125.                 cout << "Variable: " + str + " has not been declared" << endl;
  126.                 exit(-1);
  127.             }
  128.             if (symbol_table[str].first == type::I_TYPE) {
  129.                 bytecode_file << "iload\t" << symbol_table[str].second << endl;
  130.             } else {
  131.                 bytecode_file << "fload\t" << symbol_table[str].second << endl;
  132.             }
  133.             // $$ = $1.value;
  134.         }
  135.         | INT
  136.         {  
  137.             to_string($1);
  138.             if (constant_table.find(str) == constant_table.end()) {
  139.                 add_to_const_table($1);
  140.             }
  141.             bytecode_file << "ldc\t#" << constant_table[str] << endl;
  142.             // $$ = $1.lexvalue;
  143.         }
  144.         | FLOAT
  145.         {
  146.             to_string($1);
  147.             if (constant_table.find(str) == constant_table.end()) {
  148.                 add_to_const_table($1);
  149.             }
  150.             bytecode_file << "ldc\t#" << constant_table[str] << endl;
  151.             // $$ = $1.lexval;
  152.         }
  153.         | '(' expression ')'
  154.         {
  155.             // $$ = $2.value;
  156.         };
  157. sign: TOK_ADDOP {$$ = +/-};
  158. %%
  159.  
  160. int main(int argc, char **argv) {
  161.  
  162.     token_file.open("token-file.txt");
  163.     log_file.open("compiler.log");
  164.     bytecode_file.open("bytecode.j");
  165.  
  166.     log_file << std::left << std::setw (20) << "Match State" <<
  167.         std::left << std::setw (40) << "Lexeme" << std::left << std::setw (30)
  168.             << "Token Class" << endl;
  169.     log_file << std::left << std::setw (20) << "-----------" <<
  170.         std::left << std::setw (40) << "------" << std::left << std::setw (30)
  171.             << "-----------" << endl;
  172.  
  173.     // Make sure file name is specified in arguments
  174.     if (argc != 2) {
  175.         cout << "ERROR: wrong number of arguments!" << endl;
  176.         return -1;
  177.     }
  178.     // Open a file handle to code file
  179.     FILE *myfile = fopen(argv[1], "r");
  180.    
  181.     // Make sure it's valid
  182.     if (!myfile) {
  183.         cout << "Can't open code file!" << endl;
  184.         return -1;
  185.     }
  186.     // Set lex to read from file instead of STDIN
  187.     yyin = myfile;
  188.  
  189.     // Parse through the input until there is no more
  190.     do {
  191.         yyparse();
  192.     } while (!feof(yyin));
  193.    
  194. }
  195.  
  196. void yyerror(const char *s) {
  197.     cout << "EEK, parse error on line " << line_num << "!  Message: " << s << endl;
  198.     exit(-1); // Remove this to allow panic error recovery to keep execution
  199. }
  200.  
  201. void add_to_symb_table(string sym_name, type sym_type) {
  202.     if (symbol_table.find(sym_name) != symbol_table.end()) {
  203.         string err_msg = "Variable: " + sym_name + " has been declared!";
  204.         yyerror(err_msg.c_str());
  205.     } else {
  206.         symbol_table[sym_name] = make_pair(sym_type, vars_cnt++);
  207.     }
  208. }
  209.  
  210. void add_to_const_table(string const_name) {
  211.     if (constant_table.find(const_name) == constant_table.end()) {
  212.         constant_table[const_name] = constants_cnt++;
  213.     }
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement