[TransWarp] fmtparse - named rules

Phillip J. Eby pje at telecommunity.com
Mon Jun 16 11:37:56 EDT 2003

At 01:15 PM 6/16/03 +0400, Oleg Broytmann wrote:
>    How should I use Named rules?
>from peak.util.fmtparse import *
>cmp_func = Named("cmp_func",
>     Alternatives("eq", "neq", "lt", "le", "gt", "ge", "like"))
>test1 = "eq"
>print parse(test1, cmp_func)
>    Prints {}. Oops, where is my name?

fmtparse rules are sort of like generators, except they call a passed-in 
visitor function rather than yielding.  'Named' "yields" a (name,value) 
tuple for each value yielded by its contained rule.  Alternatives never 
yields anything, so Named(Alternatives) yields nothing either.  You need an 
ExtractString around the Alternatives.

>    The following is better:
>between_expr = Sequence("between", '(', Named("name"), ',', 
>Named("value1"), ',', Named("value2"), ')')

This is because the default subrule for Named is an 
ExtractString().  ExtractString has a default subrule of 
MatchString().  The default MatchString behavior is to match until it hits 
a terminator.  In your sequence above, each MatchString will be told that 
',' (and maybe ')') are terminators.  The default ExtractStrings then take 
the value matched by the MatchString, and yield it to the Named, which then 
turns it into a (name,value) tuple and yields it to the Sequence.  The 
sequence yields a sequence to the parse operation, which turns it into a 

>test2 = "between(month,1,12)"
>print parse(test2, between_expr)
>    It prints {'name': 'month', 'value1': '1', 'value2': '12'}. Ok. But
>between_expr = Named("between", Sequence("between", '(', Named("name"), 
>',', Named("value1"), ',', Named("value2"), ')'))
>test3 = "between(month,1,12)"
>print parse(test3, between_expr)
>    Prints {'between': ('value2', '12')}. Ouch, where is name and value1? It
>seems I am doing it wrong way, but what is the right way?

I'm not clear on what you're trying to accomplish..

>    Returning to the very first exampl... I can use ExtractString:
>cmp_func = Named("cmp_func",
>     ExtractString(Alternatives("eq", "neq", "lt", "le", "gt", "ge", "like")))

ExtractString yields the string that is matched by its subrule, so 
'cmp_func' will yield a pair like ('cmp_func', 'eq') or ('cmp_func','like').

>test4 = "eq"
>print parse(test4, cmp_func) # => {} Oops, where is my name?
>    {'cmp_func': 'eq'} - ok, exactly what I wanted... but this:
>between_expr = Named("between", ExtractString(Sequence("between", '(', 
>Named("name"), ',', Named("value1"), ',', Named("value2"), ')')))
>test5 = "between(month,1,12)"
>print parse(test5, between_expr)
>    {'between': 'between(month,1,12)'}. ExtractString extracted too much...

What did you want it to extract?  You told it to extract 
Sequence("between", '(', ... ')'), so that's what you got.  I'm having 
trouble understanding what you *want* to do here.

More information about the PEAK mailing list