Nested list sheets in pyparsing without causing infinite recursion?

Pyparsing has the following toy grammar:

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()

However, running this program will be infinitely recursive, which I did not want. Rather, I wanted my grammar to handle nested phrases so that the program described above would resolve something equivalent below:

>>> 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>

I tried to change the definitions for And_Phraseand Or_Phraseso that they corresponded only to lists with two or more elements, but could not understand how to do this.

I also tried using pyparsing.operatorPrecedence, but I don’t think I did it right:

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()

... because he did not give a list at all:

>>> test("Hello world and bob")
<Expression>
  <Word>Hello</Word>
  <Word>world</Word>
  <Word>and</Word>
  <Word>bob</Word>
</Expression>

How can I change the definitions of rules to handle nested lists?

+5
source
1

, operatorPrecedence - . . -, "" "" . , :

and_tok = pyp.Keyword("and")
or_tok = pyp.Keyword("or")
Word = ~(and_tok | or_tok) + pyp.Word(pyp.alphas)("Word")

"" "" "".

, operatorPrecedence. "" - , . operatorPrecedence . Phrase , , amok. operatorPrecedence Word ( pyp.OneOrMore(Word), ).

, operatorPrecedence , ^ Word. , Phrase Expression operatorPrecedence.

, :

Expression = (
    pyp.operatorPrecedence(pyp.OneOrMore(Word), [
        (and_tok, 2, pyp.opAssoc.LEFT),
        (or_tok, 2, pyp.opAssoc.LEFT)
    ])
)

:

>>> test("Hello and Bob")

<ITEM>
  <ITEM>
    <Word>Hello</Word>
    <AND>and</AND>
    <Word>Bob</Word>
  </ITEM>
</ITEM>

>>> test("TestA and TestB and TestC or TestD")

<ITEM>
  <ITEM>
    <ITEM>
      <Word>TestA</Word>
      <AND>and</AND>
      <Word>TestB</Word>
      <AND>and</AND>
      <Word>TestC</Word>
    </ITEM>
    <OR>or</OR>
    <Word>TestD</Word>
  </ITEM>
</ITEM>

, , , , parseAction (operatorrPrecedence ).

( , test("TestA and TestB and TestC or TestD") . , "" "" , (TestA and TestB and TestC) or TestD, , (TestC or TestD) , "" .)

+3

All Articles