Как использовать деревья выражений в PHP? - PullRequest
1 голос
/ 19 марта 2012

В настоящее время я делаю PHP-программу, которая решает уравнения. Я разделил входное уравнение на массив так, чтобы каждая строка в массиве содержала один член. (Итак. [0] = "+ 5x", [1] = "=", [2] = "-5", [3] = "+10". Это просто базовое уравнение. Скрипт также делит то, что находится в () в под-массивах. Так, например, 2x + (5-3x) = 3 (x + 1) [0] = "+ 2 * x", [1] = массив ([0] = "+5" ....

Однако я обнаружил деревья выражений, которые идеально подходят для использования в этом решении уравнений. Я искал весь Интернет, чтобы узнать это, но я не могу найти сайты, которые объясняют это на PHP (я знаю PHP OOP.). Есть много страниц, объясняющих их, например, в Си, но, поскольку я знаю только PHP, это не поможет, потому что я не понимаю пример кода.

Может ли кто-нибудь здесь объяснить все о деревьях выражений в PHP и некотором практическом примере кода?

Ответы [ 4 ]

4 голосов
/ 19 марта 2012

Здесь описан алгоритм . Вы можете реализовать это в PHP. Я не думаю, что кто-то уже реализовал это в PHP (и распространяет это как открытый исходный код)

Примером может быть:

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

Где:

  • * = приоритет 2
  • + = приоритет 1
  • ( = повысит приоритет знаков на 10
  • + (второй +) = приоритет 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

2 голосов
/ 19 марта 2012

Я построил дерево выражений в PHP, которое анализирует математические выражения и пытается решить проблему. Вы можете найти источник здесь http://codehackit.blogspot.com/2011/08/expression-parser-in-php.html

Я довольно подробно объясняю все детали в этом сообщении в блоге, но если вы обнаружите какие-либо двусмысленности, просто спросите здесь;)

Ура, надеюсь, это поможет или хотя бы вдохновит

2 голосов
/ 19 марта 2012

Я бы посоветовал вам прочитать немного о Составной шаблон проектирования для ваших деревьев выражений. В статье Википедии об этом есть несколько 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.

0 голосов
/ 19 марта 2012

Я написал скобочный парсер для этой утилиты несколько лет назад - он принимает выражение SQL WHERE в квадратных скобках практически любой глубины и преобразует его в код PHP Propel.Весь тарбол: здесь , а синтаксический анализ выражения запущен здесь .Код может быть более аккуратным, и имейте в виду, что я не знаком ни с какими методами анализа формальных выражений - но он работает, по моде :).

...