def TestUnbalancedBrackets(self): """ Tests that an equation with unbalanced brackets is flagged as Malformed Equation """ test_eqn = [ "21a*sin(bx+(cy+dz)", "100log(ccos(xy+yz))+23(34)tan(exp(2x)", "sin(x)^(-2x+3y+aexp(-kt)" ] var = ['x','y','z','t'] const = {'a':'1','b':'1','c':'1','d':'1','k':'1'} for eqn in test_eqn: tokens = [(group,value) for group, value in self.lex.scan(eqn)] par = Parser(tokens, const, var) par.parseTokens()
def TestEvalExpressions(self): """ Tests that the expressions are evaluated successfully by eval() without raising any exceptions """ var = ['x','y','u','v'] const = {'a':'0.25','b':'1','c':'2.6','asinc':'8'} tokens = [(group,value) for group, value in self.lex.scan('a*sin(bx+cy-xy+exp(uv))asin(a*sin(asinc+asin(0.01cy)))+tan(log10(10))')] par = Parser(tokens, const, var) x = [1,1,1,1] eval(par.parseTokens()) var = ['t','theta'] const = {'a':'1.8','k':'16','c':'1','azm':'1'} tokens = [(group,value) for group, value in self.lex.scan('atan(aexp(-kt))+cktsin(azm*theta)')] par = Parser(tokens, const, var) x = [1,1] eval(par.parseTokens())
def TestIdentifier(self): """ Tests that the identifiers are properly parsed and ambiguous identifiers raise error """ const = {'b':'1','bat':'2'} var = ['attr'] tokens = [(group,value) for group, value in self.lex.scan('battrexp(x)+log(bat^x)')] par = Parser(tokens, const, var) nose.tools.assert_raises(AmbiguousIdentifierError, par.parseTokens) const = {'p':'3'} var = ['rice','price'] tokens = [(group,value) for group, value in self.lex.scan('plog(rice)+price*rice')] par = Parser(tokens, const, var) par.parseTokens() const = {'b':'1','a':'2', 'bet':'3'} var = ['x','eta'] tokens = [(group,value) for group, value in self.lex.scan('2betalog(x)+bet*a+b*etaexp(eta)')] par = Parser(tokens, const, var) nose.tools.assert_raises(AmbiguousIdentifierError, par.parseTokens)
def TestKnownValues(self): """ Tests some equations by comparing output to known results """ v = ['log'] c = {'exp':'1'} tokens = [(group,value) for group, value in self.lex.scan('expexp(exp)explog10(exp(log))')] par = Parser(tokens, c, v) assert par.parseTokens() == '1*exp(1)*1*log10(exp(x[0]))' v = ['x'] c = {} tokens = [(group,value) for group, value in self.lex.scan('sin(x)^-2+(cos(x))^2-1')] par = Parser(tokens, c, v) assert par.parseTokens() == 'sin(x[0])**-2+(cos(x[0]))**2-1' v = ['x','y','z'] c = {'a':'1.67e-5','b':'8'} tokens = [(group,value) for group, value in self.lex.scan('aexp(bx+xy) + sin(z)log(by)*5')] par = Parser(tokens, c, v) assert par.parseTokens() == '1.67e-5*exp(8*x[0]+x[0]*x[1])+sin(x[2])*log(8*x[1])*5'
def main(): var = [] const = [] eqn = [] reserved = ['exp','log','log10','acos','asin','atan','cos','sin','tan','cosh','sinh','tanh'] f = open(r'C:\Stuff\work\inputmv.txt', 'r') for line in f: if line[-1]=="\n": line = line[:-1] if line.find('var',0,3) == 0: var = line[line.find(' ')+1:].split(',') elif line.find('const',0,5) == 0: const = line[line.find(' ')+1:].split(',') elif len(line) > 0: eqn.append(line) f.close() # Make sure they are sorted by length if len(const) > 0: const.sort(lambda x, y: len(x)-len(y)) if len(var) > 0: var.sort(lambda x, y: len(x)-len(y)) for word in reserved: if word in var or word in const: raise InvalidNameError(word) rules = { "Function": r"(exp|log|log10|acos|asin|atan|cos|sin|tan|cosh|sinh|tanh)\(", "Number": r"\d+(\.\d+)?", "Operator": r"[-+()*^]", } lex = Lexer(rules, False) out = ['['] for equation in eqn: tokens = [(group,value) for group, value in lex.scan(equation)] par = Parser(tokens, const, var) out.append(par.parseTokens()) out.append(',') out.pop() out.append(']') ret = ''.join(out) print ret # Rewrite code including safe locals and globals dict #f = lambda x: eval(ret) #result = fsolve(f,[1,1]) #print result pass