This is problem?
Must be:
#keyword to perform action on ALL items all_ = pp.CaselessLiteral("all")
EDIT - if you are interested ...
Your regular expressions are so similar, I thought I would see how it would look in order to combine them into one. Here is a snippet to parse your three-point notations using a single regular expression, and then using parsing to figure out what type you got:
import pyparsing as pp dotted_notation = pp.Regex(r'[a-zA-Z](\.\d{1,2}(\.\d{1,2})?)?') def name_notation_type(tokens): name = { 0 : "area", 1 : "category", 2 : "criteria"}[tokens[0].count('.')]
Print
A ['A'] - area: A A is a area A.1 ['A.1'] - category: A.1 A.1 is a category A.2.2 ['A.2.2'] - criteria: A.2.2 A.2.2 is a criteria ['A', 'A.1', 'A.2.2'] - area: A - category: A.1 - criteria: A.2.2
EDIT2 - I see the original problem ...
What you are mistaken is pipeting an implicit missing space. Pyparsing will skip spaces between specific tokens, but the opposite is not true - pyparsing does not require spaces between individual parser expressions. Thus, in your version of all_-less, "ALL" looks like 3 areas: "A", "L" and "L". This applies not only to Regex, but also to any pyparsing class. See if the PyEping WordEnd class can be useful to provide this.
EDIT3 - Then maybe something like this ...
toggle_item = (toggle + pp.OneOrMore(item)).setParseAction(toggle_item_action) toggle_all = (toggle + all_).setParseAction(toggle_all_action) toggle_directive = toggle_all | toggle_item
As your commands are formatted, you must first make the analyzer see if ALL switches to ALL before looking for individual areas, etc. If you need to support something that can read "ENABLE A.1 ALL" then use a negative result for item : item = ~all_ + (area ^ etc...) . (Note also that I replaced item + pp.ZeroOrMore(item) with just pp.OneOrMore(item) .)