Skip to content

Instantly share code, notes, and snippets.

@jdh30
Last active June 6, 2020 03:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdh30/8289c160ff29ff3d19e2e4eecbabe3de to your computer and use it in GitHub Desktop.
Save jdh30/8289c160ff29ff3d19e2e4eecbabe3de to your computer and use it in GitHub Desktop.
FemtoML parser in F# using FParsec
> let pInt : Parser<_, unit> = puint32 |>> int .>> spaces;;
> let str s = pstring s >>. spaces;;
> let keywords =
"if then else let rec in fun".Split ' '
|> set;;
> let pIdent : Parser<_, unit> =
let isAlphaNum c = isLetter c || isDigit c
let idStr = many1Satisfy2L isLetter isAlphaNum "identifier" .>> spaces
let p state =
let reply = idStr state
if reply.Status = Ok && keywords.Contains reply.Result then
Reply(Error, expected "identifier")
else
reply
attempt p .>> spaces;;
> let opp = OperatorPrecedenceParser<Expr,unit,unit>();;
> let pExpr = opp.ExpressionParser .>> spaces;;
> let pAtom =
choice
[ pInt |>> Int
pIdent |>> Ident
between (str "(") (str ")") pExpr ];;
> opp.TermParser <-
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)) ];;
> opp.AddOperator(InfixOperator("<", spaces, 1, Associativity.Left, fun f g -> BinOp(f, Lt, g)));;
> opp.AddOperator(InfixOperator("+", spaces, 2, Associativity.Left, fun f g -> BinOp(f, Add, g)));;
> opp.AddOperator(InfixOperator("-", spaces, 2, Associativity.Left, fun f g -> BinOp(f, Sub, g)));;
> let parse str = run (spaces >>. pExpr .>> eof) str;;
@jdh30
Copy link
Author

jdh30 commented Jun 6, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment