1

優れた pyparsing モジュールについて学んだばかりで、それを使用してクエリ パーサーを作成したいと考えています。

基本的に、次の種類の式を解析できるようにしたいと考えています。

'b_Coherent == "1_2" or (symbol == 2 and nucleon != 3)'

ここで、b_coherent、symbol、nucleon はデータベースのキーワードです。

私は pyparsing (searchparser.py) に同梱されている例の 1 つを注意深く読んで、私の目標にかなり近づいたと思います (願っています!) が、まだ何か問題があります。

これが私のコードです:

from pyparsing import *

logical_operator    = oneOf(['and','&','or','|'], caseless=True) 
not_operator        = oneOf(['not','^'], caseless=True) 
db_keyword          = oneOf(['nucleon','b_coherent','symbol','mass'], caseless=True)
arithmetic_operator = oneOf(['==','!=','>','>=','<', '<='])

value = Word(alphanums+'_')
quote = Combine('"' + value + '"') | value

selection = db_keyword + arithmetic_operator + (value|quote)
selection = selection + ZeroOrMore(logical_operator+selection)

parenthesis = Forward()
parenthesis << ((selection + parenthesis) | selection)
parenthesis = Combine('(' + parenthesis + ')') | selection

grammar = parenthesis + lineEnd

res = grammar.parseString('b_Coherent == "1_2" or (symbol == 2 and nucleon != 3)')

Forward オブジェクトを完全に理解するには問題があります。多分それが私のパーサーが正しく動作しない理由の 1 つです。私の文法のどこが間違っているか分かりますか?

助けてくれてどうもありがとう

エリック

4

2 に答える 2

1

Forward を使用して、括弧などでネストする独自の式を手作りできますが、pyparsing を使用すると、operatorPrecedenceこのプロセス全体が簡素化されます。コメント付きで、以下の元のコードの更新された形式を参照してください。

from pyparsing import *

# break these up so we can represent higher precedence for 'and' over 'or'
#~ logical_operator    = oneOf(['and','&','or','|'], caseless=True) 
not_operator        = oneOf(['not','^'], caseless=True) 
and_operator        = oneOf(['and','&'], caseless=True) 
or_operator         = oneOf(['or' ,'|'], caseless=True) 

# db_keyword is okay, but you might just want to use a general 'identifier' expression,
# you won't have to keep updating as you add other terms to your query language
db_keyword          = oneOf(['nucleon','b_coherent','symbol','mass'], caseless=True)
ident = Word(alphas+'_', alphanums+'_')

# these aren't really arithmetic operators, they are comparison operators
#~ arithmetic_operator = oneOf(['==','!=','>','>=','<', '<='])
comparison_operator = oneOf(['==','!=','>','>=','<', '<='])

# instead of generic 'value', define specific value types 
#~ value = Word(alphanums+'_')
integer = Regex(r'[+-]?\d+').setParseAction(lambda t:int(t[0]))
float_ = Regex(r'[+-]?\d+\.\d*').setParseAction(lambda t:float(t[0]))

# use pyparsing's QuotedString class for this, it gives you quote escaping, and
# automatically strips quotes from the parsed text
#~ quote = Combine('"' + value + '"') | value
quote = QuotedString('"')

# when you are doing boolean expressions, it's always handy to add TRUE and FALSE literals
literal_true = Keyword('true', caseless=True)
literal_false = Keyword('false', caseless=True)
boolean_literal = literal_true | literal_false

# in future, you can expand comparison_operand to be its own operatorPrecedence 
# term, so that you can do things like "nucleon != 1+2" - but this is fine for now
comparison_operand = quote | db_keyword | ident | float_ | integer
comparison_expr = Group(comparison_operand + comparison_operator + comparison_operand)

# all this business is taken of for you by operatorPrecedence
#~ selection = db_keyword + arithmetic_operator + (value|quote)
#~ selection = selection + ZeroOrMore(logical_operator+selection)
#~ parenthesis = Forward()
#~ parenthesis << ((selection + parenthesis) | selection)
#~ parenthesis = Combine('(' + parenthesis + ')') | selection
#~ grammar = parenthesis + lineEnd

boolean_expr = operatorPrecedence(comparison_expr | boolean_literal, 
    [
    (not_operator, 1, opAssoc.RIGHT),
    (and_operator, 2, opAssoc.LEFT),
    (or_operator,  2, opAssoc.LEFT),
    ])
grammar = boolean_expr

res = grammar.parseString('b_Coherent == "1_2" or (symbol == 2 and nucleon != 3)', parseAll=True)

print res.asList()

版画

[[['b_coherent', '==', '1_2'], 'or', [['symbol', '==', 2], 'and', ['nucleon', '!=', 3]]]]

ここから、実際に評価できるものを作成するための次のステップをどのように行うかを検討することをお勧めします.pyparsing wikiのsimpleBool.pyの例をチェックして、.operatorPrecedence

あなたが pyparse を楽しんでいると聞いてうれしいです、ようこそ!

于 2012-11-01T09:57:20.730 に答える
0

後で定義される式の前方宣言 - 代数中置記法などの再帰文法に使用されます。式がわかっている場合は、'<<' 演算子を使用して Forward 変数に割り当てられます。

于 2012-10-31T16:21:40.940 に答える