protected function detectSymbols(array $tokens)
    {
        $symbolNodes = [];

        $expectingOpeningBracket = false; // True if we expect an opening bracket (after a function name)
        $openBracketCounter = 0;

        foreach ($tokens as $token) {
            $type = $token->getType();

            if ($type == Token::TYPE_WORD) {
                $identifier = $token->getValue();
                $symbol = $this->symbolContainer->find($identifier);

                if ($symbol === null) {
                    $this->throwException(
                        NotFoundException::class,
                        'Error: Detected unknown or invalid string identifier.',
                        $token->getPosition(),
                        $identifier
                    );
                }
            } elseif ($type == Token::TYPE_NUMBER) {
                // Notice: Numbers do not have an identifier
                $symbol = $this->symbolContainer->findSubtypes(Number::class)[0];
            } else { // Type Token::TYPE_CHARACTER:
                $identifier = $token->getValue();
                $symbol = $this->symbolContainer->find($identifier);

                if ($symbol === null) {
                    $this->throwException(
                        NotFoundException::class,
                        'Error: Detected unknown or invalid character identifier.',
                        $token->getPosition(),
                        $identifier
                    );
                }

                if (is_a($symbol, AbstractOpeningBracket::class)) {
                    $openBracketCounter++;
                }
                if (is_a($symbol, AbstractClosingBracket::class)) {
                    $openBracketCounter--;

                    // Make sure there are not too many closing brackets
                    if ($openBracketCounter < 0) {
                        $this->throwException(
                            ParserException::class,
                            'Error: Found closing bracket that does not have an opening bracket.',
                            $token->getPosition(),
                            $identifier
                        );
                    }
                }
            }

            // Make sure a function is not followed by a symbol that is not of type opening bracket
            if ($expectingOpeningBracket) {
                if (! is_a($symbol, AbstractOpeningBracket::class)) {
                    $this->throwException(
                        ParserException::class,
                        'Error: Expected opening bracket (after a function) but got something else.',
                        $token->getPosition(),
                        get_class($symbol)
                    );
                }

                $expectingOpeningBracket = false;
            } else {
                if (is_a($symbol, AbstractFunction::class)) {
                    $expectingOpeningBracket = true;
                }
            }

            $symbolNode = new SymbolNode($token, $symbol);

            $symbolNodes[] = $symbolNode;
        }

        // Make sure the term does not end with the name of a function but without an opening bracket
        if ($expectingOpeningBracket) {
            throw new ParserException(
                'Error: Expected opening bracket (after a function) but reached the end of the term'
            );
        }

        // Make sure there are not too many opening brackets
        if ($openBracketCounter > 0) {
            throw new ParserException(
                'Error: There is at least one opening bracket that does not have a closing bracket'
            );
        }

        return $symbolNodes;
    }
protected function detectSymbols(array $tokens)
    {
        $symbolNodes = [];

        $expectingOpeningBracket = false; // True if we expect an opening bracket (after a function name)
        $openBracketCounter = 0;

        foreach ($tokens as $token) {
            $type = $token->getType();

            if ($type == Token::TYPE_WORD) {
                $identifier = $token->getValue();
                $symbol = $this->symbolContainer->find($identifier);

                if ($symbol === null) {
                    $this->throwException(
                        NotFoundException::class,
                        'Error: Detected unknown or invalid string identifier.',
                        $token->getPosition(),
                        $identifier
                    );
                }
            } elseif ($type == Token::TYPE_NUMBER) {
                // Notice: Numbers do not have an identifier
                $symbol = $this->symbolContainer->findSubtypes(Number::class)[0];
            } else { // Type Token::TYPE_CHARACTER:
                $identifier = $token->getValue();
                $symbol = $this->symbolContainer->find($identifier);

                if ($symbol === null) {
                    $this->throwException(
                        NotFoundException::class,
                        'Error: Detected unknown or invalid character identifier.',
                        $token->getPosition(),
                        $identifier
                    );
                }

                if (is_a($symbol, AbstractOpeningBracket::class)) {
                    $openBracketCounter++;
                }
                if (is_a($symbol, AbstractClosingBracket::class)) {
                    $openBracketCounter--;

                    // Make sure there are not too many closing brackets
                    if ($openBracketCounter < 0) {
                        $this->throwException(
                            ParserException::class,
                            'Error: Found closing bracket that does not have an opening bracket.',
                            $token->getPosition(),
                            $identifier
                        );
                    }
                }
            }

            // Make sure a function is not followed by a symbol that is not of type opening bracket
            if ($expectingOpeningBracket) {
                if (! is_a($symbol, AbstractOpeningBracket::class)) {
                    $this->throwException(
                        ParserException::class,
                        'Error: Expected opening bracket (after a function) but got something else.',
                        $token->getPosition(),
                        get_class($symbol)
                    );
                }

                $expectingOpeningBracket = false;
            } else {
                if (is_a($symbol, AbstractFunction::class)) {
                    $expectingOpeningBracket = true;
                }
            }

            $symbolNode = new SymbolNode($token, $symbol);

            $symbolNodes[] = $symbolNode;
        }

        // Make sure the term does not end with the name of a function but without an opening bracket
        if ($expectingOpeningBracket) {
            throw new ParserException(
                'Error: Expected opening bracket (after a function) but reached the end of the term'
            );
        }

        // Make sure there are not too many opening brackets
        if ($openBracketCounter > 0) {
            throw new ParserException(
                'Error: There is at least one opening bracket that does not have a closing bracket'
            );
        }

        return $symbolNodes;
    }
