mossadal / math-parser Goto Github PK
View Code? Open in Web Editor NEWPHP parser for mathematical expressions
License: GNU Lesser General Public License v3.0
PHP parser for mathematical expressions
License: GNU Lesser General Public License v3.0
If you supply a variable named e, the number e is used instead of the supplied value.
Maybe throw an exception when a variable named e is supplied?
We have expressions that may use some of from a lot of variables, more than 10K.
Does your parser have something like onVariable or onFunction events to catch and provide custom variables?
Right now the parser has some really useful interpretation exceptions. Unfortunately I found no possibility to get the, let's say an unknown token, from the exception. It's being merged with the exception's message. This forces me to inform an user with a generic error description.
This can easily be accomplished by adding an exception variable, with an accessor. For example, the token exception could get a public getToken()
method which will return the token only. If you agree and would like this feature, I can create a pull request for this.
Hello and thank you for publishing the package.
I've been trying pow() and log() with two parameters but the , returned the Unknown token exception.
The ** operator returned a Syntax error exception.
Code example
$parser = new StdMathParser();
$AST = $parser->parse( 'pow(33,10)' );
$evaluator = new Evaluator();
//$total returns the exceptions explained above
$total = $AST->accept($evaluator);
$parser = new StdMathParser();
$AST = $parser->parse( '3**10' );
$evaluator = new Evaluator();
//$total returns the exceptions explained above
$total = $AST->accept($evaluator);
Did I forget a step for those scenarios ?
All the other math functions and operator work as expected in my case.
Thanks again
Intelij (idea) doesn't understand @retval
. It works with @return
. The namespaces are different too.
Are you open for a pr?
Is there a simple way to add custom constants similar to 'pi' such as
epsilon_o = 8.8541878128e-12
speed_of_light = 299792458.0
electron_mass = 9.1e-31
...
so they can be utilized?
"0.148*speed_of_light^2"
Hello. Nice lib and examples of code. But how can i start to use it? Do i need compile somehow this code? If i just wanna use it on my web form to prevent some hacks in input (without php eval function). what i need to do to use your lib? Sorry for my bad English
Package operations: 70 installs, 0 updates, 0 removals
I needed something like the expression tree in math.js (https://mathjs.org/docs/expressions/expression_trees.html) to extract all variables from an expression. Like:
$formula = '(a+b)*c';
$variables = magic($formula);
print_r($variables); // ['a','b','c']
Unfortunately, it wasn't that straightforward to implement (without getting deep into the code/lexer stuff). Like everyone in 2023 I struggled my way through AI and finally got a working VariableCollector
class based on the Evaluate
class.
I leave the following AI-generated answer as a starting point for someone who is looking for an approach to solve it. If there is a better way, please add it here.
Based on the provided code, you can create a VariableCollector
class by extending the Evaluator
class and overriding the visitVariableNode()
method. This method is called when a VariableNode
is visited during the traversal of the Abstract Syntax Tree (AST).
Here's what your VariableCollector
class would look like:
namespace MathParser\Interpreting;
use MathParser\Parsing\Nodes\VariableNode;
class VariableCollector extends Evaluator
{
private $variables = [];
public function visitVariableNode(VariableNode $node)
{
$name = $node->getName();
if (!in_array($name, $this->variables)) {
$this->variables[] = $name;
}
}
public function getVariables()
{
return $this->variables;
}
}
In this class, the visitVariableNode
method adds the variable name to the $variables
array if it's not already there. The getVariables
method returns the collected variables.
To use the VariableCollector
class, you would do the following:
$collector = new VariableCollector();
$AST->accept($collector);
$variables = $collector->getVariables();
print_r($variables);
This will print an array of unique variable names that were found in the expression Source 2.
Please note that this example assumes that your variable names are single characters. If you use multi-character variable names, you will need to create a custom Lexer, as described in previous responses.
Source: https://www.phind.com/search?cache=xs6ryq72b7ofro516tfah9s5 -> last answer
I would like to run my own functions in evaluations. E.g.:
function doSomething($x) {
...
return $answer;
}
$AST = $parser->parse('doSomething(x)');
$evaluator->setVariables([ 'x' => 2 ]);
$value = $AST->accept($evaluator);
How to achieve this?
Hello @mossadal,
Will you upgrade your project to support PHP 8 as a major release 2.X any time soon ?
Best Regards
First of all, thanks for this great library! I really love how its structured with an AST and the code quality is great! We are using it at the Larachat's slackbot "Eve" and encountered some unexpected behaviours. You can view the whole discussion over here btw. Here are the expressions we used, what we expected and the result.
used | expected | result |
---|---|---|
0 ^ 0 |
1 | division by zero exception |
0 * log(0) |
NAN | 0 |
Is this something you would agree on?
Hi again! I found this other bug when I wanted to try to trigger various exceptions by writing bad equations.
$ php -v
PHP 7.0.15 (cli) (built: Feb 10 2017 16:55:27) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
$equation = '1(2';
$parser = new \MathParser\StdMathParser();
// Generate an abstract syntax tree.
$AST = $parser->parse( $equation );
// Evaluate the expression in the AST.
$evaluator = new \MathParser\Interpreting\Evaluator();
$value = $AST->accept( $evaluator );
PHP Fatal error: Uncaught Error: Call to undefined method MathParser\Parsing\Nodes\SubExpressionNode::setLeft() in ./vendor/mossadal/math-parser/src/MathParser/Parsing/Parser.php:278
If you use a negative number on the right hand side, the StdMathParser will return a Syntax Error.
For example: 6 + -1
which is valid and would result in 5
.
Hi, can u please add Maximum, Minimum Functions?
For Example:
max(1,3) + 7
// return 10
min(5,0) + 10
//return 10
or if possible:
max(1,2,3,4,5) + 1
//return 6
//x=1 , y=2
max(x,y) + 10
// return 12
Thanks for sharing this work! I would like to parse dollar values in my expression, for example:
$1,500.75 - $200.00
I'm not sure the best way to do this, but it looks like I can create a custom Lexer and add a token definition with an custom pattern that will match dollar values.
However, I would still need to parse the token into a float. For TokenType::RealNumber
this happens in the Node::factory
method which is called from the private function shuntingYard
in the the Parser class. This doesn't look easily extendable.
Do you have any suggestions on how I should go about this?
Hi,
how can add a new Operator "pipe ( | )" that acts as "add ( + )" put 0 whereas a variable is null (or blank)?
This is an example how to get it worked:
a=5, b=null
a+b = null (actual working)
a|b = 5 (desidered)
Thanks
$expression = 'a + i';
$variableValues = ['a' => 1, 'i' => 1];
// Generate an abstract syntax tree
$AST = $this->parser->parse($expression);
// Set variables with value ['x' => 1, ..]
$this->evaluator->setVariables($variableValues);
// pass evaluator to Abstract Syntax Tree
$value = $AST->accept($this->evaluator);
return $value;
Any expression that contains i
seems the throw the following expception:
MathParser\Exceptions\UnknownConstantException: Unknown constant i.
Replacing i with any other alphabet seems to fix the issue.
"1+.1"
(or ".1"
) triggers an exception saying Unknown token 0 encountered
.
Maybe add some parsing logic to say "if period, assume a zero to the left"?
So that "1+.1"
is treated as "1+0.1"
.
Does that make sense? Or is this a bad idea? ;-)
Hi! I found this bug when I wanted to try to trigger various exceptions by writing bad equations.
$ php -v
PHP 7.0.15 (cli) (built: Feb 10 2017 16:55:27) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
$equation = '2poww(2)';
$parser = new \MathParser\StdMathParser();
// Generate an abstract syntax tree.
$AST = $parser->parse( $equation );
// Evaluate the expression in the AST.
$evaluator = new \MathParser\Interpreting\Evaluator();
$value = $AST->accept( $evaluator );
PHP Warning: array_key_exists() expects parameter 2 to be array, null given in ./vendor/mossadal/math-parser/src/MathParser/Interpreting/Evaluator.php on line 162
Warning: array_key_exists() expects parameter 2 to be array, null given in ./vendor/mossadal/math-parser/src/MathParser/Interpreting/Evaluator.php on line 162
When I pulled your project, I tried to run the tests and this error occurred:
PHP Fatal error: Uncaught Error: Class 'PHP_Timer' not found math-parser/vendor/phpunit/phpunit/src/Framework/TestResult.php:662
I made some researches and I found this recent issue (around 6 months old) about the problem.
sebastianbergmann/phpunit#3008
Apparently, some old phpunit versions can't work with the new version of PHP_Timer. I've tried the conflict param for composer, but it didn't seem to work. I will continue to search a solution.
I must admit that I pulled your project to run the tests because I tried to evaluate round, ceil and floor functions and I got this error:
"MathParser\Exceptions\UnknownVariableException : Unknown variable r." has if round is not a function...
EDIT: Well I found out why round, ceil and floor throw exception. They seem to work on dev-master, but not on your last tag (1.3.13). But still nothing for PHP_Timer.
Greetings!
I'm a little surprised that this super-functional library doesn't support calculating the remainder of the division (%)
Maybe I didn't study the code carefully?
If it really does not exist, please add.
I've studied the code, it should be a pretty simple action. At the same time, I have not found an opportunity to extend expressions in child classes
Thank you for your work and attention
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.