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
/* SI 413 Fall 2013
 * Lab 6
 * Parser for pat that just shows the parse tree
 * YOUR NAME HERE
 * PARTNER 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(3);
}
 
ParseTree* tree; // 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. */
%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.
  // If it is, we'll show trees as pdf files.
  bool tty = isatty(0) && isatty(2);
 
  while(true) {
    tree = NULL;
    yyparse();
    if (done) break;
    if (tty) {
      tree->writeDot("pat.dot");
      system("dot -Tpdf pat.dot > pat.pdf");
      system("evince pat.pdf > /dev/null 2>&1 &");
    }
    else {
      tree->writeTo(resout);
    }
  }
 
  // Try to kill off any parse tree windows that are hanging around
  system("kill `pgrep -f \"evince pat.pdf\"`");
 
  return 0;
}