Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyparsing isn't nesting list ... why?

For some reason, pyparsing isn't nesting the list for my string:

rank = oneOf("2 3 4 5 6 7 8 9 T J Q K A")
suit = oneOf("h c d s")
card = rank + Optional(suit)

suit_filter = oneOf("z o")
hand = card + card + Optional(suit_filter)

greater = Literal("+")
through = Literal("-")
series = hand + Optional(greater | through + hand)

series_split = Literal(",")
hand_range = series + ZeroOrMore(series_split + series)

hand_range.parseString('22+,AKo-ATo,KQz')

>> ['2', '2', '+', ',', 'A', 'K', 'o', '-', 'A', 'T', 'o', ',', 'K', 'Q', 'z']

I'm not sure why the pyparsing isn't creating lists around 22+, AKo-ATo, and KQz (or any layers deeper than that). What am I missing?

like image 501
MikeRand Avatar asked Feb 25 '23 19:02

MikeRand


1 Answers

Pyparsing isn't grouping these tokens because you didn't tell it to. Pyparsing's default behavior is to simply string together all matched tokens into a single list. To get grouping of your tokens, wrap the expressions in your parser that are to be grouped in a pyparsing Group expression. In your case, change series from:

series = hand + Optional(greater | through + hand)

to

series = Group(hand + Optional(greater | through + hand))

Also, I recommend that you not implement your own comma-delimited list as you have done in series, but instead use the pyparsing helper, delimitedList:

hand_range = delimitedList(series)

delimitedList assumes comma delimiters, but any character (or even complete pyparsing expression) can be given as the delim argument. The delimiters themselves are suppressed from the results, as delimitedList assumes that the delimiters are there simply as separators between the important bits, the list elements.

After making these two changes, the parse results now start to look more like what you are asking for:

[['2', '2', '+'], ['A', 'K', 'o', '-', 'A', 'T', 'o'], ['K', 'Q', 'z']]

I'm guessing that you might also want to put Group around the hand definition, to structure those results as well.

If this is an expression that will be evaluated in some way (like a poker hand), then please look at these examples on the pyparsing wiki, which use classes as parse actions to construct objects that can be evaluated for rank or boolean value or whatever.

http://pyparsing.wikispaces.com/file/view/invRegex.py

http://pyparsing.wikispaces.com/file/view/simpleBool.py

http://pyparsing.wikispaces.com/file/view/eval_arith.py

If you construct objects for these expressions, then you won't need to use Group.

like image 98
PaulMcG Avatar answered Mar 07 '23 10:03

PaulMcG