protected function checkGrammar(array $nodes)
    {
        // TODO Make sure that separators are only in the child nodes of the array node of a function node
        // (If this happens the calculator will throw an exception)

        foreach ($nodes as $index => $node) {
            if (is_a($node, SymbolNode::class)) {
                /** @var $node SymbolNode */

                $symbol = $node->getSymbol();

                if (is_a($symbol, AbstractOperator::class)) {
                    /** @var $symbol AbstractOperator */

                    $posOfRightOperand = $index + 1;

                    // Make sure the operator is positioned left of a (potential) operand (=prefix notation).
                    // Example term: "-1"
                    if ($posOfRightOperand >= sizeof($nodes)) {
                        $this->throwException(
                            ParserException::class,
                            'Error: Found operator that does not stand before an operand.',
                            $node->getToken()->getValue(),
                            $node->getToken()->getPosition()
                        );
                    }

                    $posOfLeftOperand = $index - 1;

                    $leftOperand = null;

                    // Operator is unary if positioned at the beginning of a term
                    if ($posOfLeftOperand >= 0) {
                        $leftOperand = $nodes[$posOfLeftOperand];

                        if (is_a($leftOperand, SymbolNode::class)) {
                            /** @var $leftOperand SymbolNode */
                            if (is_a($leftOperand->getSymbol(), AbstractOperator::class)
                                ||
                                is_a($leftOperand->getSymbol(), AbstractSeparator::class)
                            ) {
                                // Operator is unary if positioned right to another operator
                                $leftOperand = null;
                            }
                        }
                    }

                    // If null, the operator is unary
                    if ($leftOperand === null) {
                        if (! $symbol->getOperatesUnary()) {
                            $this->throwException(
                                ParserException::class,
                                'Error: Found operator in unary notation that is not unary.',
                                $node->getToken()->getValue(),
                                $node->getToken()->getPosition()
                            );
                        }

                        // Remember that this node represents a unary operator
                        $node->setIsUnaryOperator(true);
                    } else {
                        if (! $symbol->getOperatesBinary()) {
                            $this->throwException(
                                ParserException::class,
                                'Error: Found operator in binary notation that is not binary.',
                                $node->getToken()->getValue(),
                                $node->getToken()->getPosition()
                            );
                        }
                    }
                }
            } else {
                /** @var $node ContainerNode */
                $this->checkGrammar($node->getChildNodes());
            }
        }

        if ($this->customGrammarChecker !== null) {
            $customGrammarChecker = $this->customGrammarChecker;

            // Execute custom grammar checker function
            $customGrammarChecker($nodes);
        }
    }
protected function checkGrammar(array $nodes)
    {
        // TODO Make sure that separators are only in the child nodes of the array node of a function node
        // (If this happens the calculator will throw an exception)

        foreach ($nodes as $index => $node) {
            if (is_a($node, SymbolNode::class)) {
                /** @var $node SymbolNode */

                $symbol = $node->getSymbol();

                if (is_a($symbol, AbstractOperator::class)) {
                    /** @var $symbol AbstractOperator */

                    $posOfRightOperand = $index + 1;

                    // Make sure the operator is positioned left of a (potential) operand (=prefix notation).
                    // Example term: "-1"
                    if ($posOfRightOperand >= sizeof($nodes)) {
                        $this->throwException(
                            ParserException::class,
                            'Error: Found operator that does not stand before an operand.',
                            $node->getToken()->getValue(),
                            $node->getToken()->getPosition()
                        );
                    }

                    $posOfLeftOperand = $index - 1;

                    $leftOperand = null;

                    // Operator is unary if positioned at the beginning of a term
                    if ($posOfLeftOperand >= 0) {
                        $leftOperand = $nodes[$posOfLeftOperand];

                        if (is_a($leftOperand, SymbolNode::class)) {
                            /** @var $leftOperand SymbolNode */
                            if (is_a($leftOperand->getSymbol(), AbstractOperator::class)
                                ||
                                is_a($leftOperand->getSymbol(), AbstractSeparator::class)
                            ) {
                                // Operator is unary if positioned right to another operator
                                $leftOperand = null;
                            }
                        }
                    }

                    // If null, the operator is unary
                    if ($leftOperand === null) {
                        if (! $symbol->getOperatesUnary()) {
                            $this->throwException(
                                ParserException::class,
                                'Error: Found operator in unary notation that is not unary.',
                                $node->getToken()->getValue(),
                                $node->getToken()->getPosition()
                            );
                        }

                        // Remember that this node represents a unary operator
                        $node->setIsUnaryOperator(true);
                    } else {
                        if (! $symbol->getOperatesBinary()) {
                            $this->throwException(
                                ParserException::class,
                                'Error: Found operator in binary notation that is not binary.',
                                $node->getToken()->getValue(),
                                $node->getToken()->getPosition()
                            );
                        }
                    }
                }
            } else {
                /** @var $node ContainerNode */
                $this->checkGrammar($node->getChildNodes());
            }
        }

        if ($this->customGrammarChecker !== null) {
            $customGrammarChecker = $this->customGrammarChecker;

            // Execute custom grammar checker function
            $customGrammarChecker($nodes);
        }
    }
