如何在PHP中使用表达式树?

时间:2012-03-18 21:48:52

标签: php expression-trees

我目前正在制作一个解决方程式的PHP程序。我已将输入方程式划分为数组,以便数组中的每一行包含一个项。 (所以。[0] =“+ 5x”,[1] =“=”,[2] =“ - 5”,[3] =“+ 10”。这只是一个基本的等式。脚本也划分了什么因此例如2x +(5-3x)= 3(x + 1)[0] =“+ 2 * x”,[1] =数组([0] =“+ 5”)在()中进入子数组。 ....

然而,我发现表达式树在这个等式求解器中使用是完美的。我搜索了整个互联网来学习它,但我找不到任何用PHP解释它的网站(我知道PHP OOP。)。有很多页面在例如C中解释它们,但由于我只知道PHP,这没有用,因为我不理解示例代码。

这里的任何人都可以解释PHP中表达式树的一切和一些实际的示例代码吗?

4 个答案:

答案 0 :(得分:4)

Here is the algorithm描述。你可以在PHP中实现它。我认为没有人已经在PHP中实现了这一点(并将其作为开源发布)

一个例子是:

2*x+3*5-(6+9) = 0

其中:

  • * = priority 2
  • + =优先级1
  • ( =将标志的优先级提高10
  • +(second +)= priority 11
  • ) =将降低标志的优先级10
  • = =在这种情况下,它显示有另一个表达式(0)

最重要的是最重要的 - 首先需要做的

使用这些规则,您可以创建表达式树...

所以..你必须创建表达式然后解释的方式是:

2 x * 3 5 * + 6 9 + -

说明:

  • 2 * x | (1)
  • 3 * 5 | (2)
  • (1) + (2) | (3)
  • 6 + 9 | (4)
  • (3) - (4) = final

我不记得究竟如何写一棵树,我把它做到了计算机科学课程,但它是这样的:

                                     -
                                /         \
                                E         (E)
                                |          +
                                +         / \
                             /    \      6   9
                            E      E        
                            |      |    
                            *      *
                           / \    / \    
                          T   E   T  E
                          |   |   |  |
                          2   T   3  T
                              |      |
                              x      5

现在你必须为此创建自己的解释器。您可以使用解释器模式:PHP Interpreter

答案 1 :(得分:2)

我建议您阅读一些关于表达式树Composite design pattern的内容。关于它的维基百科文章有一些UML图和示例Java代码,翻译成PHP并不困难。

您可能还需要查看Shunting-yard算法,以便将字符串解析为表达式树。

表达式树的一个(非常简单的)PHP示例可能如下所示:

interface INode {
    public function getValue();
}

class ValueNode implements INode {
    private $val;

    function __construct($val) {
        $this->val = $val;
    }

    public function getValue() {
        return $this->val;
    }
}

class AdditionNode implements INode {
    private $op1, $op2;

    function __construct($op1, $op2) {
        if(!($op1 instanceof INode) or !($op2 instanceof INode)) {
            throw new Exception("The operands must implement the INode interface.");
        }

        $this->op1 = $op1;
        $this->op2 = $op2;
    }

    public function getValue() {
        return $this->op1->getValue() + $this->op2->getValue();
    }
}


$a = new ValueNode(1);
$b = new ValueNode(5);
$c = new ValueNode(10);
$add1 = new AdditionNode($a, $b);
$add2 = new AdditionNode($add1, $c);

echo $add2->getValue(); // 16

在这种情况下,INode接口只有一个方法应该返回以节点为根的子树的值。

ValueNode类是一个简单的包装器,允许数字成为表达式树的一部分(实际上,在PHP中,您不仅限于ValueNode中的数字)。 ValueNode个对象只能用作表达式树中的叶节点。

您开始将复合模式与AdditionNode类一起使用,该类接受INode个对象作为子对象,可以帮助您构建表达式树。

您可以进一步扩展此示例以添加其他操作,变量,常量等,这些都将实现INode接口。

答案 2 :(得分:2)

我在PHP中构建了一个表达式树,它解析数学表达式并尝试解决问题。您可以在http://codehackit.blogspot.com/2011/08/expression-parser-in-php.html

找到来源

我几乎解释了博客文章中的所有细节,但如果你发现任何含糊之处,请在这里询问;)

欢呼,希望它有助于或至少激发

答案 3 :(得分:0)

几年前我为this utility编写了一个括号解析器 - 它采用了几乎任何深度的括号SQL WHERE表达式,并将其转换为PHP Propel代码。整个tarball是here,表达式解析开始here。代码可能更整洁,请记住,我不熟悉任何正式的表达式分析技术 - 但它在时尚:)之后有效。