/* SI 413 Fall 2021
* Lab 6
* Parser for pat that just shows the parse tree
* YOUR NAME HERE
*/
%code requires {
#include <cstdlib>
#include <iostream>
#include "colorout.hpp"
#include "parsetree.hpp"
using namespace std;
// This says that semantic values of tokens should be ParseTree pointers.
#define YYSTYPE ParseTree*
int yylex();
extern colorout resout;
extern colorout errout;
}
%code {
int yyerror(const char *p) {
errout << "Parser error: " << p << endl;
exit(1);
}
ParseTree* tree = NULL; // This global will be set to the whole parse tree.
// Global variable to indicate to stop parsing.
bool done = false;
// These are the colored output streams to make things all pretty.
colorout resout(1, 'u');
colorout errout(2, 'r');
}
/* Tell bison to give descriptive error mesages. */
%define parse.error verbose
/* This defines the tokens. You will have to change this to
set their precedence and associativity!
*/
%token STOP FOLD COLON REV SYM NAME LB RB
%%
/*Note: YYACCEPT is a bison macro that just tells it to quit parsing.*/
S: seq STOP { tree = $1; YYACCEPT; }
| { done = true; }
seq: seq FOLD catseq {$$ = new ParseTree("seq",$1,$2,$3);}
| catseq {$$ = new ParseTree("seq",$1);}
catseq: catseq opseq {$$ = new ParseTree("catseq",$1,$2);}
| opseq {$$ = new ParseTree("catseq",$1);}
opseq: opseq COLON NAME {$$ = new ParseTree("opseq",$1,$2,$3);}
| opseq REV {$$ = new ParseTree("opseq",$1,$2);}
| atom {$$ = new ParseTree("opseq",$1);}
atom: SYM {$$ = new ParseTree("atom",$1);}
| NAME {$$ = new ParseTree("atom",$1);}
| LB seq RB {$$ = new ParseTree("atom",$1,$2,$3);}
%%
int main()
{
// This checks whether the output is a terminal.
bool tty = isatty(0) && isatty(2);
while(true) {
if (tty) cerr << "> ";
yyparse();
if (done) break;
if (isatty(1)) {
// try to create parse tree pdf and display it
tree->writeDot("pat.dot");
if(system("dot -Tpdf pat.dot >pat.pdf") == 0) {
if (system("evince pat.pdf >/dev/null 2>&1 &") != 0) {
resout << "tree created in pat.pdf" << endl;
}
}
else {
errout << "error creating pat.pdf. Try 'sudo apt install graphviz'" << endl;
}
}
else {
// not running on a terminal, so do a textual representation of the tree.
tree->writeTo(resout);
}
delete tree;
}
if (tty) cerr << "Goodbye!" << endl;
// Try to kill off any parse tree windows that are hanging around
(void)!system("kill `pgrep -f \"evince pat.pdf\"`");
return 0;
}