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

@ -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 {

View File

@ -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 << "}";
} }

View File

@ -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;
}; };