Pyparsing setParseAction doesn't convert string to int

Viewed 244

I'm trying to parse some ancient industrial equipment data format using pyparsing and run into a behavior I don't understand.

The input string format is: R<x0>,<y0>,<w>,<h>[,*<level>];, where x0, y0, w, h are real numbers, level is integer in range of 1-8. The star marks the presence of the level token and the whole level construct can be omitted, in which case it is defaulted to 1.

I want the parser to output a list of numbers like this [x0, y0, w, h, level] with the numbers being converted to appropriate data types.

The parser I wrote does almost exactly what I want with a single nuance:

from pyparsing import Word, nums, ZeroOrMore, Suppress, Literal, Optional, Combine, StringEnd, srange

rtext = 'R.0,.2,5.7,.2,*1;'
# rtext = 'R0.0,0.2,5.7,0.2;'

real = Combine(ZeroOrMore(Word(nums)) + Literal('.') + Word(nums)).setParseAction(lambda s, l, t: float(t[0]))
level = Word(srange('[1-8]')).setParseAction(lambda s, l, t: int(t[0]))
rect_mark = Suppress('R')
comma = Suppress(',')
star = Suppress('*')
semicolon = Suppress(';')
level_str = Combine(star + level)

rect = rect_mark + real + comma + real + comma + real + comma + real + \
       Optional(comma + level_str, default=1) + semicolon + StringEnd()

res = rect.parseString(rtext)
print(res)   # => [0.0, 0.2, 5.7, 0.2, '1']

Why does level token not get converted to int? Sure, I can convert it in a later processing step, but I'd rather have the input data be consistent.

0 Answers
Related