1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | /* SI 413 Fall 2012 * Lab 7 * Parser for SPL that just shows the parse tree * This parser uses a simpler grammar with assoc/prec specifications. */ // This code is included in the spl.tab.hpp header file %code requires { #include <cstdlib> #include <iostream> using namespace std; #include "ast.hpp" int yylex(); } // end header file part // This code is only included in the parser file spl.tab.cpp %code { // These are the colored output streams to make things all pretty. colorout resout(1, 'u'); colorout errout(2, 'r'); // Global variable will be set to the entire AST. Stmt* tree; // Global variable to indicate if an error has occurred. bool error; // Global variable to indicate that terminal input is "live" and // so prompts should be displayed. bool showPrompt; // This is the C file that flex reads from for scanning. extern FILE* yyin; void yyerror(const char *p) { if (! error) { errout << "Parser error: " << p << endl; error = true; } } } // end top of parser part /* Tell bison to give descriptive error mesages. */ %error-verbose %union { Block* block; Stmt* stmt; Exp* exp; Id* id; Oper op; }; %left<op> BOP %right<op> NOTTOK %left<op> COMP %left<op> OPA %left<op> OPM %right POSNEG %left FUNARG %token LC RC LP RP LAMBDA IF IFELSE 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);} | WRITE exp STOP {$$ = new Write($2);} | IF exp block {$$ = new IfStmt($2,$3,new NullStmt());} | IFELSE exp block block {$$ = new IfStmt($2,$3,$4);} | WHILE exp block {$$ = new WhileStmt($2,$3);} | block {$$ = $1;} exp: exp BOP exp {$$ = new BoolOp($1,$2,$3);} | NOTTOK 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));} | READ {$$ = new Read();} | LAMBDA ID block {$$ = new Lambda($2,$3);} | exp FUNARG exp {$$ = new Funcall($1,$3);} | LP exp RP {$$ = $2;} | ID {$$ = $1;} | NUM {$$ = $1;} | BOOL {$$ = $1;} %% int main(int argc, char** argv) { showPrompt = isatty(0) && isatty(2); bool interactive = showPrompt; if (argc >= 2) { if (!(yyin = fopen(argv[1],"r"))) { cerr << "Could not open input file \"" << argv[1] << "\"!" << endl; exit(2); } interactive = false; } if (interactive) { bool showAST = true; // set to false to stop the AST from popping up. // This is the "interactive" version of the interpreter. // It keeps going, even if there are errors, and prints out // prompts and such. while(true) { tree = NULL; error = false; cerr << "spl> "; yyparse(); if (tree == NULL && ! error) break; else if (tree != NULL) { tree->writeDot("spl.dot"); system("dot -Tpdf spl.dot > spl.pdf"); if (showAST) system("evince spl.pdf > /dev/null 2>&1 &"); tree->exec(); } } cerr << "Goodbye" << endl; } else { // This is the non-interactive version of the interpreter. // It exits with return code 5 if there is any kind of error, // and doesn't display prompts or other niceties. error = false; while(! error) { tree = NULL; if (yyparse() != 0 || error || tree == NULL) break; tree->writeDot("spl.dot"); system("dot -Tpdf spl.dot > spl.pdf"); tree->exec(); } if (error) return 5; } return 0; } |