Menu

Hierarchy Tree Within ParseResults?

Alan
2009-11-25
2013-05-14
  • Alan

    Alan - 2009-11-25

    Here's a simple outline of what I'm working with:

    a = Literal("apple").setResultsName("apple") <br>
    b = Literal("banana").setResultsName("banana") <br>
    c = Literal("carrot").setResultsName("carrot") <br>
    d = Literal("dulse").setResultsName("dulse") <br>
    fruit = OneOrMore(a | b).setResultsName("fruit") <br>
    veg = OneOrMore(c | d).setResultsName("veg") <br>
    food = OneOrMore(fruit + veg | a).setResultsName("food") <br>

    strFood = "apple carrot" <br>
    strApple = "apple" <br>

    Because of the way that 'food' is defined, apple can be matched on its own or as part of the 'fruit + veg' combination. I'm trying to find a way to distinguish between the two by looking at the ParseResults, but the problem I'm running into is that ParseResults contains the matches at every level of the tree. For example: <br>

    print food.parseString(strFood).dump()  produces: <br>
    -  <br>

    - apple: apple <br>
    - carrot: carrot <br>
    - food:  <br>
      - apple: apple <br>
      - carrot: carrot <br>
      - fruit:  <br>
           - apple: apple <br>
      - veg:  <br>
           - carrot: carrot <br>
    - fruit:  <br>
       - apple: apple <br>
    - veg:  <br>
       - carrot: carrot <br>

    <br>
    My challenge here is that the source string could contain 'apple' at the root level or  within the Food>Fruit level, or both, and each one means something different.  What I'd like to do is test to see whether or not 'apple' exists at the root level and know that it wasn't matched as part of the 'fruit+veg' combination, but the way it is now, I can't do that. Is there some function I can use on the ParseResults, or some other way of structuring my grammar so that I get a proper hierarchy (that is, each match is placed in a single unique position within the tree)? I know that I could use setResultName to distinguish them, but I have many levels of nesting and lots of optional tokens; I'd rather not have to come up with an exhaustive set of unique names, if possible. <br>

    Thanks in advance, <br>
    Alan

     
  • Paul McGuire

    Paul McGuire - 2009-12-23

    Leon -

    By default, pyparsing elevates all results names to a flat namespace, since there is no telling how many intermediate levels there might be included artificially due to the assembly of the parser from its different parts.

    But you can introduce a sort of namespace to the results names, by using the Group class:

        fruit = Group(OneOrMore(a | b)).setResultsName("fruit")
        veg = Group(OneOrMore(c | d)).setResultsName("veg")
        food = OneOrMore(Group(fruit + veg) | a).setResultsName("food")

    See if this gives you more control on how results names get merged into higher levels of your parser.

    (You can also abbreviate `expr.setResultsName("name")` as `expr("name")` - I feel that it cleans up the code quite a bit.

    • Paul
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.