Make parser create trees
This commit is contained in:
parent
c1e4433011
commit
f098f91455
29
main.cpp
29
main.cpp
|
@ -1,39 +1,14 @@
|
|||
#include <iostream>
|
||||
#include <set>
|
||||
#include "tree.hpp"
|
||||
#include "parser.hpp"
|
||||
|
||||
extern int yylex();
|
||||
|
||||
extern std::string* target_program;
|
||||
extern std::set<std::string> symbols;
|
||||
extern stmt_ptr target_program;
|
||||
|
||||
int main() {
|
||||
if (!yylex()) {
|
||||
// Write initial C++ stuff.
|
||||
std::cout << "#include <iostream>" << std::endl;
|
||||
std::cout << "int main() {" << std::endl;
|
||||
|
||||
// Write declaractions for all variables.
|
||||
std::set<std::string>::iterator it;
|
||||
for (it = symbols.begin(); it != symbols.end(); it++) {
|
||||
std::cout << "double " << *it << ";" << std::endl;
|
||||
}
|
||||
|
||||
// Write the program itself.
|
||||
std::cout << std::endl << "/* Begin program */" << std::endl << std::endl;
|
||||
std::cout << *target_program << std::endl;
|
||||
std::cout << "/* End program */" << std::endl << std::endl;
|
||||
|
||||
// Write print statements for all symbols.
|
||||
for (it = symbols.begin(); it != symbols.end(); it++) {
|
||||
std::cout << "std::cout << \"" << *it << ": \" << " << *it << " << std::endl;" << std::endl;
|
||||
}
|
||||
|
||||
// Write terminating brace.
|
||||
std::cout << "}" << std::endl;
|
||||
|
||||
delete target_program;
|
||||
target_program = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
74
parser.y
74
parser.y
|
@ -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(); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <stack>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "tree.hpp"
|
||||
#include "parser.hpp"
|
||||
|
||||
/*
|
||||
|
@ -44,8 +45,7 @@ std::stack<int> _indent_stack;
|
|||
YYLTYPE loc;
|
||||
|
||||
#define PUSH_TOKEN(token, text) do { \
|
||||
yylval = text ? new std::string(text) : NULL; \
|
||||
loc.first_line = loc.last_line = yylineno; \
|
||||
yylval.str = text ? new std::string(text) : NULL; \
|
||||
int status = yypush_parse(pstate, token, &yylval, &loc); \
|
||||
if (status != YYPUSH_MORE) { \
|
||||
yypstate_delete(pstate); \
|
||||
|
|
34
tree.hpp
34
tree.hpp
|
@ -25,7 +25,26 @@ struct expr {
|
|||
virtual ~expr() = default;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<expr> expr_ptr;
|
||||
typedef expr* expr_ptr;
|
||||
|
||||
struct expr_id : expr {
|
||||
std::string id;
|
||||
|
||||
expr_id(std::string i) :
|
||||
id(std::move(i)) {}
|
||||
};
|
||||
|
||||
struct expr_int : expr {
|
||||
int val;
|
||||
|
||||
expr_int(int i) : val(i) {}
|
||||
};
|
||||
|
||||
struct expr_float : expr {
|
||||
double val;
|
||||
|
||||
expr_float(double f) : val(f) {}
|
||||
};
|
||||
|
||||
struct expr_binop : expr {
|
||||
binop op;
|
||||
|
@ -61,7 +80,7 @@ struct stmt {
|
|||
virtual ~stmt() = default;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<stmt> stmt_ptr;
|
||||
typedef stmt* stmt_ptr;
|
||||
|
||||
struct stmt_block : stmt {
|
||||
std::vector<stmt_ptr> children;
|
||||
|
@ -80,14 +99,21 @@ struct stmt_while : stmt {
|
|||
expr_ptr cond;
|
||||
stmt_ptr body;
|
||||
|
||||
stmt_while(expr_ptr c, stmt_ptr b)
|
||||
: cond(std::move(c)), body(std::move(b)) {}
|
||||
stmt_while(expr_ptr c, stmt_ptr b) :
|
||||
cond(std::move(c)), body(std::move(b)) {}
|
||||
};
|
||||
|
||||
struct stmt_break : stmt {
|
||||
|
||||
};
|
||||
|
||||
struct stmt_expr : stmt {
|
||||
expr_ptr child;
|
||||
|
||||
stmt_expr(expr_ptr c) :
|
||||
child(std::move(c)) {}
|
||||
};
|
||||
|
||||
template <typename T, typename ... Ts>
|
||||
stmt_ptr make_stmt(Ts&& ... ts) {
|
||||
return stmt_ptr(new T(std::move(ts)...));
|
||||
|
|
Loading…
Reference in New Issue
Block a user