5

ドット付き表記を使用して識別されたオブジェクトに対して、次のような単純なアクションを実行する構文パーサーを構築しています。

DISABLE ALL;
ENABLE A.1 B.1.1 C

しかしDISABLE ALL、キーワードALLでは、代わりに3として一致し、Regex(r'[a-zA-Z]') => 'A', 'L', 'L'引数を一致させるために使用します。

正規表現を使用してWordを作成するにはどうすればよいですか?AFAIKWordをA.1.1使用できません

以下の例を参照してください

import pyparsing as pp

def toggle_item_action(s, loc, tokens):
    'enable / disable a sequence of items'
    action = True if tokens[0].lower() == "enable" else False
    for token in tokens[1:]:
        print "it[%s].active = %s" % (token, action)

def toggle_all_items_action(s, loc, tokens):
    'enable / disable ALL items'
    action = True if tokens[0].lower() == "enable" else False
    print "it.enable_all(%s)" % action

expr_separator = pp.Suppress(';')

#match A
area = pp.Regex(r'[a-zA-Z]')
#match A.1
category = pp.Regex(r'[a-zA-Z]\.\d{1,2}')
#match A.1.1
criteria = pp.Regex(r'[a-zA-Z]\.\d{1,2}\.\d{1,2}')
#match any of the above
item = area ^ category ^ criteria
#keyword to perform action on ALL items
all_ = pp.CaselessLiteral("all")

#actions
enable = pp.CaselessKeyword('enable')
disable = pp.CaselessKeyword('disable')
toggle = enable | disable

#toggle item expression
toggle_item = (toggle + item + pp.ZeroOrMore(item)
    ).setParseAction(toggle_item_action)

#toggle ALL items expression
toggle_all_items = (toggle + all_).setParseAction(toggle_all_items_action)

#swapping order to `toggle_all_items ^ toggle_item` works
#but seems to weak to me and error prone for future maintenance
expr = toggle_item ^ toggle_all_items
#expr = toggle_all_items ^ toggle_item

more = expr + pp.ZeroOrMore(expr_separator + expr)

more.parseString("""
    ENABLE A.1 B.1.1;
    DISABLE ALL
    """, parseAll=True)
4

1 に答える 1

4

これは問題ですか?

#match any of the above
item = area ^ category ^ criteria
#keyword to perform action on ALL items
all_ = pp.CaselessLiteral("all")

する必要があります:

#keyword to perform action on ALL items
all_ = pp.CaselessLiteral("all")
#match any of the above
item = area ^ category ^ criteria ^ all_

編集-興味があれば...

あなたの正規表現はとても似ているので、それらを1つにまとめるとどうなるか見てみようと思いました。これは、単一の正規表現を使用して3つの点線表記を解析し、解析アクションを使用して取得したタイプを把握するためのスニペットです。

import pyparsing as pp

dotted_notation = pp.Regex(r'[a-zA-Z](\.\d{1,2}(\.\d{1,2})?)?') 
def name_notation_type(tokens):
    name = {
        0 : "area",
        1 : "category",
        2 : "criteria"}[tokens[0].count('.')]
    # assign results name to results - 
    tokens[name] = tokens[0] 
dotted_notation.setParseAction(name_notation_type)

# test each individually
tests = "A A.1 A.2.2".split()
for t in tests:
    print t
    val = dotted_notation.parseString(t)
    print val.dump()
    print val[0], 'is a', val.getName()
    print

# test all at once
tests = "A A.1 A.2.2"
val = pp.OneOrMore(dotted_notation).parseString(tests)
print val.dump()

プリント:

A
['A']
- area: A
A is a area

A.1
['A.1']
- category: A.1
A.1 is a category

A.2.2
['A.2.2']
- criteria: A.2.2
A.2.2 is a criteria

['A', 'A.1', 'A.2.2']
- area: A
- category: A.1
- criteria: A.2.2

EDIT2-元の問題が表示されます...

あなたを混乱させているのは、pyparsingの暗黙の空白スキップです。構文解析は、定義されたトークン間の空白をスキップしますが、その逆は当てはまりません。構文解析では、個別のパーサー式の間に空白は必要ありません。したがって、all_-lessバージョンでは、「ALL」は「A」、「L」、「L」の3つの領域のように見えます。これは、正規表現だけでなく、ほぼすべてのpyparsingクラスに当てはまります。pyparsingWordEndクラスがこれを実施するのに役立つかどうかを確認してください。

EDIT3-それなら多分このようなもの...

toggle_item = (toggle + pp.OneOrMore(item)).setParseAction(toggle_item_action)
toggle_all = (toggle + all_).setParseAction(toggle_all_action)

toggle_directive = toggle_all | toggle_item

コマンドのフォーマット方法では、個々の領域などを探す前に、まずパーサーにALLが切り替えられているかどうかを確認させる必要があります。「ENABLEA.1 ALL」と表示される可能性のあるものをサポートする必要がある場合は、ネガティブルックアヘッドを使用します。の場合itemitem = ~all_ + (area ^ etc...)item + pp.ZeroOrMore(item)(私がちょうどに置き換えたことにも注意してくださいpp.OneOrMore(item)。)

于 2011-06-09T12:34:45.437 に答える