protected function checkGrammar ( array $ nodes ) { // TODO Make sure that separators are only in the child nodes of the array node of a function node // (If this happens the calculator will throw an exception) foreach ( $ nodes as $ index => $ node ) { if ( is_a ( $ node , SymbolNode :: class ) ) { /** @var $node SymbolNode */ $ symbol = $ node -> getSymbol ( ) ; if ( is_a ( $ symbol , AbstractOperator :: class ) ) { /** @var $symbol AbstractOperator */ $ posOfRightOperand = $ index + 1 ; // Make sure the operator is positioned left of a (potential) operand (=prefix notation). // Example term: "-1" if ( $ posOfRightOperand >= sizeof ( $ nodes ) ) { $ this -> throwException ( ParserException :: class , 'Error: Found operator that does not stand before an operand.' , $ node -> getToken ( ) -> getValue ( ) , $ node -> getToken ( ) -> getPosition ( ) ) ; } $ posOfLeftOperand = $ index - 1 ; $ leftOperand = null ; // Operator is unary if positioned at the beginning of a term if ( $ posOfLeftOperand >= 0 ) { $ leftOperand = $ nodes [ $ posOfLeftOperand ] ; if ( is_a ( $ leftOperand , SymbolNode :: class ) ) { /** @var $leftOperand SymbolNode */ if ( is_a ( $ leftOperand -> getSymbol ( ) , AbstractOperator :: class ) || is_a ( $ leftOperand -> getSymbol ( ) , AbstractSeparator :: class ) ) { // Operator is unary if positioned right to another operator $ leftOperand = null ; } } } // If null, the operator is unary if ( $ leftOperand === null ) { if ( ! $ symbol -> getOperatesUnary ( ) ) { $ this -> throwException ( ParserException :: class , 'Error: Found operator in unary notation that is not unary.' , $ node -> getToken ( ) -> getValue ( ) , $ node -> getToken ( ) -> getPosition ( ) ) ; } // Remember that this node represents a unary operator $ node -> setIsUnaryOperator ( true ) ; } else { if ( ! $ symbol -> getOperatesBinary ( ) ) { $ this -> throwException ( ParserException :: class , 'Error: Found operator in binary notation that is not binary.' , $ node -> getToken ( ) -> getValue ( ) , $ node -> getToken ( ) -> getPosition ( ) ) ; } } } } else { /** @var $node ContainerNode */ $ this -> checkGrammar ( $ node -> getChildNodes ( ) ) ; } } if ( $ this -> customGrammarChecker !== null ) { $ customGrammarChecker = $ this -> customGrammarChecker ; // Execute custom grammar checker function $ customGrammarChecker ( $ nodes ) ; } }
Ensures the tree follows the grammar rules for terms

@param array $nodes
@return void
@throws ParserException
Ensures the tree follows the grammar rules for terms