protected function detectSymbols ( array $ tokens ) { $ symbolNodes = [ ] ; $ expectingOpeningBracket = false ; // True if we expect an opening bracket (after a function name) $ openBracketCounter = 0 ; foreach ( $ tokens as $ token ) { $ type = $ token -> getType ( ) ; if ( $ type == Token :: TYPE_WORD ) { $ identifier = $ token -> getValue ( ) ; $ symbol = $ this -> symbolContainer -> find ( $ identifier ) ; if ( $ symbol === null ) { $ this -> throwException ( NotFoundException :: class , 'Error: Detected unknown or invalid string identifier.' , $ token -> getPosition ( ) , $ identifier ) ; } } elseif ( $ type == Token :: TYPE_NUMBER ) { // Notice: Numbers do not have an identifier $ symbol = $ this -> symbolContainer -> findSubtypes ( Number :: class ) [ 0 ] ; } else { // Type Token::TYPE_CHARACTER: $ identifier = $ token -> getValue ( ) ; $ symbol = $ this -> symbolContainer -> find ( $ identifier ) ; if ( $ symbol === null ) { $ this -> throwException ( NotFoundException :: class , 'Error: Detected unknown or invalid character identifier.' , $ token -> getPosition ( ) , $ identifier ) ; } if ( is_a ( $ symbol , AbstractOpeningBracket :: class ) ) { $ openBracketCounter ++ ; } if ( is_a ( $ symbol , AbstractClosingBracket :: class ) ) { $ openBracketCounter -- ; // Make sure there are not too many closing brackets if ( $ openBracketCounter < 0 ) { $ this -> throwException ( ParserException :: class , 'Error: Found closing bracket that does not have an opening bracket.' , $ token -> getPosition ( ) , $ identifier ) ; } } } // Make sure a function is not followed by a symbol that is not of type opening bracket if ( $ expectingOpeningBracket ) { if ( ! is_a ( $ symbol , AbstractOpeningBracket :: class ) ) { $ this -> throwException ( ParserException :: class , 'Error: Expected opening bracket (after a function) but got something else.' , $ token -> getPosition ( ) , get_class ( $ symbol ) ) ; } $ expectingOpeningBracket = false ; } else { if ( is_a ( $ symbol , AbstractFunction :: class ) ) { $ expectingOpeningBracket = true ; } } $ symbolNode = new SymbolNode ( $ token , $ symbol ) ; $ symbolNodes [ ] = $ symbolNode ; } // Make sure the term does not end with the name of a function but without an opening bracket if ( $ expectingOpeningBracket ) { throw new ParserException ( 'Error: Expected opening bracket (after a function) but reached the end of the term' ) ; } // Make sure there are not too many opening brackets if ( $ openBracketCounter > 0 ) { throw new ParserException ( 'Error: There is at least one opening bracket that does not have a closing bracket' ) ; } return $ symbolNodes ; }
Creates a flat array of symbol nodes from tokens.

@param Token[] $tokens
@return SymbolNode[]
@throws NotFoundException
@throws ParserException
Creates a flat array of symbol nodes from tokens .