Pyparsing のクラスはほぼ左から右へと進み、FollowedBy (正の先読み) や NotAny または '~' 演算子 (負の先読み) などの明示的な式を使用して先読みが実装されます。これにより、繰り返される項目に通常一致するターミネータを検出できます。たとえば、OneOrMore(Word(alphas)) + Literal('end')
「start blah blah end」のような文字列では一致が見つかりません。これは、終了の「end」が OneOrMore の繰り返し式に飲み込まれてしまうためです。修正は、繰り返される式に否定先読みを追加することです。OneOrMore(~Literal('end') + Word(alphas)) + Literal('end')
つまり、アルファで構成された別の単語を読み取る前に、まずそれが「end」という単語ではないことを確認してください。
これは、繰り返しが Word などの pyparsing クラス内にある場合に失敗します。Word(alphas)
単語を止める空白がない限り、アルファベット文字を読み続けます。Combine(OneOrMore(~Literal('lab') + Word(alphas, exact=1)))
複雑な結合式を使用して単純なトークンを構成すると、パーサーが遅くなるため、非常に高価なものを使用してこの繰り返しに割り込む必要があります。
pyparsing Regex オブジェクトにラップされた正規表現を使用することで妥協できる場合があります。
>>> labword = Regex(r'(\w+)(lab)(\d+)')
>>> print labword.parseString("abclab1").dump()
['abclab1']
これにより、正しい種類のグループ化と検出が行われますが、グループ自体は公開されません。これを行うには、各グループに名前を追加します。pyparsing はこれらを結果名のように扱い、setResultsName を呼び出した場合と同様に、個々のフィールドにアクセスできるようにします。
>>> labword = Regex(r'(?P<locn>\w+)(?P<env>lab)(?P<identifier>\d+)')
>>> print labword.parseString("abclab1").dump()
['abclab1']
- env: lab
- identifier: 1
- locn: abc
>>> print labword.parseString("abclab1").asDict()
{'identifier': '1', 'locn': 'abc', 'env': 'lab'}
私が考えることができる他の唯一の非正規表現のアプローチは、文字列全体を読み取る式を定義してから、解析アクションで部分を分割することです。