Help improve program for parsing simple rules

pruebauno at latinmail.com pruebauno at latinmail.com
Thu Apr 16 11:57:53 EDT 2009


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:

rules=[
         '( A - B ) = 0',
         '(A + B + C + D + E + F + G + H + I) = J',
         '(A + B + C + D + E + F + G + H) = I',
         '(A + B + C + D + E + F) = G',
         '(A + B + C + D + E) = (F + G + H + I + J)',
         '(A + B + C + D + E) = (F + G + H + I)',
         '(A + B + C + D + E) = F',
         '(A + B + C + D) = (E + F + G + H)',
         '(A + B + C) = (D + E + F)',
         '(A + B) = (C + D + E + F)',
         '(A + B) = (C + D)',
         '(A + B) = (C - D + E - F - G + H + I + J)',
         '(A + B) = C',
         '(A + B) = 0',
         '(A+B+C+D+E) = (F+G+H+I+J)',
         '(A+B+C+D) = (E+F+G+H)',
         '(A+B+C+D)=(E+F+G+H)',
         '(A+B+C)=(D+E+F)',
         '(A+B)=(C+D)',
         '(A+B)=C',
         '(A-B)=C',
         '(A/(B+C))',
         '(G + H) = I',
         '-0.99 LE ((A+B+C)-(D+E+F+G)) LE 0.99',
         '-0.99 LE (A-(B+C)) LE 0.99',
         '-1000.00 LE A LE 0.00',
         '-5000.00 LE A LE 0.00',
         'A < B',
         'A < 7000',
         'A = -(B)',
         'A = C',
         'A = 0',
         'A GT 0',
         'A GT 0.00',
         'A GT 7.00',
         'A LE B',
         'A LT -1000.00',
         'A LT -5000',
         'A LT 0',
         'A=(B+C+D)',
         'A=B',
         'I = (G + H)',
         '0.00 LE A LE 4.00',
         '4.00 LT A LE 7.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}

import tokenize as TOK
import StringIO as SIO

COMP_REPLACERS={'LT':'<', 'GT':'>', 'LE':'<=', 'GE':'>=', '=':'==',
'=>':'=>', '=<':'=<'}

def get_tokens(string):
    return [x[:2] for x in TOK.generate_tokens(SIO.StringIO
(string).readline)][:-1]

def replace_comps(toks,repl):
    return [(TOK.OP, repl[x[1]]) if x[1] in repl else x for x in toks]

def replace_names(norm,vars_):
    return [(TOK.NUMBER,str(vars_.get(x[1],x[1]))) if x[0]==TOK.NAME
else x for x in norm]

def split_seccions(subs,comp_split):
    l=[]
    g=[]
    for type_,value in subs:
        if value in comp_split:
            g.append((l,value))
            l=[]
        else:
            l.append((type_,value))
    g.append((l,''))
    return g

def all_seccions(grps):
    return [(TOK.untokenize(lst),comper) for lst,comper in grps]

def calc_seccions(rep):
    return [(str(eval(comp,{},{})),comper) for comp,comper in rep]

def calc_deltas(calc):
    return [eval(calc[i][0]+'-'+calc[i+1][0],{},{}) for i in range(len
(calc)-1)]

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,{},{})
        print
        print 'Values:',', '.join(str(key)+': '+str(val) for key,val
in sorted(vars_.iteritems()))
        print 'Read rule:   ',cur_rule
        print 'Used rule:   ',TOK.untokenize(normal)
        print 'Substitution:',rep_out
        print 'Calculation: ',calc_out
        print 'Result:      ','Successful' if result else 'Failed'
        if  not result and '==' in calc_out:
            print 'Difference:  ',', '.join(map(str,deltas))
        print '='*40


if __name__=='__main__': main()



More information about the Python-list mailing list