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
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2014 Stefano Sanfilippo
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
@ -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 {
|
||||
|
|
10
Nodes.cpp
10
Nodes.cpp
|
@ -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 << "}";
|
||||
}
|
||||
|
|
17
Nodes.hpp
17
Nodes.hpp
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Reference in New Issue
Block a user