#!/usr/bin/env python from expression_parser import * ############################################################################### # Tests: def test_parser( s, e ): """ Parse string 's' and compare the result to string 'e'. If they differ, print the parsed structure. Parameters: @param s the string to be tested. @param e the correct result from the parsed string. @return True if parsed s matches e, False otherwise. """ status = [ "[FAILED]", "[PASSED]" ] max_status = max( len( status[ 0 ] ), len( status[ 1 ] ) ) msg = " Test expression....: %r" % s msg = msg + " " * ( 79 - ( len( msg ) + max_status ) % 80 ) print msg, r = expression_parser( s ) if str( r ) != e or DEBUG > 0: print print " Expected result....: %s" % e print " Result.............: %s" % r print " Parsed structure...:" print "-"*79 print "%r" % r print "-"*79 print if str( r ) != e: print status[ 0 ] return False else: print status[ 1 ] return True # test_parser() def test_eval( e, v, c ): """ Evaluate Expression e with values in dict 'v' and compare results with r Parameters: @param e Expression to be evaluated. @param v dict with values of variables and functions. @param c correct value expression should return when evaluated @return True if evaluates to the right value, False otherwise. """ status = [ "[FAILED]", "[PASSED]" ] max_status = max( len( status[ 0 ] ), len( status[ 1 ] ) ) msg = " Test expression....: %s" % e msg = msg + " " * ( 79 - ( len( msg ) + max_status ) % 80 ) print msg, exp = expression_parser( e ) r = evaluate_expression( exp, v ) if r != c or DEBUG > 0: print print " Parsed expression..: %s" % exp print " Expected result....: %r" % c print " Result.............: %r" % r print " Values.............: %s" % v print " Parsed structure...:" print "-"*79 print "%r" % exp print "-"*79 print if r != c: print status[ 0 ] return False else: print status[ 1 ] return True # test_eval() tests_parser = [ ( "a and b", "( a __and__ b )" ), ( "a or b", "( a __or__ b )" ), ( "a or not b", "( a __or__ __not__ b )" ), ( "a or b and c", "( a __or__ b __and__ c )" ), ( "a and ( b or c ) and d", "( a __and__ ( b __or__ c ) __and__ d )" ), ( "a and (b or c) and d", "( a __and__ ( b __or__ c ) __and__ d )" ), ( "2 + ( 3 * 4 )", "( 2 __+__ ( 3 __*__ 4 ) )" ), ( "function( a )", "( function( a ) )" ), ( "function( a, b )", "( function( a, b ) )" ), ( "function(a,b,c)", "( function( a, b, c ) )" ), ( "function( a and b )", "( function( a __and__ b ) )" ), ( "function( a and b, c )", "( function( a __and__ b, c ) )" ), ( "function( a and b, c or d )", "( function( a __and__ b, c __or__ d ) )" ), ( "'some string'", "( \"some string\" )" ), ( "\"other string\"", "( \"other string\" )" ), ( "'string' and var", "( \"string\" __and__ var )" ), ( "'string' and 123", "( \"string\" __and__ 123 )" ), ( '"nested \\"same quotes\\" string"', '( "nested \\"same quotes\\" string" )' ), ( "'nested \"different quotes\" string'", "( \"nested \\\"different quotes\\\" string\" )" ), ( "\"a'b\\'c\\'d'e\"", "( \"a\\'b\\\\'c\\\\'d\\'e\" )" ), ( "'any function() may be documented and checked'", "( \"any function() may be documented and checked\" )" ), ( "a and b or f( abc and def, 123 ) or b or \"123'a\\'b\\'c'\" and 123 or ( a and b )", "( a __and__ b __or__ f( abc __and__ def, 123 ) __or__ b __or__ \"123\\'a\\\\'b\\\\'c\\'\" __and__ 123 __or__ ( a __and__ b ) )" ), ( "1 + ( 2 + ( 3 + 4 ) + 5 ) + 6", "( 1 __+__ ( 2 __+__ ( 3 __+__ 4 ) __+__ 5 ) __+__ 6 )" ), ] tests_eval = [ # AND Karnaugh Map ( "a and b", { "a": True, "b": False }, False ), ( "a and b", { "a": False, "b": True }, False ), ( "a and b", { "a": False, "b": False }, False ), ( "a and b", { "a": True, "b": True }, True ), # OR Karnaugh Map ( "a or b", { "a": True, "b": False }, True ), ( "a or b", { "a": False, "b": True }, True ), ( "a or b", { "a": False, "b": False }, False ), ( "a or b", { "a": True, "b": True }, True ), # NOT ( "not a", { "a": True }, False ), ( "not a", { "a": False }, True ), # * ( "2 * 3", { }, 6 ), ( "2 * a", { "a": 3 }, 6 ), ( "a * 3", { "a": 2 }, 6 ), ( "a * b", { "a": 2, "b": 3 }, 6 ), # + ( "4 + 5", { }, 9 ), ( "4 + a", { "a": 5 }, 9 ), ( "a + 5", { "a": 4 }, 9 ), ( "a + b", { "a": 4, "b": 5 }, 9 ), ( "a + b", { "a": 'test', "b": 'worked' }, 'testworked' ), ( "a + 'worked'", { "a": 'test' }, 'testworked' ), # - ( "6 - 7", { }, -1 ), ( "6 - a", { "a": 7 }, -1 ), ( "a - 7", { "a": 6 }, -1 ), ( "a - b", { "a": 6, "b": 7 }, -1 ), # / ( "8.0 / 9.0", { }, 8.0/9.0 ), ( "8.0 / a", { "a": 9.0 }, 8.0/9.0 ), ( "a / 9.0", { "a": 8.0 }, 8.0/9.0 ), ( "a / b", { "a": 8.0, "b": 9.0 }, 8.0/9.0 ), # % ( "10 % 11", { }, 10 ), ( "10 % a", { "a": 11 }, 10 ), ( "a % 11", { "a": 10 }, 10 ), ( "a % b", { "a": 10, "b": 11 }, 10 ), # ** ( "12 ** 13", { }, 12**13 ), ( "12 ** a", { "a": 13 }, 12**13 ), ( "a ** 13", { "a": 12 }, 12**13 ), ( "a ** b", { "a": 12, "b": 13 }, 12**13 ), # == ( "1 == 2", { }, False ), ( "1 == 1", { }, True ), ( "1 == a", { "a": 2 }, False ), ( "a == 2", { "a": 1 }, False ), ( "a == b", { "a": 1, "b": 2 }, False ), ( "a == b", { "a": 2, "b": 2 }, True ), ( "'abc' == 'abc'", { }, True ), ( "'abc' == 'cde'", { }, False ), ( "a == b", { "a": 'test', "b": 'test' }, True ), ( "a == b", { "a": 'test1', "b": 'test2' }, False ), # != ( "1 != 2", { }, True ), ( "1 != 1", { }, False ), ( "1 != a", { "a": 2 }, True ), ( "a != 2", { "a": 1 }, True ), ( "a != b", { "a": 1, "b": 2 }, True ), ( "a != b", { "a": 2, "b": 2 }, False ), ( "'abc' != 'abc'", { }, False ), ( "'abc' != 'cde'", { }, True ), ( "a != b", { "a": 'test', "b": 'test' }, False ), ( "a != b", { "a": 'test1', "b": 'test2' }, True ), # Grouping: ( "1 + 2 * 3", { }, 1 + 2 * 3 ), ( "1 + 2 * 3 ** 4", { }, 1 + 2 * 3 ** 4 ), ( "1 + 2 % 3 * 4", { }, 1 + 2 % 3 * 4 ), ( "1 + 2 % 3 ** 4", { }, 1 + 2 % 3 ** 4 ), ( "10 / 2 * 3", { }, 10 / 2 * 3 ), ( "1 + ( 2 * 3 + 4 ) * 5", { }, 1 + ( 2 * 3 + 4 ) * 5 ), ( "1 + ( 2 + ( 3 + 4 ) + 5 ) + 6", { }, 1 + ( 2 + ( 3 + 4 ) + 5 ) + 6 ), ( " ( 1 + ( 2 * 3 + 4 ) * 5 ) * 3 ", { }, ( 1 + ( 2 * 3 + 4 ) * 5 ) * 3 ), ( " ( 2 + 3 ) ** ( 4 + 5 ) ", { }, ( 2 + 3 ) ** ( 4 + 5 ) ), ( "f( a )", { "f": lambda a: "***%s***" % a, "a": 123 }, "***123***" ), ( "f( a, b, c)", { "f": lambda a, b, c: a+b+c, "a":1, "b":2, "c":3 }, 6 ), ( "f( a, b)", { "f": lambda a, b: a+b, "a":'test', "b":'worked' }, 'testworked' ), ] if __name__ == "__main__": print "\nParser Tests:" for t in tests_parser: test_parser( t[ 0 ], t[ 1 ] ) print "\nEvaluation Tests:" for t in tests_eval: test_eval( t[ 0 ], t[ 1 ], t[ 2 ] )