import logging
from latex2sympy import latex2sympy
from sympy import Add, Mul, Pow, sin, cos, tan, sqrt, log, exp, Integral, Derivative, Sum
from sympy.core.function import AppliedUndef # <-- import the missing class
# Define how each node type or function should be spelled out
node_to_spelling = {
Add: 'plus',
Mul: 'times',
Pow: 'to the power of',
AppliedUndef: 'applied to', # now resolved
# Functions (common ones)
sin: 'sine of',
cos: 'cosine of',
tan: 'tangent of',
sqrt: 'square root of',
log: 'logarithm of',
exp: 'exponential of',
Integral: 'the integral of',
Sum: 'the summation of',
Derivative: 'the derivative of',
}
def parse_math_expression(latex_math_string):
"""
Parses a LaTeX mathematical string into a SymPy expression.
"""
if not isinstance(latex_math_string, str) or not latex_math_string.strip():
logging.warning("Received invalid or empty input for parsing.")
return None
logging.info(f"Attempting to parse LaTeX math string: '{latex_math_string[:100]}...'")
try:
return latex2sympy(latex_math_string)
except Exception as e:
logging.error(f"Error during parsing: {e}")
return None
def spell_out_sympy_expression(expr):
"""
Recursively spells out a SymPy expression into words.
"""
from sympy import Symbol, Number, Function
# Base cases
if expr.is_Number:
return str(expr)
if expr.is_Symbol:
return str(expr)
if isinstance(expr, Number):
return str(expr)
# Operators and functions
if isinstance(expr, Add):
return ' plus '.join(spell_out_sympy_expression(arg) for arg in expr.args)
if isinstance(expr, Mul):
return ' times '.join(spell_out_sympy_expression(arg) for arg in expr.args)
if isinstance(expr, Pow):
base, exponent = expr.args
return f"{spell_out_sympy_expression(base)} to the power of {spell_out_sympy_expression(exponent)}"
if isinstance(expr, Function):
func_type = type(expr)
func_name = node_to_spelling.get(func_type, func_type.__name__)
args_spelled = ' and '.join(spell_out_sympy_expression(arg) for arg in expr.args)
return f"{func_name} {args_spelled}"
return str(expr)
# Example usage
latex_math = r"\frac{-b \pm \sqrt{b^2-4ac}}{2a}"
sympy_expr = parse_math_expression(latex_math)
if sympy_expr:
print(spell_out_sympy_expression(sympy_expr))
By adding from sympy.core.function import AppliedUndef, the NameError will be resolved. You can integrate this corrected import into your existing script so the node_to_spelling dictionary recognizes AppliedUndef correctly.