1010import sympy
1111
1212from sympy .core .relational import Relational
13- import sympy .parsing .sympy_tokenize as sympy_tokenize
14- from token import NAME
13+ import tokenize as sympy_tokenize
1514from six .moves import map
1615from six .moves import zip
1716
17+ from sympy .parsing .sympy_parser import (
18+ AppliedFunction , implicit_multiplication , split_symbols ,
19+ function_exponentiation , implicit_application , OP , NAME ,
20+ _group_parentheses , _apply_functions , _flatten , _token_callable
21+ )
22+
1823OTHER_SYMPY_FUNCTIONS = ('sqrt' ,)
1924
2025Arguments = collections .namedtuple ('Arguments' , 'function args kwargs' )
2126
27+
2228class Eval (object ):
2329 def __init__ (self , namespace = {}):
2430 self ._namespace = namespace
@@ -79,6 +85,7 @@ def eval(self, x, use_none_for_exceptions=False, repr_expression=True):
7985 s = "" .join (traceback .format_exception (etype , value , tb ))
8086 return s
8187
88+
8289class LatexVisitor (ast .NodeVisitor ):
8390 EXCEPTIONS = {'integrate' : sympy .Integral , 'diff' : sympy .Derivative }
8491 formatters = {}
@@ -129,6 +136,7 @@ def visit_Call(self, node):
129136 self .latex = sympy .latex (self .evaluator .eval_node (node ))
130137 return self .latex
131138
139+
132140@LatexVisitor .formats_function ('solve' )
133141def format_solve (node , visitor ):
134142 expr = visitor .evaluator .eval_node (node .args [0 ])
@@ -147,12 +155,14 @@ def format_solve(node, visitor):
147155
148156 return '' .join (buffer )
149157
158+
150159@LatexVisitor .formats_function ('limit' )
151160def format_limit (node , visitor ):
152161 if len (node .args ) >= 3 :
153162 return sympy .latex (
154163 sympy .Limit (* [visitor .evaluator .eval_node (arg ) for arg in node .args ]))
155164
165+
156166@LatexVisitor .formats_function ('prime' )
157167def format_prime (node , visitor ):
158168 number = sympy .latex (visitor .evaluator .eval_node (node .args [0 ]))
@@ -161,26 +171,31 @@ def format_prime(node, visitor):
161171 ordinal (int (number )),
162172 r'}\; \mathrm{prime~number}' ])
163173
174+
164175@LatexVisitor .formats_function ('isprime' )
165176def format_isprime (node , visitor ):
166177 number = sympy .latex (visitor .evaluator .eval_node (node .args [0 ]))
167178 return '' .join ([r'\mathrm{Is~}' , number , r'\mathrm{~prime?}' ])
168179
180+
169181@LatexVisitor .formats_function ('nextprime' )
170182def format_nextprime (node , visitor ):
171183 number = sympy .latex (visitor .evaluator .eval_node (node .args [0 ]))
172184 return r'\mathrm{Least~prime~greater~than~}' + number
173185
186+
174187@LatexVisitor .formats_function ('factorint' )
175188def format_factorint (node , visitor ):
176189 number = sympy .latex (visitor .evaluator .eval_node (node .args [0 ]))
177190 return r'\mathrm{Prime~factorization~of~}' + number
178191
192+
179193@LatexVisitor .formats_function ('factor' )
180194def format_factor (node , visitor ):
181195 expression = sympy .latex (visitor .evaluator .eval_node (node .args [0 ]))
182196 return r'\mathrm{Factorization~of~}' + expression
183197
198+
184199@LatexVisitor .formats_function ('solve_poly_system' )
185200def format_factorint (node , visitor ):
186201 equations = visitor .evaluator .eval_node (node .args [0 ])
@@ -194,6 +209,7 @@ def format_factorint(node, visitor):
194209 r'\end{cases} \mathrm{~for~}' ,
195210 sympy .latex (variables )])
196211
212+
197213@LatexVisitor .formats_function ('plot' )
198214def format_plot (node , visitor ):
199215 if node .args :
@@ -205,6 +221,7 @@ def format_plot(node, visitor):
205221 function = sympy .latex (keywords )
206222 return r'\mathrm{Plot~}' + function
207223
224+
208225@LatexVisitor .formats_function ('rsolve' )
209226def format_rsolve (node , visitor ):
210227 recurrence = sympy .latex (sympy .Eq (visitor .evaluator .eval_node (node .args [0 ]), 0 ))
@@ -217,8 +234,11 @@ def format_rsolve(node, visitor):
217234 else :
218235 return r'\mathrm{Solve~the~recurrence~}' + recurrence
219236
237+
220238diophantine_template = (r"\begin{{align}}&{}\\&\mathrm{{where~}}"
221239 r"{}\mathrm{{~are~integers}}\end{{align}}" )
240+
241+
222242@LatexVisitor .formats_function ('diophantine' )
223243def format_diophantine (node , visitor ):
224244 expression = visitor .evaluator .eval_node (node .args [0 ])
@@ -232,6 +252,7 @@ def format_diophantine(node, visitor):
232252 result = diophantine_template .format (result , tuple (symbols ))
233253 return result
234254
255+
235256@LatexVisitor .formats_function ('summation' )
236257@LatexVisitor .formats_function ('product' )
237258def format_diophantine (node , visitor ):
@@ -241,13 +262,15 @@ def format_diophantine(node, visitor):
241262 klass = sympy .Product
242263 return sympy .latex (klass (* list (map (visitor .evaluator .eval_node , node .args ))))
243264
265+
244266@LatexVisitor .formats_function ('help' )
245267def format_help (node , visitor ):
246268 if node .args :
247269 function = visitor .evaluator .eval_node (node .args [0 ])
248270 return r'\mathrm{Show~documentation~for~}' + function .__name__
249271 return r'\mathrm{Show~documentation~(requires~1~argument)}'
250272
273+
251274class TopCallVisitor (ast .NodeVisitor ):
252275 def __init__ (self ):
253276 super (TopCallVisitor , self ).__init__ ()
@@ -264,12 +287,14 @@ def visit_NameConstant(self, node):
264287 if not self .call :
265288 self .call = node
266289
290+
267291# From https://stackoverflow.com/a/739301/262727
268292def ordinal (n ):
269293 if 10 <= n % 100 < 20 :
270294 return 'th'
271295 else :
272- return {1 : 'st' , 2 : 'nd' , 3 : 'rd' }.get (n % 10 , "th" )
296+ return {1 : 'st' , 2 : 'nd' , 3 : 'rd' }.get (n % 10 , "th" )
297+
273298
274299# TODO: modularize all of this
275300def latexify (string , evaluator ):
@@ -278,13 +303,15 @@ def latexify(string, evaluator):
278303 a .visit (ast .parse (string ))
279304 return a .latex
280305
306+
281307def topcall (string ):
282308 a = TopCallVisitor ()
283309 a .visit (ast .parse (string ))
284310 if hasattr (a , 'call' ):
285311 return getattr (a .call .func , 'id' , None )
286312 return None
287313
314+
288315def arguments (string_or_node , evaluator ):
289316 node = None
290317 if not isinstance (string_or_node , ast .Call ):
@@ -315,21 +342,20 @@ def arguments(string_or_node, evaluator):
315342 return Arguments (node .value , [], {})
316343 return None
317344
345+
318346re_calls = re .compile (r'(Integer|Symbol|Float|Rational)\s*\([\'\"]?([a-zA-Z0-9\.]+)[\'\"]?\s*\)' )
319347
348+
320349def re_calls_sub (match ):
321350 return match .groups ()[1 ]
322351
352+
323353def removeSymPy (string ):
324354 try :
325355 return re_calls .sub (re_calls_sub , string )
326356 except IndexError :
327357 return string
328358
329- from sympy .parsing .sympy_parser import (
330- AppliedFunction , implicit_multiplication , split_symbols ,
331- function_exponentiation , implicit_application , OP , NAME ,
332- _group_parentheses , _apply_functions , _flatten , _token_callable )
333359
334360def _implicit_multiplication (tokens , local_dict , global_dict ):
335361 result = []
@@ -385,6 +411,7 @@ def _implicit_multiplication(tokens, local_dict, global_dict):
385411 result .append (tokens [- 1 ])
386412 return result
387413
414+
388415def implicit_multiplication (result , local_dict , global_dict ):
389416 """Makes the multiplication operator optional in most cases.
390417
@@ -407,6 +434,7 @@ def implicit_multiplication(result, local_dict, global_dict):
407434 result = _flatten (result )
408435 return result
409436
437+
410438def custom_implicit_transformation (result , local_dict , global_dict ):
411439 """Allows a slightly relaxed syntax.
412440
@@ -446,6 +474,7 @@ def custom_implicit_transformation(result, local_dict, global_dict):
446474 u'draw' : 'plot'
447475}
448476
477+
449478def synonyms (tokens , local_dict , global_dict ):
450479 """Make some names synonyms for others.
451480
@@ -463,6 +492,7 @@ def synonyms(tokens, local_dict, global_dict):
463492 result .append (token )
464493 return result
465494
495+
466496def close_matches (s , global_dict ):
467497 """
468498 Checks undefined names to see if they are close matches to a defined name.
0 commit comments