diff --git a/Monicelli.y b/Monicelli.y index cd34592..7766865 100644 --- a/Monicelli.y +++ b/Monicelli.y @@ -1,21 +1,20 @@ %{ #define YYERROR_VERBOSE -extern void emit(const char *, ...); extern void yyerror(const char *); extern int yylex(); + +#include "Nodes.hpp" + +using namespace monicelli; + +extern Program *program; %} %code requires { - #include "Type.h" +#include "Nodes.hpp" } -%union { - Type typeval; - int intval; - double floatval; - char *strval; -} %define api.prefix {monicelli_} %token MAIN @@ -39,130 +38,323 @@ extern int yylex(); %nonassoc LOWER_THAN_ELSE %nonassoc BRANCH_ELSE -%type NUMBER; -%type FLOAT; -%type ID; -%type TYPENAME; +%{ +#include + +static std::stack stmtStack; +static std::stack argsStack; +static std::stack paramsStack; +static std::stack branchCaseStack; +%} + +%union { + int intval; + double floatval; + char *strval; + bool boolval; + monicelli::Type typeval; + monicelli::Statement* statementval; + monicelli::StatementList* statlistval; + monicelli::Assert* assertval; + monicelli::FunctionCall* callval; + monicelli::Print* printval; + monicelli::Input* inputval; + monicelli::Abort* abortval; + monicelli::Branch* branchval; + monicelli::VarDeclaration* declval; + monicelli::Assignment* assignval; + monicelli::Loop* loopval; + monicelli::BranchCase *caseval; + monicelli::Return* returnval; + monicelli::Expression* expressionval; + monicelli::SemiExpression *semiexpval; + monicelli::Id* idval; + monicelli::Number* numericval; + monicelli::Function* funval; + monicelli::Main* mainval; +} + +%type NUMBER +%type FLOAT +%type ID +%type TYPENAME + +%type statement +// This is not nice :\ used to carry the else body +%type branch_body +%type assert_stmt +%type fun_call +%type fun_decl +%type print_stmt +%type input_stmt +%type abort_stmt +%type branch_stmt +%type case_stmt +%type var_decl +%type assign_stmt +%type loop_stmt +%type return_stmt +%type expression maybe_expression simple_expression var_init +%type semi_expression +%type variable +%type numeric +%type main +%type pointer %start program %% program: - /* epsilon */ | fun_decls main fun_decls + /* epsilon */ + | fun_decls main fun_decls { + program->setMain($2); + } ; fun_decls: - /* epsilon */ | fun_decls fun_decl + /* epsilon */ + | fun_decl { + program->addFunction($1); + } + fun_decls ; fun_decl: - FUNDECL ID args FUN_END statements + FUNDECL ID { + paramsStack.push(new IdList()); + } args FUN_END { + stmtStack.push(new StatementList()); + } + statements { + $$ = new Function(new Id($2), paramsStack.top(), stmtStack.top()); + paramsStack.pop(); + stmtStack.pop(); + } ; args: /* epsilon */ | PARAMS arglist ; arglist: - variable | variable arglist + variable { + paramsStack.top()->push_back($1); + } + | variable { + paramsStack.top()->push_back($1); + } + arglist ; main: - MAIN statements + MAIN { + stmtStack.push(new StatementList()); + } + statements { + $$ = new Main(stmtStack.top()); + stmtStack.pop(); + } ; statements: - /* epsilon */ | statement statements + /* epsilon */ { + } + | statement { + if ($1 != nullptr) { + stmtStack.top()->push_back($1); + } + } + statements ; statement: - assert_stmt | fun_call | print_stmt | input_stmt | abort_stmt | - branch_stmt | var_decl | assign_stmt | loop_stmt | return_stmt | COMMA + assert_stmt { $$ = $1; } + | fun_call { $$ = $1; } + | print_stmt { $$ = $1; } + | input_stmt { $$ = $1; } + | abort_stmt { $$ = $1; } + | branch_stmt { $$ = $1; } + | var_decl { $$ = $1; } + | assign_stmt { $$ = $1; } + | loop_stmt { $$ = $1; } + | return_stmt { $$ = $1; } + | COMMA { $$ = nullptr; } ; var_decl: - VARDECL variable COMMA pointer TYPENAME var_init + VARDECL variable COMMA pointer TYPENAME var_init { + $$ = new VarDeclaration($2, $5, $4, $6); + } ; pointer: - /* epsilon */ | STAR + /* epsilon */ { $$ = false; } | STAR { $$ = true; } ; var_init: - /* epsilon */ | ASSIGN expression + /* epsilon */ { $$ = nullptr; } | ASSIGN expression { $$ = $2; } ; numeric: - NUMBER | FLOAT + NUMBER { $$ = new Integer($1); } | FLOAT { $$ = new Float($1); } ; variable: - ID | ARTICLE ID | ARTICLE STAR ID | STAR ID + ID { $$ = new Id($1); } | ARTICLE ID { $$ = new Id($2); } ; assign_stmt: - variable ASSIGN expression + variable ASSIGN expression { + $$ = new Assignment($1, $3); + } ; print_stmt: - expression PRINT + expression PRINT { + $$ = new Print($1); + } ; input_stmt: - INPUT variable + INPUT variable { + $$ = new Input($2); + } ; return_stmt: - RETURN BANG | RETURN expression BANG + RETURN maybe_expression BANG { + $$ = new Return($2); + } +; +maybe_expression: + expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; } ; loop_stmt: - LOOP_BEGIN statements LOOP_CONDITION expression + LOOP_BEGIN { + stmtStack.push(new StatementList()); + } + statements LOOP_CONDITION expression { + $$ = new Loop(stmtStack.top(), $5); + stmtStack.pop(); + } ; branch_stmt: - BRANCH_CONDITION variable BRANCH_BEGIN - branch_body - BRANCH_END + BRANCH_CONDITION variable BRANCH_BEGIN { + branchCaseStack.push(new BranchCaseList()); + } + branch_body BRANCH_END { + $$ = new Branch($2, branchCaseStack.top(), $5); + branchCaseStack.pop(); + } ; branch_body: - cases %prec LOWER_THAN_ELSE | - cases BRANCH_ELSE COLON statements + cases %prec LOWER_THAN_ELSE { + $$ = nullptr; + } + | cases BRANCH_ELSE COLON { + stmtStack.push(new StatementList()); + } + statements { + $$ = stmtStack.top(); + stmtStack.pop(); + } ; cases: case_stmt | case_stmt CASE_END cases ; case_stmt: - semi_expression COLON statements + semi_expression COLON { + stmtStack.push(new StatementList()); + } statements { + branchCaseStack.top()->push_back(new BranchCase($1, stmtStack.top())); + stmtStack.pop(); + } ; fun_call: - FUNCALL ID call_args FUN_END + FUNCALL { + argsStack.push(new ExpressionList()); + } + ID call_args FUN_END { + $$ = new FunctionCall(new Id($3), argsStack.top()); + argsStack.pop(); + } ; call_args: /* epsilon */ | PARAMS call_arglist ; call_arglist: - expression | expression COMMA call_arglist + expression { argsStack.top()->push_back($1); } + | expression { argsStack.top()->push_back($1); } COMMA call_arglist ; abort_stmt: - ABORT + ABORT { + $$ = new Abort(); + } ; assert_stmt: - ASSERT expression BANG + ASSERT expression BANG { + $$ = new Assert($2); + } ; expression: - simple_expression | - expression OP_LT expression | - expression OP_GT expression | - expression OP_LTE expression | - expression OP_GTE expression | - expression OP_PLUS expression | - expression OP_MINUS expression | - expression OP_TIMES expression | - expression OP_DIV expression | - expression OP_SHL expression | - expression OP_SHR expression + simple_expression { + $$ = $1; + } + | expression OP_LT expression { + $$ = new ExpLt($1, $3); + } + | expression OP_GT expression { + $$ = new ExpGt($1, $3); + } + | expression OP_LTE expression { + $$ = new ExpGte($1, $3); + } + | expression OP_GTE expression { + $$ = new ExpLte($1, $3); + } + | expression OP_PLUS expression { + $$ = new ExpPlus($1, $3); + } + | expression OP_MINUS expression { + $$ = new ExpMinus($1, $3); + } + | expression OP_TIMES expression { + $$ = new ExpTimes($1, $3); + } + | expression OP_DIV expression { + $$ = new ExpDiv($1, $3); + } + | expression OP_SHL expression { + $$ = new ExpShl($1, $3); + } + | expression OP_SHR expression { + $$ = new ExpShr($1, $3); + } ; semi_expression: - simple_expression | - OP_LT expression | - OP_GT expression | - OP_LTE expression | - OP_GTE expression | - OP_PLUS expression | - OP_MINUS expression | - OP_TIMES expression | - OP_DIV expression | - OP_SHL expression | - OP_SHR expression + expression { + $$ = new SemiExpEq($1); + } + | OP_LT expression { + $$ = new SemiExpLt($2); + } + | OP_GT expression { + $$ = new SemiExpGt($2); + } + | OP_LTE expression { + $$ = new SemiExpLte($2); + } + | OP_GTE expression { + $$ = new SemiExpGte($2); + } + | OP_PLUS expression { + $$ = new SemiExpPlus($2); + } + | OP_MINUS expression { + $$ = new SemiExpMinus($2); + } + | OP_TIMES expression { + $$ = new SemiExpTimes($2); + } + | OP_DIV expression { + $$ = new SemiExpDiv($2); + } + | OP_SHL expression { + $$ = new SemiExpShl($2); + } + | OP_SHR expression { + $$ = new SemiExpShr($2); + } ; simple_expression: - fun_call | - numeric | - variable + fun_call { $$ = $1; } + | numeric { $$ = $1; } + | variable { $$ = $1; } ; %%