%{
package main
%}

%union {
  s string
  expr *Expr
}

%token DEF_FORM
%token ASSIGN
%token ID
%token MONEY
%token FRAC
%token XREF
%token FUNC
%left '+' '-'
%left '*' '/'
%%
input: /* empty */
       | input stuff

stuff: DEF_FORM { cast(yylex).BeginForm($1.s) }
     | '}'      { cast(yylex).EndForm() }
     | ASSIGN   { cast(yylex).Assign($1.s) }
     | expr     { cast(yylex).Expr($1.expr) }

expr: atom
    | expr '+' expr { $$.expr = NewOp($2.s, $1.expr, $3.expr) }
    | expr '-' expr { $$.expr = NewOp($2.s, $1.expr, $3.expr) }
    | expr '*' expr { $$.expr = NewOp($2.s, $1.expr, $3.expr) }
    | expr '/' expr { $$.expr = NewOp($2.s, $1.expr, $3.expr) }

atom: MONEY        { $$.expr = NewExpr("$", $1.s) }
    | ID           { $$.expr = NewExpr("ID", $1.s) }
    | '(' expr ')' { $$.expr = $2.expr }
    | XREF         { $$.expr = NewExpr("XREF", $1.s) }
    | FUNC arglist ')' { $$.expr = NewFun($1.s, $2.expr) }
    | FRAC         { $$.expr = NewExpr("%", $1.s) }

arglist: expr { $$.expr = NewExpr("", ""); $$.expr.AddKid($1.expr) }
       | arglist ',' expr { $1.expr.AddKid($3.expr) }

%%
func cast(y yyLexer) *Tacky { return y.(*Lexer).p }
