/* SI 413 Fall 2011
 * Lab 6
 * spl-pt1.ypp 
 * Parser for SPL that just shows the parse tree
 */

%{
#include <cstdlib>
#include <iostream>
using namespace std;

#include "parsetree.hpp"

ParseTree* tree; // This global will be set to the whole parse tree.

int yylex(); 
int yyerror(const char *p) { cerr << "Parse error!" << endl; }

%}

%token LC RC LP RP NUM BOOL ID LAMBDA IF WHILE READ WRITE NEW STOP ASN ELSE
%token BOP NOT COMP OPA OPM

%%
  /*Note: YYACCEPT is a bison macro that just tells it to quit parsing.*/
res: block { tree = $1; YYACCEPT; }
|    stmt  { tree = $1; YYACCEPT; }
|          { tree = NULL; }

block: LC stmtlist RC { $$ = new ParseTree("block",$2); }

stmtlist: stmtlist stmt { $$ = new ParseTree("stmtlist",$1,$2); }
|         stmt          { $$ = new ParseTree("stmtlist",$1); }

stmt: NEW ID ASN exp STOP           {$$ = new ParseTree("stmt",$1,$2,$3,$4,$5);}
|     ID ASN exp STOP               {$$ = new ParseTree("stmt",$1,$2,$3,$4);}
|     READ ID STOP                  {$$ = new ParseTree("stmt",$1,$2,$3);}
|     WRITE exp STOP                {$$ = new ParseTree("stmt",$1,$2,$3);}
|     IF LP exp RP block            {$$ = new ParseTree("stmt",$1,$2,$3,$4,$5);}
|     IF LP exp RP block ELSE block {$$ = new ParseTree
                                            ("stmt",$1,$2,$3,$4,$5,$6,$7);
                                    }
|     WHILE LP exp RP block         {$$ = new ParseTree("stmt",$1,$2,$3,$4,$5);}
|     exp STOP                      {$$ = new ParseTree("stmt",$1,$2);}

exp: exp BOP nexp       {$$ = new ParseTree("exp",$1,$2,$3);}
|    nexp               {$$ = new ParseTree("exp",$1);}


nexp: NOT cexp          {$$ = new ParseTree("nexp",$1,$2);}
|     cexp              {$$ = new ParseTree("nexp",$1);}

cexp: cexp COMP aexp    {$$ = new ParseTree("cexp",$1,$2,$3);}
|     aexp              {$$ = new ParseTree("cexp",$1);}

aexp: aexp OPA term     {$$ = new ParseTree("aexp",$1,$2,$3);}
|     term              {$$ = new ParseTree("aexp",$1);}

term: term OPM sfactor  {$$ = new ParseTree("term",$1,$2,$3);}
|     sfactor           {$$ = new ParseTree("term",$1);}

sfactor: OPA factor     {$$ = new ParseTree("sfactor",$1,$2);}
|        factor         {$$ = new ParseTree("sfactor",$1);}

factor: ID | NUM | BOOL {$$ = new ParseTree("factor",$1);}
| LP exp RP             {$$ = new ParseTree("factor",$1,$2,$3);}
| ID LP exp RP          {$$ = new ParseTree("factor",$1,$2,$3,$4);}
| LAMBDA ID block       {$$ = new ParseTree("factor",$1,$2,$3);}

%%
int main()
{
  while(true) {
    yyparse();
    if (tree == NULL) break;
    tree->writeDot("spl1.dot");
    system("dot -Tpdf spl1.dot > spl1.pdf");
    system("evince spl1.pdf &");
  }
  return 0;
}