Getting rid of explicit stacks with more left-recursive rules.
As a result, the grammar should be more readable.
This commit is contained in:
parent
e984b5d0ea
commit
2f66c31729
127
Monicelli.ypp
127
Monicelli.ypp
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Monicelli: an esoteric language compiler
|
* Monicelli: an esoteric language compiler
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Stefano Sanfilippo
|
* Copyright (C) 2014 Stefano Sanfilippo
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -72,16 +72,6 @@
|
||||||
%nonassoc LOWER_THAN_ELSE
|
%nonassoc LOWER_THAN_ELSE
|
||||||
%nonassoc BRANCH_ELSE
|
%nonassoc BRANCH_ELSE
|
||||||
|
|
||||||
%code {
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
static std::stack<StatementList*> stmtStack;
|
|
||||||
static std::stack<ExpressionList*> argsStack;
|
|
||||||
static std::stack<IdList*> paramsStack;
|
|
||||||
static std::stack<BranchCaseList*> branchCaseStack;
|
|
||||||
static std::stack<FunArgList*> funArgStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
int intval;
|
int intval;
|
||||||
double floatval;
|
double floatval;
|
||||||
|
@ -96,17 +86,21 @@ static std::stack<FunArgList*> funArgStack;
|
||||||
Input* inputval;
|
Input* inputval;
|
||||||
Abort* abortval;
|
Abort* abortval;
|
||||||
Branch* branchval;
|
Branch* branchval;
|
||||||
|
Branch::Body* branchbodyval;
|
||||||
VarDeclaration* declval;
|
VarDeclaration* declval;
|
||||||
Assignment* assignval;
|
Assignment* assignval;
|
||||||
Loop* loopval;
|
Loop* loopval;
|
||||||
BranchCase *caseval;
|
BranchCase *caseval;
|
||||||
|
BranchCaseList *caselistval;
|
||||||
Return* returnval;
|
Return* returnval;
|
||||||
Expression* expressionval;
|
Expression* expressionval;
|
||||||
|
ExpressionList* exprlistval;
|
||||||
SemiExpression *semiexpval;
|
SemiExpression *semiexpval;
|
||||||
Id* idval;
|
Id* idval;
|
||||||
Number* numericval;
|
Number* numericval;
|
||||||
Function* funval;
|
Function* funval;
|
||||||
FunArg *argval;
|
FunArg *argval;
|
||||||
|
FunArgList *arglistval;
|
||||||
Main* mainval;
|
Main* mainval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,23 +108,26 @@ static std::stack<FunArgList*> funArgStack;
|
||||||
%type<floatval> FLOAT
|
%type<floatval> FLOAT
|
||||||
%type<strval> ID
|
%type<strval> ID
|
||||||
%type<typeval> TYPENAME fun_return
|
%type<typeval> TYPENAME fun_return
|
||||||
|
|
||||||
%type<statementval> statement
|
%type<statementval> statement
|
||||||
%type<statlistval> branch_body
|
%type<statlistval> statements
|
||||||
|
%type<branchbodyval> branch_body
|
||||||
%type<assertval> assert_stmt
|
%type<assertval> assert_stmt
|
||||||
%type<callval> fun_call
|
%type<callval> fun_call
|
||||||
%type<argval> arg_decl
|
%type<argval> arg_decl
|
||||||
|
%type<arglistval> args_decl args
|
||||||
%type<funval> fun_decl
|
%type<funval> fun_decl
|
||||||
%type<printval> print_stmt
|
%type<printval> print_stmt
|
||||||
%type<inputval> input_stmt
|
%type<inputval> input_stmt
|
||||||
%type<abortval> abort_stmt
|
%type<abortval> abort_stmt
|
||||||
%type<branchval> branch_stmt
|
%type<branchval> branch_stmt
|
||||||
%type<caseval> case_stmt
|
%type<caseval> case_stmt
|
||||||
|
%type<caselistval> cases
|
||||||
%type<declval> var_decl
|
%type<declval> var_decl
|
||||||
%type<assignval> assign_stmt
|
%type<assignval> assign_stmt
|
||||||
%type<loopval> loop_stmt
|
%type<loopval> loop_stmt
|
||||||
%type<returnval> return_stmt
|
%type<returnval> return_stmt
|
||||||
%type<expressionval> expression maybe_expression simple_expression var_init
|
%type<expressionval> expression maybe_expression simple_expression var_init
|
||||||
|
%type<exprlistval> call_arglist call_args
|
||||||
%type<semiexpval> semi_expression
|
%type<semiexpval> semi_expression
|
||||||
%type<idval> variable
|
%type<idval> variable
|
||||||
%type<numericval> numeric
|
%type<numericval> numeric
|
||||||
|
@ -155,31 +152,24 @@ fun_decls:
|
||||||
fun_decls
|
fun_decls
|
||||||
;
|
;
|
||||||
fun_decl:
|
fun_decl:
|
||||||
FUN_DECL fun_return ID {
|
FUN_DECL fun_return ID args FUN_END statements {
|
||||||
funArgStack.push(new FunArgList());
|
$$ = new Function(new Id($3), $2, $4, $6);
|
||||||
} args FUN_END {
|
|
||||||
stmtStack.push(new StatementList());
|
|
||||||
}
|
|
||||||
statements {
|
|
||||||
$$ = new Function(new Id($3), $2, funArgStack.top(), stmtStack.top());
|
|
||||||
funArgStack.pop();
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
fun_return:
|
fun_return:
|
||||||
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
|
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
|
||||||
;
|
;
|
||||||
args:
|
args:
|
||||||
/* epsilon */ | PARAMS args_decl
|
/* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; }
|
||||||
;
|
;
|
||||||
args_decl:
|
args_decl:
|
||||||
arg_decl {
|
arg_decl {
|
||||||
funArgStack.top()->push_back($1);
|
$$ = new FunArgList();
|
||||||
|
$$->push_back($1);
|
||||||
}
|
}
|
||||||
| arg_decl {
|
| args_decl COMMA arg_decl {
|
||||||
funArgStack.top()->push_back($1);
|
$1->push_back($3);
|
||||||
}
|
}
|
||||||
COMMA args_decl
|
|
||||||
;
|
;
|
||||||
arg_decl:
|
arg_decl:
|
||||||
variable pointer TYPENAME {
|
variable pointer TYPENAME {
|
||||||
|
@ -187,23 +177,20 @@ arg_decl:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
main:
|
main:
|
||||||
MAIN {
|
MAIN statements {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new Main($2);
|
||||||
}
|
|
||||||
statements {
|
|
||||||
$$ = new Main(stmtStack.top());
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
statements:
|
statements:
|
||||||
/* epsilon */ {
|
/* epsilon */ {
|
||||||
|
$$ = new StatementList();
|
||||||
}
|
}
|
||||||
| statement {
|
| statements statement {
|
||||||
if ($1 != nullptr) {
|
if ($2 != nullptr) {
|
||||||
stmtStack.top()->push_back($1);
|
$1->push_back($2);
|
||||||
}
|
}
|
||||||
|
$$ = $1;
|
||||||
}
|
}
|
||||||
statements
|
|
||||||
;
|
;
|
||||||
statement:
|
statement:
|
||||||
assert_stmt { $$ = $1; }
|
assert_stmt { $$ = $1; }
|
||||||
|
@ -264,61 +251,59 @@ maybe_expression:
|
||||||
expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; }
|
expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
loop_stmt:
|
loop_stmt:
|
||||||
LOOP_BEGIN {
|
LOOP_BEGIN statements LOOP_CONDITION expression {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new Loop($2, $4);
|
||||||
}
|
|
||||||
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 BRANCH_END {
|
||||||
branchCaseStack.push(new BranchCaseList());
|
$$ = new Branch($2, $4);
|
||||||
}
|
|
||||||
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 {
|
||||||
$$ = nullptr;
|
$$ = new Branch::Body($1);
|
||||||
}
|
}
|
||||||
| cases BRANCH_ELSE COLON {
|
| cases BRANCH_ELSE COLON statements {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new Branch::Body($1, $4);
|
||||||
}
|
|
||||||
statements {
|
|
||||||
$$ = stmtStack.top();
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
cases:
|
cases:
|
||||||
case_stmt | case_stmt CASE_END cases
|
case_stmt {
|
||||||
|
$$ = new BranchCaseList();
|
||||||
|
$$->push_back($1);
|
||||||
|
}
|
||||||
|
| cases CASE_END case_stmt {
|
||||||
|
$1->push_back($3);
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
case_stmt:
|
case_stmt:
|
||||||
semi_expression COLON {
|
semi_expression COLON statements {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new BranchCase($1, $3);
|
||||||
} statements {
|
|
||||||
branchCaseStack.top()->push_back(new BranchCase($1, stmtStack.top()));
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
fun_call:
|
fun_call:
|
||||||
FUN_CALL {
|
FUN_CALL ID call_args FUN_END {
|
||||||
argsStack.push(new ExpressionList());
|
$$ = new FunctionCall(new Id($2), $3);
|
||||||
}
|
|
||||||
ID call_args FUN_END {
|
|
||||||
$$ = new FunctionCall(new Id($3), argsStack.top());
|
|
||||||
argsStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
call_args:
|
call_args:
|
||||||
/* epsilon */ | PARAMS call_arglist
|
/* epsilon */ {
|
||||||
|
$$ = new ExpressionList();
|
||||||
|
}
|
||||||
|
| PARAMS call_arglist {
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
call_arglist:
|
call_arglist:
|
||||||
expression { argsStack.top()->push_back($1); }
|
expression {
|
||||||
| expression { argsStack.top()->push_back($1); } COMMA call_arglist
|
$$ = new ExpressionList();
|
||||||
|
$$->push_back($1);
|
||||||
|
}
|
||||||
|
| call_arglist COMMA expression {
|
||||||
|
$$->push_back($3);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
abort_stmt:
|
abort_stmt:
|
||||||
ABORT {
|
ABORT {
|
||||||
|
|
10
Nodes.cpp
10
Nodes.cpp
|
@ -122,9 +122,9 @@ void Branch::emit(std::ostream &stream, int indent) {
|
||||||
stream << "if (";
|
stream << "if (";
|
||||||
var->emit(stream);
|
var->emit(stream);
|
||||||
|
|
||||||
if (cases->size() > 0) {
|
if (body->cases->size() > 0) {
|
||||||
BranchCase *last = cases->back();
|
BranchCase *last = body->cases->back();
|
||||||
for (BranchCase *c: *cases) {
|
for (BranchCase *c: *body->cases) {
|
||||||
c->emit(stream, indent + 1);
|
c->emit(stream, indent + 1);
|
||||||
if (c != last) {
|
if (c != last) {
|
||||||
stream << " else if (";
|
stream << " else if (";
|
||||||
|
@ -133,12 +133,12 @@ void Branch::emit(std::ostream &stream, int indent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (els == nullptr) {
|
if (body->els == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << " else {\n";
|
stream << " else {\n";
|
||||||
els->emit(stream, indent + 1);
|
body->els->emit(stream, indent + 1);
|
||||||
emitIndent(stream, indent);
|
emitIndent(stream, indent);
|
||||||
stream << "}";
|
stream << "}";
|
||||||
}
|
}
|
||||||
|
|
17
Nodes.hpp
17
Nodes.hpp
|
@ -265,14 +265,23 @@ typedef PointerList<BranchCase> BranchCaseList;
|
||||||
|
|
||||||
class Branch: public Statement {
|
class Branch: public Statement {
|
||||||
public:
|
public:
|
||||||
Branch(Id *v, BranchCaseList *c, StatementList *e):
|
struct Body {
|
||||||
var(v), cases(c), els(e) {}
|
public:
|
||||||
|
Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pointer<BranchCaseList> cases;
|
||||||
|
Pointer<StatementList> els;
|
||||||
|
|
||||||
|
friend class Branch;
|
||||||
|
};
|
||||||
|
|
||||||
|
Branch(Id *v, Branch::Body *b): var(v), body(b) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(std::ostream &stream, int indent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<Id> var;
|
Pointer<Id> var;
|
||||||
Pointer<BranchCaseList> cases;
|
Pointer<Branch::Body> body;
|
||||||
Pointer<StatementList> els;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user