pyparser and recursion problem

Paul McGuire ptmcg at austin.rr.com
Fri Jul 27 09:39:04 EDT 2007


On Jul 26, 10:40 pm, pyscottish... at hotmail.com wrote:
> Hey,
>
> Thanks Neil and Paul!
>
> After reading Neil's advice I started playing around with the
> setParseAction method, and then I found Paul's script
> 'macroExpander.py' (http://pyparsing.wikispaces.com/space/showimage/
> macroExpander.py).
>
<snip>

Great! I'm glad those examples are useful (I keep meaning to get them
a little better organized.)

Just one side note.  macroExpander uses the Forward class in a non-
traditional way.  The Forward class is usually used to define a
recursive grammar, like in this simple list grammar that defines a
comma-separated list, with nested sublists enclosed in parentheses:

listExpr = Forward()
listItem = Word(alphanums) | Group( '(' + listExpr + ')' )
listExpr << delimitedList( listItem )

I need to use listExpr as part of the definition of listItem, but I
need to use listItem to define listExpr.  So I "forward declare"
listExpr by calling it a Forward instance, then I "inject" the grammar
contents using the shift '<<' operator when I have defined listItem.

macroExpander is a little different.  In this case, I'm using a
Forward as a parse-time dynamic grammar element.  A Forward is used as
a placeholder for all previously seen macro names, beginning as an
empty Forward (an empty Forward never matches).  As new macro
definitions are found, the placeholder content gets defined as a
MatchFirst of all macro definitions that have been seen so far - sort
of a self-modifying parser.

This explains why you had to reverse the order of your example string
when you adapted macroExpander to your example.  Your original string
referenced macros that hadn't been encountered yet, so the only way to
handle that was to parse everything, and then recursively post-process
the structure with a parse action on the top-level expression.  (I
tried a version using parse actions on the all-uppercase macro
expression, and a dict of previously-seen references and placeholders
in the cumulative ParseResults, but I couldn't get this working, so I
went with the recursive post-process instead - much simpler and more
straightforward.)

Glad you worked out your question, hope to hear from you further in
your pyparsing exploits.

-- Paul





More information about the Python-list mailing list