我正在尝试解析 SQL 搜索条件,但无法让解析器将逻辑 ( AND
, OR
) 与其他中缀运算符区分开来。我将它们解析为不同的节点(也许这很难做到),但简化了评估阶段。这是相关的代码片段(如有必要,我可以包含更多)。
let opp = OperatorPrecedenceParser<_,_,_>()
let scalarExpr = opp.ExpressionParser
opp.TermParser <- constant <|> id <|> between lparen rparen scalarExpr <|> scalarExpr
//infix operators added here
let comparison = //(e.g., 1 < 2)
let compareExpr = pipe3 scalarExpr compareOp scalarExpr (fun l op r -> Comparison(op, l, r))
between lparen rparen compareExpr <|> compareExpr
let andTerm = pstringCI "and" .>> ws
let orTerm = pstringCI "or" .>> ws
let searchCondition, searchConditionRef = createParserForwardedToRef()
searchConditionRef :=
[ comparison
pipe3 searchCondition andTerm searchCondition (fun l _ r -> And(l, r))
pipe3 searchCondition orTerm searchCondition (fun l _ r -> Or(l, r))
between lparen rparen searchCondition ]
|> choice
let filter : Parser<_,unit> = ws >>. searchCondition .>> eof
"1 = 1"
正确解析为Comparison (Eq,Constant (Int32 1),Constant (Int32 1))
但是一旦我尝试使用逻辑运算符加入两个比较,例如"1 = 1 or 2 = 2"
,它无法解析
Ln 中的错误:1 Col:7
1 = 1 或 2 = 2
^
预期:输入结束或中缀运算符
:7
我希望它将1
错误之前的错误解析为标量表达式,并在or
回溯时意识到它不是中缀运算符,1
作为完整的标量返回,并识别它正在解析由逻辑运算符连接的条件的左侧or
。
相反,它似乎继续假设1
开始一个更复杂的标量表达式,可能涉及中缀运算符。
代码有问题,还是将AND
/解析OR
为中缀运算符的解决方案(使用相同的OperatorPrecedenceParser
)?我宁愿不走那条路,所以我希望我在某个地方犯了一个简单的错误。
完整的代码在要点上。