Plugging AST nodes into semantic rules.

This commit is contained in:
Stefano Sanfilippo 2014-11-27 20:01:52 +01:00
parent e65896f2c5
commit 747bc16a85

View File

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