Pyparsing には次のおもちゃの文法があります。
import pyparsing as pp
or_tok = "or"
and_tok = "and"
lparen = pp.Suppress("(")
rparen = pp.Suppress(")")
Word = pp.Word(pp.alphas)("Word")
Phrase = pp.Forward()
And_Phrase = pp.Group(pp.delimitedList(Phrase, and_tok))("And_Phrase")
Or_Phrase = pp.Group(pp.delimitedList(Phrase, or_tok))("Or_Phrase")
Phrase << (pp.Optional(lparen) + (And_Phrase ^ Or_Phrase) + pp.Optional(rparen)) ^ Word
Expression = pp.OneOrMore(Word ^ Phrase)("Expression")
def test(text):
output = Expression.parseString(text)
print output.asXML()
ただし、このプログラムを実行すると、無限に再帰が発生します。これは、私が望んでいたことではありません。むしろ、上記のプログラムが以下と同等のものに解決されるように、文法でネストされたフレーズを処理できるようにしたかったのです。
>>> test("TestA and TestB and TestC or TestD")
<Expression>
<And_Phrase>
<Word>TestA</Word>
<Word>TestB</Word>
<Or_Phrase>
<Word>TestC</Word>
<Word>TestD</Word>
</Or_Phrase>
</And_Phrase>
</Expression>
And_Phrase
andの定義を変更して、Or_Phrase
2 つ以上の要素を持つリストのみに一致するようにしようとしましたが、その方法がわかりませんでした。
も使用してみpyparsing.operatorPrecedence
ましたが、正しくやったとは思いません:
import pyparsing as pp
or_tok = "or"
and_tok = "and"
lparen = pp.Suppress("(")
rparen = pp.Suppress(")")
Word = pp.Word(pp.alphas)("Word")
Phrase = pp.Forward()
Phrase << Word ^ \
pp.operatorPrecedence(Phrase, [
(and_tok, 2, pp.opAssoc.LEFT),
(or_tok, 2, pp.opAssoc.LEFT)
])
Expression = pp.OneOrMore(Word ^ Phrase)("Expression")
def test(text):
output = Expression.parseString(text)
print output.asXML()
...リストがまったく生成されなかったため:
>>> test("Hello world and bob")
<Expression>
<Word>Hello</Word>
<Word>world</Word>
<Word>and</Word>
<Word>bob</Word>
</Expression>
入れ子になったリストを処理できるようにルール定義を変更するにはどうすればよいですか?