module CircleLang open Parser (* AST *) type Shape = | Circle type Expr = | Shapes of Shape list (* GRAMMAR *) // circle // circle circle // circle circle circle // circlecirclecircle (* * ::= * ::= + * ::= * * ::= circle *) let pcircle: Parser = pstr "circle" |>> (fun _ -> Circle) let pshape: Parser = pleft pcircle pws0 let pshapes: Parser = pmany1 pshape |>> (fun ss -> Shapes ss) let grammar: Parser = pleft pshapes peof let parse (input: string) : Expr option = let i = prepare input match grammar i with | Success(ast,_) -> Some ast | Failure(_,_) -> None (* EVALUATOR *) let doctype = "\n" let prefix = "\n" let suffix = "\n" let rec evalShapes (ss: Shape list)(x: int) : string = match ss with | [] -> "" | s::ss' -> let circle = "\n" let circles = evalShapes ss' (x + 30) circle + circles let eval (e: Expr) : string = let str = match e with | Shapes ss -> evalShapes ss 25 doctype + prefix + str + suffix