Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyparsing: named results?

I am writing a parser to parse mathematical expressions, which contain variables among other things. I want a list of all the captured variables. But I am only getting the last captured variable. Below is a minimal example to show the problem.

    >>> from pyparsing import *
    >>> var = Word(alphas)
    >>> expr = Forward()
    >>> expr << var('var') + ZeroOrMore(Literal('+') + expr)
    >>> foo = expr.parseString("x + y + z")
    >>> foo
    (['x', '+', 'y', '+', 'z'], {'var': [('x', 0), ('y', 2), ('z', 4)]})
    >>> foo['var']
    'z'

I was expecting ['x', 'y', 'z']. I am using pyparsing version 2.1.

like image 703
Tima Avatar asked Jul 28 '15 22:07

Tima


1 Answers

By default, named results only capture the last item. If you use the explicit setResultsName method call, you can get all the items by adding the optional listAllMatches=True argument. Since you are using the shortcut form var('var'), you can get the listAllMatches behavior if you end the results name with an '*':

expr << var('var*') + ZeroOrMore(Literal('+') + expr)

I prefer to use the dump() method to list out the body and names from parsed results:

>>> foo = expr.parseString("x + y + z")
>>> foo.var
(['x', 'y', 'z'], {})
>>> print foo.dump()
['x', '+', 'y', '+', 'z']
- var: ['x', 'y', 'z']

By the way, because you have defined your grammar in this way, your operations will be evaluated right-to-left. This will be okay if you only evaluate addition, but doing "3 - 5 + 2" right-to-left will give you -4, when you should get 0. Look into using infixNotation (formerly named operatorPrecedence) to define and evaluate arithmetic and boolean expressions. There are also several examples available on the pyparsing wiki at pyparsing.wikispaces.com.

like image 136
PaulMcG Avatar answered Sep 28 '22 23:09

PaulMcG