I'm parsing strings with dotted.strings
and infix math operators. The parsing itself seems to work fine, but the name returned by getName
is not what I expect.
from pyparsing import (Word, alphas, opAssoc, infixNotation,
Suppress, Group, delimitedList, oneOf)
LPAR, RPAR = map(Suppress, "()")
chars = Word(alphas + "_")
colstr = Group(delimitedList(chars, delim=".")).setResultsName("colstr*")
infix_expr = infixNotation(colstr, [
("-", 1, opAssoc.RIGHT),
(oneOf("* /"), 2, opAssoc.LEFT),
(oneOf("+ -"), 2, opAssoc.LEFT),
])("infix")
Now testing it out...
>>> infix_ex = infix_expr.parseString('a.b + x.y')
>>> print(infix_ex.dump())
[[['a', 'b'], '+', ['x', 'y']]]
- infix: [['a', 'b'], '+', ['x', 'y']]
- colstr: [['a', 'b'], ['x', 'y']]
[0]:
['a', 'b']
[1]:
['x', 'y']
This is what I expect, but getName
seems to return the name from the wrong level of the parsing tree.
>>> infix_ex.getName()
'infix'
>>> infix_ex[0].getName()
'colstr'
>>> infix_ex[0].asList()
[['a', 'b'], '+', ['x', 'y']]
As you can see, getName
returns 'infix' for the root level and 'colstr' for the 'infix' level of the tree.
This is pretty much unavoidable, since getName()
is a method that is defined on ParseResults
, not on the matched token (which could be a string, and thereby not supporting getName()
).
Here is the example from the ParseResults.getName
docstring:
integer = Word(nums)
ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
house_number_expr = Suppress('#') + Word(nums, alphanums)
user_data = (Group(house_number_expr)("house_number")
| Group(ssn_expr)("ssn")
| Group(integer)("age"))
user_info = OneOrMore(user_data)
result = user_info.parseString("22 111-22-3333 #221B")
print(result.asList())
for item in result:
print(item.getName(), ':', item[0])
Which prints:
[['22'], ['111-22-3333'], ['221B']]
age : 22
ssn : 111-22-3333
house_number : 221B
Note that, to use getName()
each of the named bit has to be a Group
, and that the name goes on the container, not on the matched token directly.
You can define results names on elements that are not Group
s, and access them directly without having to get the [0]
th element, but you would not be able to call getName()
on them.
If you are planning to use getName()
to walk the structure returned by parsing using infixNotation
, I encourage you to instead define your own container classes for the operand and for each precedence level in your infix notation grammar. See the simple_bool.py
example code to see how this is done. That way you will have more direct control over the objects passed back to you from pyparsing, rather than trying to work through the parsed infix notation hierarchy (and probably re-trace some parsing steps in the process).