lmfit / asteval

minimalistic evaluator of python expression using ast module
https://lmfit.github.io/asteval
MIT License
176 stars 41 forks source link

Access to parse tree? #82

Closed colmshell closed 3 years ago

colmshell commented 3 years ago

Hi. First of all, thanks for this wonderful project. It did exactly what I was looking for. I am using it to execute user defined math formulae and for that it works really well. I really appreciate being able to lock down the interpreter. I found it after going through "formulas", pandas.eval (where I ran into this nasty bug https://github.com/pandas-dev/pandas/issues/24670 ) and even briefly flirting with using python eval. Finding this made my day.

I also have a need to display these user defined formulae. It would be pretty great if this package could help with that by exposing the AST or something. I'm currently using "formulas", but I'm not a great fan of this package.

I also briefly looked at https://github.com/glenfletcher/Equation which generates latex, but it's unmaintained and doesn't seem to let you use custom functions.

newville commented 3 years ago

@colmshell I'm glad it helps!

I also have a need to display these user defined formulae. It would be pretty great if this package could help with that by exposing the AST or something. I'm currently using "formulas", but I'm not a great fan of this package.

Don't you already have the user's expression that is sent to the interpreter?

For completeness, you can use the parse method to get back the AST, so that you could do something like

 >>> from asteval import Interpreter 
 >>> import ast
 >>> aeval = Interpreter()
 >>> ast.dump(aeval.parse('sin(x/3)')
"Module(body=[Expr(value=Call(func=Name(id='sin', ctx=Load()), args=[BinOp(left=Name(id='x', ctx=Load()), op=Div(), right=Constant(value=3, kind=None))], keywords=[]))], type_ignores=[])"

That is the AST represents 'sin(x/3)', but I'm not sure what else you would want to do with it (besides "evaluate it"!) that wasn't also represented by the string 'sin(x/3)'.

colmshell commented 3 years ago

Ah, perfect, thanks. I think this probably does what I need.

I wanted to render the formula I'm parsing using HTML. If I have myfunction(x / y), with a parse tree I can hyperlink myfunction, x and y to explanations for users who view the formula.