Last active
May 30, 2020 07:54
-
-
Save mrakgr/b16ced3ec9cb92c8adbc79d85914ce3f to your computer and use it in GitHub Desktop.
FemtoML parser in F# using FParsec (rewrite of Jon Harrop's example)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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