Help improve program for parsing simple rules

Aaron Brady castironpi at gmail.com
Fri Apr 17 14:17:10 EDT 2009


On Apr 17, 7:37 am, prueba... at latinmail.com wrote:
> On Apr 16, 3:59 pm, Aaron Brady <castiro... at gmail.com> wrote:
>
>
>
> > On Apr 16, 10:57 am, prueba... at latinmail.com wrote:
>
> > > Another interesting task for those that are looking for some
> > > interesting problem:
> > > I inherited some rule system that checks for programmers program
> > > outputs that to be ported: given some simple rules and the values it
> > > has to determine if the program is still working correctly and give
> > > the details of what the values are. If you have a better idea of how
> > > to do this kind of parsing please chime in. I am using tokenize but
> > > that might be more complex than it needs to be. This is what I have
> > > come up so far:
>
snip
> > > def main():
> > >     for cur_rule in rules[20:26]:
> > >         tokens=get_tokens(cur_rule)
> > >         normal=replace_comps(tokens,COMP_REPLACERS)
> > >         subst=replace_names(normal,vars_)
> > >         groups=split_seccions(subst,COMP_REPLACERS.values())
> > >         rep=all_seccions(groups)
> > >         rep_out=''.join(x[0]+x[1] for x in rep)
> > >         calc=calc_seccions(rep)
> > >         calc_out=''.join(x[0]+x[1] for x in calc)
> > >         deltas=calc_deltas(calc)
> > >         result=eval(calc_out,{},{})
>
> > snip
>
snip
> > >>> a= '-1000.00 < A < 0.00'
> > >>> eval( a, { 'A': -100 } )
snip
> > >>> a= '-1000.00 LE A LE 0.00'
> > >>> b= a.replace( ' LE ', ' <= ' )
snip
>
> I know about evals implication of safety. Rules are defined by the
> programmers so I don't worry too much about it at this point. They
> should know better than messing up their application server. Unless
> there is some easier way to do it I am willing to take the risk.
> Precedence is standard math, we can always add some extra parenthesis
> to the rules, I don't thing the old system would mind.
>
> I thought about using eval with a locals dictionary, but they want
> output of the intermediate values. I want to avoid the situation where
> the intermediate output does not match what eval is doing.

I take you to need the operands to the individual comparison
operators; that is, each side of each comparison.  There might be a
way using abstract syntax trees.  Or, a basic 're' split can simplify
it.

>>> import re
>>> a= '-1000.00 LE A LE 0.00'
>>> b= re.split( r'\s(LT|GT|LE|GE|=|<|>|<=|>=)\s', a )
>>> b
['-1000.00', 'LE', 'A', 'LE', '0.00']
>>> COMP_REPLACERS={'LT':'<', 'GT':'>', 'LE':'<=', 'GE':'>=', '=':'=='}
>>> c= [ COMP_REPLACERS.get( x, x ) for x in b ]
>>> c
['-1000.00', '<=', 'A', '<=', '0.00']
>>> vars_={'A': 0, 'B': 1.1, 'C': 2.2, 'D': 3.3, 'E': 4.4, 'F': 5.5, 'G':
... 6.6, 'H':7.7, 'I':8.8, 'J':9.9}
>>> d= [ str( vars_.get( x, x ) ) for x in c ]
>>> d
['-1000.00', '<=', '0', '<=', '0.00']
>>> eval( ''.join( d ) )
True

The 'dict.get( x, x )' expression returns the value of the entry for
x, or x itself if it is not present.

No promises.  I didn't think it all the way through.



More information about the Python-list mailing list