I'm parsing SQL expressions and have been looking at this example. So far I'm focused on boolean operators like AND, OR, NOT, IN and NOT IN. The first four seem easy to implement, however I'm not sure what to do with NOT IN:
type BinaryExpr = {left: SqlExpr; right: SqlExpr}
and SqlExpr =
And of BinaryExpr
| Or of BinaryExpr
| Not of SqlExpr
| In of BinaryExpr
| NotIn of BinaryExpr
| Identifier of string
let parser =
let opp = OperatorPrecedenceParser<SqlExpr, unit, unit>()
let ws = spaces
let ws1 = nextCharSatisfiesNot isLetter >>. ws
let expr = opp.ExpressionParser
opp.TermParser <- identifier <|> expr
let buildAnd x y = And { left = x; right = y }
let buildOr x y = Or { left = x; right = y }
let buildIn x y = In { left = x; right = y }
let buildNotIn x y = NotIn { left = x; right = y }
opp.AddOperator(InfixOperator("OR", ws1, 1, Associativity.Left, buildOr))
opp.AddOperator(InfixOperator("AND", ws1, 2, Associativity.Left, buildAnd))
opp.AddOperator(PrefixOperator("NOT", ws1, 3, false, Not))
opp.AddOperator(InfixOperator("IN", ws1, 4, Associativity.None, buildIn))
opp.AddOperator(InfixOperator("NOT IN", ws1, 4, Associativity.None, buildNotIn))
ws >>. expr .>> eof
What I want is:
- Handle more than one space between "NOT" and "IN"
- Parse "NOT IN" as a binary operator
Currently I'm failing in the first point.
I'm assuming that NOT IN is semantically a binary operator and because of that I have created the NotIn type variant.