以下のような複雑な論理式を解析しようとしています。バイナリツリー形式でpyparsingで複雑な論理式を構文解析する
x > 7 AND x < 8 OR x = 4
を取得し、解析された文字列をバイナリツリーとして取得します。上記の発現のために期待される解析された式は、論理演算子は「AND」演算子よりも優先順位が高い
[['x', '>', 7], 'AND', [['x', '<', 8], 'OR', ['x', '=', 4]]]
のように見える「OR」すべきです。括弧はデフォルトの優先順位を上書きすることができます。より一般的には、解析された式は次のようになります。
<left_expr> <logical_operator> <right_expr>
別の例は、
input_string = x > 7 AND x < 8 AND x = 4
parsed_expr = [[['x', '>', 7], 'AND', ['x', ',', 8]], 'AND', ['x', '=', 4]]
これまでのところ、私は悲しげに、バイナリツリー形式で解析された表現を生成することはできません。この簡単な解決策を考え出しただろう。 operatorPrecedenceは、前の例と同じ論理演算子が連続しているところで私を助けてくれているようではありません。
import pyparsing as pp
complex_expr = pp.Forward()
operator = pp.Regex(">=|<=|!=|>|<|=").setName("operator")
logical = (pp.Keyword("AND") | pp.Keyword("OR")).setName("logical")
vars = pp.Word(pp.alphas, pp.alphanums + "_") | pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?")
condition = (vars + operator + vars)
clause = pp.Group(condition^(pp.Suppress("(") + complex_expr + pp.Suppress(")")))
expr = pp.operatorPrecedence(clause,[
("OR", 2, pp.opAssoc.LEFT,),
("AND", 2, pp.opAssoc.LEFT,),])
complex_expr << expr
print complex_expr.parseString("x > 7 AND x < 8 AND x = 4")
ご意見やご指摘はありがとうございます。 (括弧なし)を発現させるため
BNF
<expr> -> <expr> | <expr> <logical> <expr>
<expr> -> <opnd> <relational> <opnd>
<opnd> -> <variable> | <numeric>
<relational> -> <'>'> | <'='> | <'>='> | <'<='> | <'!='>
あなたのコード従うことが少し難しいです、あなたはBNFで文法を投稿できますか? – georg
はBNFを追加したばかりです...曖昧でないかどうかわかりません。 – consumer