/* SI 413 Fall 2011 * spl.ypp * Parser for SPL that just shows the parse tree * This parser uses a simpler grammar with assoc/prec specifications. */ %{ #include <cstdlib> #include <iostream> using namespace std; #include "ast.hpp" Stmt* tree; // This global will be set to the whole AST. int yylex(); int yyerror(const char *p) { cerr << "Parser: " << p << endl; return 0; } %} %union { Block* block; Stmt* stmt; Exp* exp; Id* id; Oper op; }; %left<op> BOP %right<op> NOT %left<op> COMP %left<op> OPA %left<op> OPM %right POSNEG %nonassoc LP %token LC RC RP LAMBDA IF ELSE WHILE READ WRITE NEW ASN STOP %token<id> ID %token<exp> NUM BOOL %type<stmt> stmt stmtlist %type<block> block %type<exp> exp %% /*Note: YYACCEPT is a bison macro that just tells it to quit parsing.*/ res: stmt { tree = $1; YYACCEPT; } | { tree = NULL; } block: LC stmtlist RC { $$ = new Block($2); } stmtlist: stmtlist stmt { $$ = Stmt::append($1,$2); } | { $$ = new NullStmt; } stmt: NEW ID ASN exp STOP {$$ = new NewStmt($2,$4);} | ID ASN exp STOP {$$ = new Asn($1,$3);} | READ ID STOP {$$ = new Read($2);} | WRITE exp STOP {$$ = new Write($2);} | IF LP exp RP block {$$ = new IfStmt($3,$5);} | IF LP exp RP block ELSE block {$$ = new IfElse($3,$5,$7);} | WHILE LP exp RP block {$$ = new WhileStmt($3,$5);} | block {$$ = $1;} exp: exp BOP exp {$$ = new BoolOp($1,$2,$3);} | NOT exp {$$ = new NotOp($2);} | exp COMP exp {$$ = new CompOp($1,$2,$3);} | exp OPA exp {$$ = new ArithOp($1,$2,$3);} | exp OPM exp {$$ = new ArithOp($1,$2,$3);} | OPA exp %prec POSNEG {$$ = ($1 == ADD ? $2 : new NegOp($2));} | LAMBDA ID block {$$ = new Lambda($2,$3);} | exp LP exp RP {$$ = new Funcall($1,$3);} | LP exp RP {$$ = $2;} | ID {$$ = $1;} | NUM {$$ = $1;} | BOOL {$$ = $1;} %% int main() { while(true) { tree = NULL; yyparse(); if (tree == NULL) break; tree->writeDot("spl.dot"); system("dot -Tpdf spl.dot > spl.pdf"); system("evince spl.pdf > /dev/null 2>&1 &"); tree->exec(); } return 0; }