我在 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 的定义And_Phrase
,Or_Phrase
以便它们只匹配具有两个或多个元素的列表,但不知道如何做到这一点。
我也尝试过使用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>
如何修改我的规则定义以便它们处理嵌套列表?