-- An example demonstrating how to connect a Happy parser to an Alex lexer.
{
import Tokens_posn
}

%name calc
%tokentype { Token }

%token  let		{ Let _     }
	in		{ In  _     }
	int		{ Int _ $$  }
	var		{ Var _ $$  }
	'='		{ Sym _ '=' }
	'+'		{ Sym _ '+' }
	'-'		{ Sym _ '-' }
	'*'		{ Sym _ '*' }
	'/'		{ Sym _ '/' }
	'('		{ Sym _ '(' }
	')'		{ Sym _ ')' }

%%

Exp :: { Exp }
Exp : let var '=' Exp in Exp	{ LetE $2 $4 $6 }
    | Exp1			{ $1            }

Exp1 : Exp1 '+' Term		{ PlusE  $1 $3  }
     | Exp1 '-' Term		{ MinusE $1 $3  }
     | Term			{ $1            }

Term : Term '*' Factor		{ TimesE $1 $3  }
     | Term '/' Factor		{ DivE $1 $3    }
     | Factor			{ $1            }

Factor : '-' Atom		{ NegE $2	}
       | Atom			{ $1		}

Atom : int			{ IntE $1       }
       | var			{ VarE $1       }
       | '(' Exp ')'		{ $2            }

{
data Exp =
	LetE   String Exp Exp |
	PlusE  Exp Exp        |
	MinusE Exp Exp        |
	TimesE Exp Exp        |
	DivE   Exp Exp        |
	NegE   Exp	      |
	IntE   Int            |
	VarE   String
	deriving Show


main:: IO ()
main = interact (show.runCalc)

runCalc :: String -> Exp
runCalc = calc . alexScanTokens

happyError :: [Token] -> a
happyError tks = error ("Parse error at " ++ lcn ++ "\n")
	where
	lcn = 	case tks of
		  [] -> "end of file"
		  tk:_ -> "line " ++ show l ++ ", column " ++ show c
			where
			AlexPn _ l c = token_posn tk
}
