-- calculator.hs — recursive descent expression evaluator.
--
-- Tokens are represented as an ADT; the parser threads a [Token] list
-- through a custom Result type so pattern matching can destructure the
-- pair (value, remaining-tokens) directly inside constructor patterns.
--
-- Operator precedence: * and / bind tighter than + and -.
-- All operators are left-associative.

data Token = TNum Int | TOp String
data Result = R Int [Token]

getV (R v _) = v
getR (R _ r) = r

eval ts = getV (parseExpr ts)

parseExpr ts = parseExprRest (parseTerm ts)

parseExprRest (R v (TOp "+":rest)) =
  let t = parseTerm rest
  in parseExprRest (R (v + getV t) (getR t))
parseExprRest (R v (TOp "-":rest)) =
  let t = parseTerm rest
  in parseExprRest (R (v - getV t) (getR t))
parseExprRest r = r

parseTerm ts = parseTermRest (parseFactor ts)

parseTermRest (R v (TOp "*":rest)) =
  let t = parseFactor rest
  in parseTermRest (R (v * getV t) (getR t))
parseTermRest (R v (TOp "/":rest)) =
  let t = parseFactor rest
  in parseTermRest (R (v `div` getV t) (getR t))
parseTermRest r = r

parseFactor (TNum n:rest) = R n rest

result = eval [TNum 2, TOp "+", TNum 3, TOp "*", TNum 4]
