mossadal/math-parser
Safe PHP math expression parser/evaluator that builds an AST from user formulas. Supports arithmetic, variables, and elementary functions, plus interpreters for evaluation, symbolic differentiation, and LaTeX pretty-printing; customizable lexer/parser with StdMathParser.
Installation:
composer require mossadal/math-parser
Basic Evaluation:
use MathParser\StdMathParser;
use MathParser\Interpreting\Evaluator;
$parser = new StdMathParser();
$ast = $parser->parse('2 + 3 * x');
$evaluator = new Evaluator();
$evaluator->setVariables(['x' => 5]);
$result = $ast->accept($evaluator); // Returns 17
First Use Case:
public function calculate(Request $request) {
$expression = $request->input('expression');
$variables = $request->input('variables', []);
$parser = new StdMathParser();
$ast = $parser->parse($expression);
$evaluator = new Evaluator();
$evaluator->setVariables($variables);
return response()->json(['result' => $ast->accept($evaluator)]);
}
StdMathParser and Evaluator for 90% of use cases.$ast object to understand how expressions are parsed (e.g., $ast->toString()).Expression Evaluation:
$parser = new StdMathParser();
$ast = $parser->parse($expression);
$evaluator = new Evaluator();
$evaluator->setVariables($variables);
return $ast->accept($evaluator);
MathEvaluatorService) with dependency injection.Symbolic Differentiation:
$differentiator = new Differentiator('x');
$dfAst = $parser->parse('x^2 + sin(y)')->accept($differentiator);
$result = $dfAst->accept(new Evaluator(['x' => 1, 'y' => 0])); // Returns 2
LaTeX Output:
$latexGenerator = new \MathParser\Interpreting\LatexGenerator();
$latex = $parser->parse('(a + b)/c')->accept($latexGenerator);
// Output: \frac{a + b}{c}
<script>
MathJax.typeset();
</script>
<div>{{ $latex }}</div>
Validation:
$parser = new StdMathParser([
'functions' => ['sin', 'cos', 'log'],
'variables' => ['x', 'y', 'z']
]);
$request->validate([
'expression' => 'required|regex:/^[a-zA-Z0-9+\-*\/^().\s]+$/'
]);
Caching:
$cacheKey = 'math_ast:' . md5($expression);
$ast = cache()->remember($cacheKey, now()->addHours(1), function() use ($parser, $expression) {
return $parser->parse($expression);
});
Error Handling:
try {
$ast = $parser->parse($expression);
return $ast->accept($evaluator);
} catch (\MathParser\Exception\ParseException $e) {
return response()->json(['error' => 'Invalid expression'], 400);
}
Custom Functions:
$parser = new StdMathParser();
$parser->addFunction('myFunc', function($args) {
return array_product($args);
});
$ast = $parser->parse('myFunc(2, 3, 4)'); // Returns 24
public function register() {
$this->app->singleton(StdMathParser::class, function() {
return new StdMathParser(['functions' => ['sin', 'cos']]);
});
}
public function toArray($request) {
return [
'result' => $this->evaluator->evaluate($this->expression),
'latex' => $this->latexGenerator->generate($this->ast),
];
}
Implicit Multiplication Quirks:
2x is parsed as 2*x, but x^2y is parsed as x^(2*y) (not x^2*y).2*x*y) for clarity or enforce rules via validation.Variable Naming:
x, y) work with implicit multiplication.Floating-Point Precision:
0.1 + 0.2 !== 0.3).bcmath or gmp for high-precision needs:
$evaluator = new Evaluator();
$evaluator->setPrecision(10); // If supported (check package docs)
Security Risks:
validate to restrict input format.Memory Usage:
LaTeX Generation:
Enable Debug Mode:
\MathParser\StdMathParser::setDebugMode(true);
Inspect AST:
$ast->toString(); // Prints the parsed expression tree
Step-by-Step Evaluation:
Evaluator to log intermediate steps:
class DebugEvaluator extends Evaluator {
public function visitBinaryOpNode($node) {
logger()->debug("Evaluating: {$node->left->toString()} {$node->op} {$node->right->toString()}");
return parent::visitBinaryOpNode($node);
}
}
Default Functions:
sin, cos, log, etc.), but not all are enabled by default.$parser = new StdMathParser(['functions' => ['sin', 'exp']]);
Operator Precedence:
x^2y is parsed as x^(2*y), not (x^2)*y.Variable Scope:
Evaluator instance.Evaluator for each evaluation if variables are scoped:
$evaluator = new Evaluator(['x' => 1, 'y' => 2]);
Custom Lexer/Parser:
Lexer or Parser classes to support custom syntax (e.g., custom operators).^ for exponentiation (already supported, but can be overridden).Custom Interpreters:
Visitor interface to create new interpreters (e.g., for code generation).class PythonCodeGenerator implements Visitor {
public function visitBinaryOpNode($node) {
return "({$node->left->accept($this)} {$node->op} {$node->right->accept($this)})
How can I help you explore Laravel packages today?