Created
January 20, 2013 23:15
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
type BooleanExpr = | |
| Atom of bool | |
| Binary of BooleanExpr * string * BooleanExpr | |
| Not of BooleanExpr | |
let rec evalBool = function | |
| Atom x -> x | |
| Binary (left, "&", right) -> if evalBool left then evalBool right else false | |
| Binary (left, "|", right) -> if evalBool left then true else evalBool right | |
| Binary (_, x, _) -> failwith <| "Unexpected binary operator: " + x | |
| Not x -> not <| evalBool x | |
let boolGrammar = | |
// bool <- "true" / "false" | |
let boolRule = GrammarRule<BooleanExpr>(Choice [Terminal "true"; Terminal "false"], (fun s _ -> Parsed (Atom (s = "true")))) | |
// space <- " "* | |
let spaceRule = GrammarRule<BooleanExpr>(ZeroOrMore (Terminal " "), (fun _ _ -> EmptyMatch)) | |
// paren <- "(" space expr space ")" | |
let boolParen _ = function | |
| Production [TerminalSymbol "("; EmptyMatch; x; EmptyMatch; TerminalSymbol ")"] -> x | |
| x -> unexpected x | |
let parenRule = GrammarRule<BooleanExpr>(Sequence [Terminal "("; NonTerminal "space"; NonTerminal "expr"; NonTerminal "space"; Terminal ")"], boolParen) | |
// not <- "!" atom | |
let boolNot _ = function | |
| Production [TerminalSymbol "!"; Parsed x] -> Parsed (Not x) | |
| x -> unexpected x | |
let notRule = GrammarRule<BooleanExpr>(Sequence [Terminal "!"; NonTerminal "atom"], boolNot) | |
// atom <- "bool" / "paren" / "not" | |
let atomRule = GrammarRule<BooleanExpr>(Choice [NonTerminal "bool"; NonTerminal "paren"; NonTerminal "not"], (fun _ x -> x)) | |
// or <- atom space ("|" space or)? | |
// and <- or space ("&" space and)? | |
let boolBinary _ = function | |
| Production [x; EmptyMatch; EmptyMatch] -> x | |
| Production [Parsed x; EmptyMatch; Production [TerminalSymbol op; EmptyMatch; Parsed y]] -> Parsed (Binary (x, op, y)) | |
| x -> unexpected x | |
let orRule = GrammarRule<BooleanExpr>(Sequence [NonTerminal "atom"; NonTerminal "space"; Optional (Sequence [Terminal "|"; NonTerminal "space"; NonTerminal "or"])], boolBinary) | |
let andRule = GrammarRule<BooleanExpr>(Sequence [NonTerminal "or"; NonTerminal "space"; Optional (Sequence [Terminal "&"; NonTerminal "space"; NonTerminal "and"])], boolBinary) | |
// expr <- and | |
let exprRule = GrammarRule<BooleanExpr>(NonTerminal "and", (fun _ x -> x)) | |
// start <- space expr space <epsilon> | |
let boolStart _ = function | |
| Production [EmptyMatch; x; EmptyMatch; EmptyMatch] -> x | |
| x -> unexpected x | |
let startRule = GrammarRule<BooleanExpr>(Sequence [NonTerminal "space"; NonTerminal "expr"; NonTerminal "space"; Epsilon], boolStart) | |
Map.ofList [("bool", boolRule); ("space", spaceRule); ("paren", parenRule); ("not", notRule); | |
("atom", atomRule); ("or", orRule); ("and", andRule); ("expr", exprRule); ("start", startRule)] | |
let parseAndEvalBool expr = | |
match parseExpression boolGrammar "start" expr with | |
| (Parsed b, _) -> printfn "%s = %A" expr (evalBool b) | |
| x -> unexpected x |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment