protected function detectCalculationOrder(array $nodes)
    {
        $operatorNodes = [];

        // Store all symbol nodes that have a symbol of type abstract operator in an array
        foreach ($nodes as $index => $node) {
            if (is_a($node, SymbolNode::class)) {
                if (is_a($node->getSymbol(), AbstractOperator::class)) {
                    $operatorNodes[$index] = $node;
                }
            }
        }

        // Using Quicksort algorithm to sort the operators according to their precedence. Keeps the indices.
        // Returning 1 means $nodeTwo before $nodeOne, returning -1 means $nodeOne before $nodeTwo.
        uasort($operatorNodes, function(SymbolNode $nodeOne, SymbolNode $nodeTwo)
        {
            // First-level precedence of node one
            /** @var AbstractOperator $symbolOne */
            $symbolOne = $nodeOne->getSymbol();
            $precedenceOne = 2;
            if ($nodeOne->isUnaryOperator()) {
                $precedenceOne = 3;
            }

            // First-level precedence of node two
            /** @var AbstractOperator $symbolTwo */
            $symbolTwo = $nodeTwo->getSymbol();
            $precedenceTwo = 2;
            if ($nodeTwo->isUnaryOperator()) {
                $precedenceTwo = 3;
            }

            // If the first-level precedence is the same, compare the second-level precedence
            if ($precedenceOne == $precedenceTwo) {
                $precedenceOne = $symbolOne->getPrecedence();
                $precedenceTwo = $symbolTwo->getPrecedence();
            }

            // If the second-level precedence is the same, we have to ensure that the sorting algorithm does
            // insert the node / token that is left in the term before the node / token that is right.
            // Therefore we cannot return 0 but compare the positions and return 1 / -1.
            if ($precedenceOne == $precedenceTwo) {
                return ($nodeOne->getToken()->getPosition() < $nodeTwo->getToken()->getPosition()) ? -1 : 1;
            }
            return ($precedenceOne < $precedenceTwo) ? 1 : -1;
        });

        return $operatorNodes;
    }
protected function detectCalculationOrder(array $nodes)
    {
        $operatorNodes = [];

        // Store all symbol nodes that have a symbol of type abstract operator in an array
        foreach ($nodes as $index => $node) {
            if (is_a($node, SymbolNode::class)) {
                if (is_a($node->getSymbol(), AbstractOperator::class)) {
                    $operatorNodes[$index] = $node;
                }
            }
        }

        // Using Quicksort algorithm to sort the operators according to their precedence. Keeps the indices.
        // Returning 1 means $nodeTwo before $nodeOne, returning -1 means $nodeOne before $nodeTwo.
        uasort($operatorNodes, function(SymbolNode $nodeOne, SymbolNode $nodeTwo)
        {
            // First-level precedence of node one
            /** @var AbstractOperator $symbolOne */
            $symbolOne = $nodeOne->getSymbol();
            $precedenceOne = 2;
            if ($nodeOne->isUnaryOperator()) {
                $precedenceOne = 3;
            }

            // First-level precedence of node two
            /** @var AbstractOperator $symbolTwo */
            $symbolTwo = $nodeTwo->getSymbol();
            $precedenceTwo = 2;
            if ($nodeTwo->isUnaryOperator()) {
                $precedenceTwo = 3;
            }

            // If the first-level precedence is the same, compare the second-level precedence
            if ($precedenceOne == $precedenceTwo) {
                $precedenceOne = $symbolOne->getPrecedence();
                $precedenceTwo = $symbolTwo->getPrecedence();
            }

            // If the second-level precedence is the same, we have to ensure that the sorting algorithm does
            // insert the node / token that is left in the term before the node / token that is right.
            // Therefore we cannot return 0 but compare the positions and return 1 / -1.
            if ($precedenceOne == $precedenceTwo) {
                return ($nodeOne->getToken()->getPosition() < $nodeTwo->getToken()->getPosition()) ? -1 : 1;
            }
            return ($precedenceOne < $precedenceTwo) ? 1 : -1;
        });

        return $operatorNodes;
    }
protected function detectCalculationOrder ( array $ nodes ) { $ operatorNodes = [ ] ; // Store all symbol nodes that have a symbol of type abstract operator in an array foreach ( $ nodes as $ index => $ node ) { if ( is_a ( $ node , SymbolNode :: class ) ) { if ( is_a ( $ node -> getSymbol ( ) , AbstractOperator :: class ) ) { $ operatorNodes [ $ index ] = $ node ; } } } // Using Quicksort algorithm to sort the operators according to their precedence. Keeps the indices. // Returning 1 means $nodeTwo before $nodeOne, returning -1 means $nodeOne before $nodeTwo. uasort ( $ operatorNodes , function ( SymbolNode $ nodeOne , SymbolNode $ nodeTwo ) { // First-level precedence of node one /** @var AbstractOperator $symbolOne */ $ symbolOne = $ nodeOne -> getSymbol ( ) ; $ precedenceOne = 2 ; if ( $ nodeOne -> isUnaryOperator ( ) ) { $ precedenceOne = 3 ; } // First-level precedence of node two /** @var AbstractOperator $symbolTwo */ $ symbolTwo = $ nodeTwo -> getSymbol ( ) ; $ precedenceTwo = 2 ; if ( $ nodeTwo -> isUnaryOperator ( ) ) { $ precedenceTwo = 3 ; } // If the first-level precedence is the same, compare the second-level precedence if ( $ precedenceOne == $ precedenceTwo ) { $ precedenceOne = $ symbolOne -> getPrecedence ( ) ; $ precedenceTwo = $ symbolTwo -> getPrecedence ( ) ; } // If the second-level precedence is the same, we have to ensure that the sorting algorithm does // insert the node / token that is left in the term before the node / token that is right. // Therefore we cannot return 0 but compare the positions and return 1 / -1. if ( $ precedenceOne == $ precedenceTwo ) { return ( $ nodeOne -> getToken ( ) -> getPosition ( ) < $ nodeTwo -> getToken ( ) -> getPosition ( ) ) ? - 1 : 1 ; } return ( $ precedenceOne < $ precedenceTwo ) ? 1 : - 1 ; } ) ; return $ operatorNodes ; }
Detect the calculation order of a given array of nodes.
Does only care for the precedence of operators.
Does not care for child nodes of container nodes.
Returns a new array with ordered symbol nodes.

@param AbstractNode[] $nodes
@return SymbolNode[]
Detect the calculation order of a given array of nodes . Does only care for the precedence of operators . Does not care for child nodes of container nodes . Returns a new array with ordered symbol nodes .