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() -- http://mail.python.org/mailman/listinfo/python-list