Getting rid of explicit stacks with more left-recursive rules.

As a result, the grammar should be more readable.
This commit is contained in:
Stefano Sanfilippo 2014-12-02 16:22:03 +01:00
parent e984b5d0ea
commit 2f66c31729
3 changed files with 74 additions and 80 deletions

View File

@ -72,16 +72,6 @@
%nonassoc LOWER_THAN_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 {
int intval;
double floatval;
@ -96,17 +86,21 @@ static std::stack<FunArgList*> funArgStack;
Input* inputval;
Abort* abortval;
Branch* branchval;
Branch::Body* branchbodyval;
VarDeclaration* declval;
Assignment* assignval;
Loop* loopval;
BranchCase *caseval;
BranchCaseList *caselistval;
Return* returnval;
Expression* expressionval;
ExpressionList* exprlistval;
SemiExpression *semiexpval;
Id* idval;
Number* numericval;
Function* funval;
FunArg *argval;
FunArgList *arglistval;
Main* mainval;
}
@ -114,23 +108,26 @@ static std::stack<FunArgList*> funArgStack;
%type<floatval> FLOAT
%type<strval> ID
%type<typeval> TYPENAME fun_return
%type<statementval> statement
%type<statlistval> branch_body
%type<statlistval> statements
%type<branchbodyval> branch_body
%type<assertval> assert_stmt
%type<callval> fun_call
%type<argval> arg_decl
%type<arglistval> args_decl args
%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<caselistval> cases
%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<exprlistval> call_arglist call_args
%type<semiexpval> semi_expression
%type<idval> variable
%type<numericval> numeric
@ -155,31 +152,24 @@ fun_decls:
fun_decls
;
fun_decl:
FUN_DECL fun_return ID {
funArgStack.push(new FunArgList());
} args FUN_END {
stmtStack.push(new StatementList());
}
statements {
$$ = new Function(new Id($3), $2, funArgStack.top(), stmtStack.top());
funArgStack.pop();
stmtStack.pop();
FUN_DECL fun_return ID args FUN_END statements {
$$ = new Function(new Id($3), $2, $4, $6);
}
;
fun_return:
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
;
args:
/* epsilon */ | PARAMS args_decl
/* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; }
;
args_decl:
arg_decl {
funArgStack.top()->push_back($1);
$$ = new FunArgList();
$$->push_back($1);
}
| arg_decl {
funArgStack.top()->push_back($1);
| args_decl COMMA arg_decl {
$1->push_back($3);
}
COMMA args_decl
;
arg_decl:
variable pointer TYPENAME {
@ -187,23 +177,20 @@ arg_decl:
}
;
main:
MAIN {
stmtStack.push(new StatementList());
}
statements {
$$ = new Main(stmtStack.top());
stmtStack.pop();
MAIN statements {
$$ = new Main($2);
}
;
statements:
/* epsilon */ {
$$ = new StatementList();
}
| statement {
if ($1 != nullptr) {
stmtStack.top()->push_back($1);
| statements statement {
if ($2 != nullptr) {
$1->push_back($2);
}
$$ = $1;
}
statements
;
statement:
assert_stmt { $$ = $1; }
@ -264,61 +251,59 @@ maybe_expression:
expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; }
;
loop_stmt:
LOOP_BEGIN {
stmtStack.push(new StatementList());
}
statements LOOP_CONDITION expression {
$$ = new Loop(stmtStack.top(), $5);
stmtStack.pop();
LOOP_BEGIN statements LOOP_CONDITION expression {
$$ = new Loop($2, $4);
}
;
branch_stmt:
BRANCH_CONDITION variable BRANCH_BEGIN {
branchCaseStack.push(new BranchCaseList());
}
branch_body BRANCH_END {
$$ = new Branch($2, branchCaseStack.top(), $5);
branchCaseStack.pop();
BRANCH_CONDITION variable BRANCH_BEGIN branch_body BRANCH_END {
$$ = new Branch($2, $4);
}
;
branch_body:
cases %prec LOWER_THAN_ELSE {
$$ = nullptr;
$$ = new Branch::Body($1);
}
| cases BRANCH_ELSE COLON {
stmtStack.push(new StatementList());
}
statements {
$$ = stmtStack.top();
stmtStack.pop();
| cases BRANCH_ELSE COLON statements {
$$ = new Branch::Body($1, $4);
}
;
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:
semi_expression COLON {
stmtStack.push(new StatementList());
} statements {
branchCaseStack.top()->push_back(new BranchCase($1, stmtStack.top()));
stmtStack.pop();
semi_expression COLON statements {
$$ = new BranchCase($1, $3);
}
;
fun_call:
FUN_CALL {
argsStack.push(new ExpressionList());
}
ID call_args FUN_END {
$$ = new FunctionCall(new Id($3), argsStack.top());
argsStack.pop();
FUN_CALL ID call_args FUN_END {
$$ = new FunctionCall(new Id($2), $3);
}
;
call_args:
/* epsilon */ | PARAMS call_arglist
/* epsilon */ {
$$ = new ExpressionList();
}
| PARAMS call_arglist {
$$ = $2;
}
;
call_arglist:
expression { argsStack.top()->push_back($1); }
| expression { argsStack.top()->push_back($1); } COMMA call_arglist
expression {
$$ = new ExpressionList();
$$->push_back($1);
}
| call_arglist COMMA expression {
$$->push_back($3);
}
;
abort_stmt:
ABORT {

View File

@ -122,9 +122,9 @@ void Branch::emit(std::ostream &stream, int indent) {
stream << "if (";
var->emit(stream);
if (cases->size() > 0) {
BranchCase *last = cases->back();
for (BranchCase *c: *cases) {
if (body->cases->size() > 0) {
BranchCase *last = body->cases->back();
for (BranchCase *c: *body->cases) {
c->emit(stream, indent + 1);
if (c != last) {
stream << " else if (";
@ -133,12 +133,12 @@ void Branch::emit(std::ostream &stream, int indent) {
}
}
if (els == nullptr) {
if (body->els == nullptr) {
return;
}
stream << " else {\n";
els->emit(stream, indent + 1);
body->els->emit(stream, indent + 1);
emitIndent(stream, indent);
stream << "}";
}

View File

@ -265,14 +265,23 @@ typedef PointerList<BranchCase> BranchCaseList;
class Branch: public Statement {
public:
Branch(Id *v, BranchCaseList *c, StatementList *e):
var(v), cases(c), els(e) {}
struct Body {
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);
private:
Pointer<Id> var;
Pointer<BranchCaseList> cases;
Pointer<StatementList> els;
Pointer<Branch::Body> body;
};