を括弧I持っているため、次のfsyacc文法(のわずかに変更された形式)SQL検索条件:解析は表現
scalar_expr:
| ID { Identifier($1) }
| constant { Constant($1) }
| unary_op scalar_expr { Unary($1, $2) }
| scalar_expr binary_op scalar_expr { Binary($2, $1, $3) }
| LPAREN scalar_expr RPAREN { $2 }
search_condition:
| search_condition OR search_condition { Or($1, $3) }
| search_condition AND search_condition { And($1, $3) }
| scalar_expr comparison scalar_expr { Comparison($2, $1, $3) }
| LPAREN search_condition RPAREN { $2 }
私は(previous questionからいくつかの助けを借りて)FParsecでそれを再実装しました。ここでは、関連するビットは以下のとおりです。
let binOpp = OperatorPrecedenceParser()
let scalarExpr = binOpp.ExpressionParser
binOpp.TermParser <-
[ constant
id
between lparen rparen scalarExpr ]
|> choice
// binary/unary ops added here
let comparison =
let compareExpr = pipe3 scalarExpr compareOp scalarExpr (fun l op r -> Comparison(op, l, r))
between lparen rparen compareExpr <|> compareExpr
let andTerm = stringCIReturn "and" (fun l r -> And(l, r)) .>> ws
let orTerm = stringCIReturn "or" (fun l r -> Or(l, r)) .>> ws
let searchCondition, searchConditionRef = createParserForwardedToRef()
searchConditionRef:=
chainl1 comparison (andTerm <|> orTerm)
<|> between lparen rparen searchCondition
これは1 = 1 or 2 = 2
を解析しますが、括弧内の定数または全体の検索条件をラッピングすることは、(奇妙な、括弧の作品の比較を包む)失敗します。ここで失敗する例を示します、
Error in Ln: 1 Col: 8
(1 = 1 or 2 = 2)
^
Expecting: infix operator or ')'
: 8
スカラー比較し、条件を検索し、すべてが同様に( - >定数 - オープン括弧>中置演算子)を開始することができますが、基本的に最終的に遭遇したオペレータの種類によって区別されています。たとえば、or
とヒットした場合、オープニングの括弧は条件全体に属し、左側の比較ではありません。これはバックトラッキングによって適切に処理されますか?その場合、複雑な式の解析中にどのように入力を消費しないようにすれば、どのように失敗するのですか?
スカラー、比較、および検索条件のオプションのかっこの処理は、fsyacc文法の左回帰によって処理されます。 FParsecでこれを考慮する必要があると私は理解しています。しかし、上記のエラーから、私は広範なバックトラックを避ける方法を想像することはできません。
私は質問を投稿して以来、私はそれを編集できませんでしたので、 "テスト"として "fparsec"タグを削除しようとしました。残念ながら、私はそれを元に戻すことができません(または他の編集をする)。私は昨日司会者の注意を喚起した。まだ待っている。 – Daniel
第二に、思慮深い返事をいただきありがとうございます。私は月曜日までこれを試すことができません。私は先の質問で投稿した優先パーザを使用して、実際の解決策を持っています。あなたのコードは 'AND'と' OR'を優先して処理しますか? – Daniel
AND演算子とOR演算子も元の質問と同じ優先順位を持ちます。あなたは、ORパーサーがANDパーサーを呼び出すようにすることで、さまざまな優先順位を扱うことができます。たとえば、 'expr'はhttp://stackoverflow.com/questions/4559399/#answer-4567275で' term 'を呼び出します。おそらくOPPを使う方が簡単でしょう。いずれの場合でも、文法の異なるレベルでかっこを解析できるようにバックトラッキングを許可する必要があります。 –