module CS334 open Combinator (* START AST DEFINITION *) type Expr = | Num of int | Plus of Expr * Expr (* END AST DEFINITION *) (* START PARSER DEFINITION *) let expr, exprImpl = recparser() let number = pmany1 pdigit |>> (fun ds -> stringify(ds)) |>> (fun s -> int(s)) |>> (fun i -> Num(i)) let plus = pbetween (pstr "(plus ") (pseq (pleft expr pws1) expr Plus ) (pchar ')') exprImpl := plus <|> number let grammar = pleft expr peof (* END PARSER DEFINITION *) (** * Interprets the AST, returning an F# integer result. * * @param ast An Expr. * @returns the numeric result. *) let rec eval ast : int = match ast with | Num(n) -> n | Plus(e1, e2) -> let e1res = eval e1 let e2res = eval e2 e1res + e2res (** * This is a convenience function for the main function * so that the parser can be called with an ordinary * string input. The result returns an option type * because parsing can fail. This function simplifies the * fact that our parser combinator library requires the * use of Input and Outcome<'a> types so that using the * parser is easier. * * @param input A string to parse. * @returns Some ast or None if the parse fails. *) let parse input = let i = prepare input match grammar i with | Success(ast,_) -> Some ast | Failure(_,_) -> None