3 from compiler
.transformer
import Transformer
4 from compiler
.visitor
import ASTVisitor
5 from compiler
.ast
import CallFunc
, Name
, Const
, Tuple
6 from compiler
.pycodegen
import ExpressionCodeGenerator
9 from basic
import Basic
10 from function
import FunctionClass
11 from symbol
import Symbol
13 ###################################################3
15 ###################################################3
17 _is_integer
= re
.compile(r
'\A\d+(l|L)?\Z').match
19 int_types
= (int, long)
21 complex_types
= (complex)
22 string_types
= (str) # XXX: unicode?
25 ###################################################3
27 ###################################################3
29 class SymPyTransformer(Transformer
):
30 def __init__(self
, local_dict
, global_dict
):
31 Transformer
.__init
__(self
)
33 self
.symbol_class
= 'Symbol'
35 self
.local_dict
= local_dict
36 self
.global_dict
= global_dict
38 def atom_number(self
, nodelist
):
39 n
= Transformer
.atom_number(self
, nodelist
)
40 number
, lineno
= nodelist
[0][1:]
41 if _is_integer(number
):
42 n
= Const(long(number
), lineno
)
43 return CallFunc(Name('Integer'), [n
])
44 if number
.endswith('j'):
45 n
= Const(complex(number
), lineno
)
46 return CallFunc(Name('sympify'), [n
])
47 n
= Const(number
, lineno
)
48 return CallFunc(Name('Real'), [n
])
50 def atom_name(self
, nodelist
):
51 name
, lineno
= nodelist
[0][1:]
53 if self
.local_dict
.has_key(name
):
54 name_obj
= self
.local_dict
[name
]
55 return Const(name_obj
, lineno
=lineno
)
56 elif self
.global_dict
.has_key(name
):
57 name_obj
= self
.global_dict
[name
]
59 if isinstance(name_obj
, (Basic
, type)) or callable(name_obj
):
60 return Const(name_obj
, lineno
=lineno
)
61 elif name
in ['True', 'False']:
62 return Const(eval(name
), lineno
=lineno
)
64 symbol_obj
= Symbol(name
)
65 self
.local_dict
[name
] = symbol_obj
67 return Const(symbol_obj
, lineno
=lineno
)
69 def lambdef(self
, nodelist
):
70 #this is python stdlib symbol, not SymPy symbol:
71 from sympy
import stdlib_symbol
72 if nodelist
[2][0] == stdlib_symbol
.varargslist
:
73 names
, defaults
, flags
= self
.com_arglist(nodelist
[2][1:])
78 lineno
= nodelist
[1][2]
79 code
= self
.com_node(nodelist
[-1])
81 assert not defaults
,`defaults`
# sympy.Lambda does not support optional arguments
82 assert len(names
) <= 1
85 argument
= CallFunc( Name('Symbol'), [Const(names
[0], lineno
=lineno
)])
87 argument
= CallFunc( Name('Symbol'), [Const('x')])
89 return CallFunc(Name('Lambda'),[argument
, code
])
93 def __init__(self
, local_dict
={}): #Contents of local_dict change, but it has proper effect only in global scope
95 exec 'from sympy import *' in global_dict
97 self
.r_transformer
= SymPyTransformer(local_dict
, global_dict
)
98 self
.local_dict
= local_dict
99 self
.global_dict
= global_dict
101 def parse_expr(self
, ws_expression
):
102 expression
= ws_expression
.strip() #in case of " x"
103 ast_tree
= parser
.expr(expression
)
104 ast_tree
= self
.r_transformer
.transform(ast_tree
)
106 compiler
.misc
.set_filename('<sympify>', ast_tree
)
107 code
= ExpressionCodeGenerator(ast_tree
).getCode()
109 parsed_expr
= eval(code
, self
.local_dict
, self
.global_dict
) #Changed order to prefer sympy objects to user defined