|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#include <iostream> |
|
|
|
|
#include <set> |
|
|
|
|
|
|
|
|
|
#include "tree.hpp" |
|
|
|
|
#include "parser.hpp" |
|
|
|
|
|
|
|
|
|
extern int yylex(); |
|
|
|
@ -12,8 +13,7 @@ std::string* translate_boolean_str(std::string* boolean_str);
|
|
|
|
|
* Here, target_program is a string that will hold the target program being |
|
|
|
|
* generated, and symbols is a simple symbol table. |
|
|
|
|
*/ |
|
|
|
|
std::string* target_program; |
|
|
|
|
std::set<std::string> symbols; |
|
|
|
|
stmt_ptr target_program; |
|
|
|
|
%} |
|
|
|
|
|
|
|
|
|
/* Enable location tracking. */ |
|
|
|
@ -23,7 +23,11 @@ std::set<std::string> symbols;
|
|
|
|
|
* All program constructs will be represented as strings, specifically as |
|
|
|
|
* their corresponding C/C++ translation. |
|
|
|
|
*/ |
|
|
|
|
%define api.value.type { std::string* } |
|
|
|
|
%union { |
|
|
|
|
expr_ptr ex; |
|
|
|
|
stmt_ptr st; |
|
|
|
|
std::string* str; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
* Because the lexer can generate more than one token at a time (i.e. DEDENT |
|
|
|
@ -56,6 +60,10 @@ std::set<std::string> symbols;
|
|
|
|
|
%left EQ NEQ GT GTE LT LTE |
|
|
|
|
%right NOT |
|
|
|
|
|
|
|
|
|
%type <str> IDENTIFIER FLOAT INTEGER BOOLEAN |
|
|
|
|
%type <st> program statements statement if_statement while_statement break_statement block elif_blocks else_block |
|
|
|
|
%type <ex> assign_statement primary_expression negated_expression expression condition |
|
|
|
|
|
|
|
|
|
/* This is our goal/start symbol. */ |
|
|
|
|
%start program |
|
|
|
|
|
|
|
|
@ -73,78 +81,78 @@ program
|
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
statements |
|
|
|
|
: statement { $$ = $1; } |
|
|
|
|
| statements statement { $$ = new std::string(*$1 + *$2); delete $1; delete $2; } |
|
|
|
|
: statement { $$ = new stmt_block(); ((stmt_block*)$$)->children.push_back($1); } |
|
|
|
|
| statements statement { $$ = $1; ((stmt_block*)$$)->children.push_back($2); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
statement |
|
|
|
|
: assign_statement { $$ = $1; } |
|
|
|
|
: assign_statement { $$ = new stmt_expr($1); } |
|
|
|
|
| if_statement { $$ = $1; } |
|
|
|
|
| while_statement { $$ = $1; } |
|
|
|
|
| break_statement { $$ = $1; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
primary_expression |
|
|
|
|
: IDENTIFIER { $$ = $1; } |
|
|
|
|
| FLOAT { $$ = $1; } |
|
|
|
|
| INTEGER { $$ = $1; } |
|
|
|
|
| BOOLEAN { $$ = translate_boolean_str($1); delete $1; } |
|
|
|
|
| LPAREN expression RPAREN { $$ = new std::string("(" + *$2 + ")"); delete $2; } |
|
|
|
|
: IDENTIFIER { $$ = new expr_id(*$1); delete $1; } |
|
|
|
|
| FLOAT { $$ = new expr_float(std::stod(*$1)); delete $1; } |
|
|
|
|
| INTEGER { $$ = new expr_int(std::stoi(*$1)); delete $1; } |
|
|
|
|
| BOOLEAN { $$ = new expr_int(*$1 == "True"); delete $1; } |
|
|
|
|
| LPAREN expression RPAREN { $$ = $2; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
negated_expression |
|
|
|
|
: NOT primary_expression { $$ = new std::string("!" + *$2); delete $2; } |
|
|
|
|
: NOT primary_expression { $$ = new expr_unop(unop::lnot, $2); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
expression |
|
|
|
|
: primary_expression { $$ = $1; } |
|
|
|
|
| negated_expression { $$ = $1; } |
|
|
|
|
| expression PLUS expression { $$ = new std::string(*$1 + " + " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression MINUS expression { $$ = new std::string(*$1 + " - " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression TIMES expression { $$ = new std::string(*$1 + " * " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression DIVIDEDBY expression { $$ = new std::string(*$1 + " / " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression EQ expression { $$ = new std::string(*$1 + " == " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression NEQ expression { $$ = new std::string(*$1 + " != " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression GT expression { $$ = new std::string(*$1 + " > " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression GTE expression { $$ = new std::string(*$1 + " >= " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression LT expression { $$ = new std::string(*$1 + " < " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression LTE expression { $$ = new std::string(*$1 + " <= " + *$3); delete $1; delete $3; } |
|
|
|
|
| expression PLUS expression { $$ = new expr_binop(binop::plus, $1, $3); } |
|
|
|
|
| expression MINUS expression { $$ = new expr_binop(binop::minus, $1, $3); } |
|
|
|
|
| expression TIMES expression { $$ = new expr_binop(binop::times, $1, $3); } |
|
|
|
|
| expression DIVIDEDBY expression { $$ = new expr_binop(binop::divide, $1, $3); } |
|
|
|
|
| expression EQ expression { $$ = new expr_binop(binop::eq, $1, $3); } |
|
|
|
|
| expression NEQ expression { $$ = new expr_binop(binop::neq, $1, $3); } |
|
|
|
|
| expression GT expression { $$ = new expr_binop(binop::gt, $1, $3); } |
|
|
|
|
| expression GTE expression { $$ = new expr_binop(binop::gte, $1, $3); } |
|
|
|
|
| expression LT expression { $$ = new expr_binop(binop::lt, $1, $3); } |
|
|
|
|
| expression LTE expression { $$ = new expr_binop(binop::lte, $1, $3); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
assign_statement |
|
|
|
|
: IDENTIFIER ASSIGN expression NEWLINE { symbols.insert(*$1); $$ = new std::string(*$1 + " = " + *$3 + ";\n"); delete $1; delete $3; } |
|
|
|
|
: IDENTIFIER ASSIGN expression NEWLINE { $$ = new expr_assign(*$1, $3); delete $1; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
block |
|
|
|
|
: INDENT statements DEDENT { $$ = new std::string("{\n" + *$2 + "}"); delete $2; } |
|
|
|
|
: INDENT statements DEDENT { $$ = $2; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
condition |
|
|
|
|
: expression { $$ = $1; } |
|
|
|
|
| condition AND condition { $$ = new std::string(*$1 + " && " + *$3); delete $1; delete $3; } |
|
|
|
|
| condition OR condition { $$ = new std::string(*$1 + " || " + *$3); delete $1; delete $3; } |
|
|
|
|
| condition AND condition { $$ = new expr_binop(binop::land, $1, $3); } |
|
|
|
|
| condition OR condition { $$ = new expr_binop(binop::lor, $1, $3); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
if_statement |
|
|
|
|
: IF condition COLON NEWLINE block elif_blocks else_block { $$ = new std::string("if (" + *$2 + ") " + *$5 + *$6 + *$7 + "\n"); delete $2; delete $5; delete $6; delete $7; } |
|
|
|
|
: IF condition COLON NEWLINE block elif_blocks else_block { $$ = new stmt_if($2, $6, $7); delete $6; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
elif_blocks |
|
|
|
|
: %empty { $$ = new std::string(""); } |
|
|
|
|
| elif_blocks ELIF condition COLON NEWLINE block { $$ = new std::string(*$1 + " else if (" + *$3 + ") " + *$6); delete $1; delete $3; delete $6; } |
|
|
|
|
: %empty { $$ = nullptr; } |
|
|
|
|
| elif_blocks ELIF condition COLON NEWLINE block { $$ = new stmt_if($3, $6); delete $6; } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
else_block |
|
|
|
|
: %empty { $$ = new std::string(""); } |
|
|
|
|
| ELSE COLON NEWLINE block { $$ = new std::string(" else " + *$4); delete $4; } |
|
|
|
|
: %empty { $$ = nullptr; } |
|
|
|
|
| ELSE COLON NEWLINE block { $$ = $4; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while_statement |
|
|
|
|
: WHILE condition COLON NEWLINE block { $$ = new std::string("while (" + *$2 + ") " + *$5 + "\n"); delete $2; delete $5; } |
|
|
|
|
: WHILE condition COLON NEWLINE block { $$ = new stmt_while($2, $5); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
break_statement |
|
|
|
|
: BREAK NEWLINE { $$ = new std::string("break;\n"); } |
|
|
|
|
: BREAK NEWLINE { $$ = new stmt_break(); } |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
%% |
|
|
|
|