Skip to content

Instantly share code, notes, and snippets.

@mrakgr
Last active May 30, 2020 07:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrakgr/b16ced3ec9cb92c8adbc79d85914ce3f to your computer and use it in GitHub Desktop.
Save mrakgr/b16ced3ec9cb92c8adbc79d85914ce3f to your computer and use it in GitHub Desktop.
FemtoML parser in F# using FParsec (rewrite of Jon Harrop's example)
let pInt s = (puint32 |>> int .>> spaces) s
let str s = pstring s .>> spaces
let keywords = "if then else let rec in fun".Split ' ' |> set
let pIdent s =
let isAlphaNum c = isLetter c || isDigit c
(many1Satisfy2L isLetter isAlphaNum "identifier" .>> spaces
>>=? fun x _ -> if keywords.Contains x then Reply(Error, expected "identifier") else Reply(x)) s
let rec pExpr s =
let pAtom s =
choice [
pInt |>> Int
pIdent |>> Ident
between (str "(") (str ")") pExpr ] s
let pExprInner s =
choice [
many1 pAtom |>> fun fs -> List.reduce (fun f g -> Apply(f, g)) fs
pipe3 (str "if" >>. pExpr) (str "then" >>. pExpr) (str "else" >>. pExpr)
(fun p t f -> If(p, t, f))
pipe3 (str "let" >>. (str "rec" >>. pIdent .>> str "=")) pExpr (str "in" >>. pExpr)
(fun var body rest -> LetRec(var, body, rest))
pipe2 (str "fun" >>. pIdent .>> str "->") pExpr
(fun par body -> Lambda(par, body)) ] s
let pOp op expr = pipe2 expr (many (op .>>. expr)) (List.fold (fun a (op,b) -> Op(a,op,b)))
List.foldBack pOp [str "<"; choice [str "+"; str "-"]] pExprInner s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment