Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- %{
- #include <cstdio>
- #include <iostream>
- #include <fstream>
- #include <iomanip>
- using namespace std;
- // Stuff from flex that bison needs to know about
- extern "C" int yylex();
- extern "C" int yyparse();
- extern "C" FILE *yyin;
- extern int line_num;
- // Output files declarations
- std::ofstream token_file;
- std::ofstream log_file;
- std::ofstream bytecode_file;
- int vars_cnt = 1;
- int constants_cnt = 1;
- int program_counter = 0;
- enum type {I_TYPE, F_TYPE};
- map<string, pair<type, int>> symbol_table;
- map<string, int> constant_table;
- // Function to handle parsing errors
- void yyerror(const char *s);
- void add_to_symb_table(string sym_name, type sym_type);
- void add_to_const_table(string const_name);
- %}
- // Bison fundamentally works by asking flex to get the next token, which it
- // returns as an object of type "yystype". But tokens could be of any
- // arbitrary data type! So we deal with that in Bison by defining a C union
- // holding each of the types of tokens that Flex could return, and have Bison
- // use that union instead of "int" for the definition of "yystype"
- %union {
- int ival;
- float fval;
- bool bval;
- char *id_name;
- type declaration_type;
- struct id_struct {
- char *id_name;
- int val;
- typ
- }
- yylval.id_struct.id_name =
- }
- // Define the "terminal symbol" token types I'm going to use (in CAPS
- // by convention), and associate each with a field of the union:
- %token <ival> INT
- %token <fval> FLOAT
- %token TOK_INT
- %token TOK_FLOAT
- %token TOK_BOOLEAN
- %token TOK_IF
- %token TOK_WHILE
- %token TOK_ELSE
- %token TOK_ASSIGN
- %token <id_struct> TOK_ID
- %token TOK_RELOP
- %token TOK_ADDOP
- %token TOK_MULOP
- %token UNRECOGNIZED_TOKEN
- %type <declaration_type> primitive_type;
- %type <> expression;
- // Precedence is downwards
- %left '+' '-'
- %left '*' '/'
- %%
- // Grammar
- method_body: statement_list;
- statement_list: statement | statement_list statement;
- statement: declaration | if | while | assignment;
- declaration: primitive_type TOK_ID ';'
- {
- // Declaring a variable named "TOK_ID.name" with type primitive_type
- string id_name($2);
- add_to_symb_table(id_name, $1);
- };
- primitive_type: TOK_INT
- {
- $$ = type::I_TYPE;
- }
- | TOK_FLOAT
- {
- $$ = type::F_TYPE;
- }
- | TOK_BOOLEAN
- {
- };
- if: TOK_IF '(' expression ')' '{' statement '}' TOK_ELSE '{' statement '}';
- while: TOK_WHILE '(' expression ')' '{' statement '}';
- assignment: TOK_ID TOK_ASSIGN expression ';'
- {
- // istore or fstore token_ind
- expression.value
- };
- expression: simple_expression {$$ = $1}| simple_expression TOK_RELOP simple_expression {$$ = $1 operation(relop.get_type()) $3};
- simple_expression: term {$$ = $1}| sign term {$$ = get_sign() * $1}| simple_expression TOK_ADDOP term {$$ = $1 +/- $3};
- term: factor {$$ = $1}| term TOK_MULOP factor {$$ = $1 $2.getOper $3};
- factor: TOK_ID
- {
- string str($1);
- if (symbol_table.find(str) == symbol_table.end()) {
- cout << "Variable: " + str + " has not been declared" << endl;
- exit(-1);
- }
- if (symbol_table[str].first == type::I_TYPE) {
- bytecode_file << "iload\t" << symbol_table[str].second << endl;
- } else {
- bytecode_file << "fload\t" << symbol_table[str].second << endl;
- }
- // $$ = $1.value;
- }
- | INT
- {
- to_string($1);
- if (constant_table.find(str) == constant_table.end()) {
- add_to_const_table($1);
- }
- bytecode_file << "ldc\t#" << constant_table[str] << endl;
- // $$ = $1.lexvalue;
- }
- | FLOAT
- {
- to_string($1);
- if (constant_table.find(str) == constant_table.end()) {
- add_to_const_table($1);
- }
- bytecode_file << "ldc\t#" << constant_table[str] << endl;
- // $$ = $1.lexval;
- }
- | '(' expression ')'
- {
- // $$ = $2.value;
- };
- sign: TOK_ADDOP {$$ = +/-};
- %%
- int main(int argc, char **argv) {
- token_file.open("token-file.txt");
- log_file.open("compiler.log");
- bytecode_file.open("bytecode.j");
- log_file << std::left << std::setw (20) << "Match State" <<
- std::left << std::setw (40) << "Lexeme" << std::left << std::setw (30)
- << "Token Class" << endl;
- log_file << std::left << std::setw (20) << "-----------" <<
- std::left << std::setw (40) << "------" << std::left << std::setw (30)
- << "-----------" << endl;
- // Make sure file name is specified in arguments
- if (argc != 2) {
- cout << "ERROR: wrong number of arguments!" << endl;
- return -1;
- }
- // Open a file handle to code file
- FILE *myfile = fopen(argv[1], "r");
- // Make sure it's valid
- if (!myfile) {
- cout << "Can't open code file!" << endl;
- return -1;
- }
- // Set lex to read from file instead of STDIN
- yyin = myfile;
- // Parse through the input until there is no more
- do {
- yyparse();
- } while (!feof(yyin));
- }
- void yyerror(const char *s) {
- cout << "EEK, parse error on line " << line_num << "! Message: " << s << endl;
- exit(-1); // Remove this to allow panic error recovery to keep execution
- }
- void add_to_symb_table(string sym_name, type sym_type) {
- if (symbol_table.find(sym_name) != symbol_table.end()) {
- string err_msg = "Variable: " + sym_name + " has been declared!";
- yyerror(err_msg.c_str());
- } else {
- symbol_table[sym_name] = make_pair(sym_type, vars_cnt++);
- }
- }
- void add_to_const_table(string const_name) {
- if (constant_table.find(const_name) == constant_table.end()) {
- constant_table[const_name] = constants_cnt++;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement