/* SI 413 Fall 2011
 * Lab 6
 * spl-pt2.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 "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; }

%}


%left BOP
%right NOT
%left COMP
%left OPA
%left OPM
%right POSNEG

%nonassoc LC RC LP RP NUM BOOL ID LAMBDA IF ELSE WHILE READ WRITE NEW STOP ASN

%%
  /*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 exp      {$$ = new ParseTree("exp",$1,$2,$3);}
|    NOT exp          {$$ = new ParseTree("exp",$1,$2);}
|    exp COMP exp     {$$ = new ParseTree("exp",$1,$2,$3);}
|    exp OPA exp      {$$ = new ParseTree("exp",$1,$2,$3);}
|    exp OPM exp      {$$ = new ParseTree("exp",$1,$2,$3);}
|    OPA exp %prec POSNEG {$$ = new ParseTree("exp",$1,$2);}
|    LAMBDA ID block  {$$ = new ParseTree("exp",$1,$2,$3);}
|    ID LP exp RP     {$$ = new ParseTree("exp",$1,$2,$3,$4);}
|    LP exp RP        {$$ = new ParseTree("exp",$1,$2,$3);}
|    ID               {$$ = new ParseTree("exp",$1);}
|    NUM              {$$ = new ParseTree("exp",$1);}
|    BOOL             {$$ = new ParseTree("exp",$1);}

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