Я пытаюсь разобрать условия поиска 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
backtrack, понимая, что это не инфиксный оператор, возврат1
как полный скаляр и узнайте, что он разбирает левую часть условия, к которому присоединяется логический оператор or
.
Вместо этого он, кажется, продолжает предполагать, что 1
начинает более сложное скалярное выражение, возможно, с использованием инфиксного оператора.
Есть ли проблема с кодом или есть решение для синтаксического анализа AND
/ OR
как инфиксных операторов (используя тот же OperatorPrecedenceParser
)?Я бы предпочел не идти по этому пути, поэтому я надеюсь, что где-то допустил простую ошибку.
Полный код находится в гисте.