module CS334 open Parser (* AST *) type Expr = | Num of int | Plus of Expr list (* HELPER COMBINATORS *) (* * Returns a list of p separated by sep * @param p A parser. * @param sep A separator parser. *) let pmany2sep p sep = pseq p (pmany1 (pright sep p)) (fun (x,xs) -> x::xs) "pmany2sep" (* * Accepts whatever p accepts, surrounded * by parens, i.e., (p), and returns whatever p * returns. * @param p A parser. *) let inParens p = pbetween (pchar '(') (pchar ')') p "inParens" (* * A helper that accepts whatever p accepts, * surrounded by parens, i.e., (plus p), and * returns whatever p returns. * @param p A parser. *) let inPlus p = inParens (pright (pstr "plus ") p) "inPlus" (* PLUSLANG GRAMMAR *) let expr, exprImpl = recparser() let number = pmany1 pdigit |>> (fun ds -> Num (int (stringify ds))) "number" let plusExpr = inPlus (pmany2sep expr pws1) |>> (fun es -> Plus(es)) "plusExpr" exprImpl := plusExpr <|> number "expr" let grammar = pleft expr peof "grammar" (* EVALUATOR *) let rec eval e = match e with | Num n -> n | Plus es -> // eager evaluation! es |> List.map eval // evaluate arguments first |> List.sum // then add all the numbers