Example #1
0
 public function parsePostfixExpression($node)
 {
     $token = $this->stream->current;
     while ($token->type == Token::PUNCTUATION_TYPE) {
         if ('.' === $token->value) {
             $this->stream->next();
             $token = $this->stream->current;
             $this->stream->next();
             if ($token->type !== Token::NAME_TYPE && $token->type !== Token::NUMBER_TYPE && ($token->type !== Token::OPERATOR_TYPE && preg_match('/[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/A', $token->value))) {
                 throw new SyntaxError('Expected name or number', $token->cursor);
             }
             $arg = new Node\ConstantNode($token->value);
             $arguments = new Node\ArgumentsNode();
             if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) {
                 $type = Node\GetAttrNode::METHOD_CALL;
                 foreach ($this->parseArguments()->nodes as $n) {
                     $arguments->addElement($n);
                 }
             } else {
                 $type = Node\GetAttrNode::PROPERTY_CALL;
             }
             $node = new Node\GetAttrNode($node, $arg, $arguments, $type);
         } elseif ('[' === $token->value) {
             if ($node instanceof Node\GetAttrNode && Node\GetAttrNode::METHOD_CALL === $node->attributes['type'] && version_compare(PHP_VERSION, '5.4.0', '<')) {
                 throw new SyntaxError('Array calls on a method call is only supported on PHP 5.4+', $token->cursor);
             }
             $this->stream->next();
             $arg = $this->parseExpression();
             $this->stream->expect(Token::PUNCTUATION_TYPE, ']');
             $node = new Node\GetAttrNode($node, $arg, new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL);
         } else {
             break;
         }
         $token = $this->stream->current;
     }
     return $node;
 }
Example #2
0
 public function parsePostfixExpression($node)
 {
     $token = $this->stream->current;
     while ($token->type == Token::PUNCTUATION_TYPE) {
         if ('.' === $token->value) {
             $this->stream->next();
             $token = $this->stream->current;
             $this->stream->next();
             if ($token->type !== Token::NAME_TYPE && ($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/A', $token->value))) {
                 throw new SyntaxError('Expected name', $token->cursor);
             }
             $arg = new Node\ConstantNode($token->value);
             $arguments = new Node\ArgumentsNode();
             if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) {
                 $type = Node\GetAttrNode::METHOD_CALL;
                 foreach ($this->parseArguments()->nodes as $n) {
                     $arguments->addElement($n);
                 }
             } else {
                 $type = Node\GetAttrNode::PROPERTY_CALL;
             }
             $node = new Node\GetAttrNode($node, $arg, $arguments, $type);
         } elseif ('[' === $token->value) {
             $this->stream->next();
             $arg = $this->parseExpression();
             $this->stream->expect(Token::PUNCTUATION_TYPE, ']');
             $node = new Node\GetAttrNode($node, $arg, new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL);
         } else {
             break;
         }
         $token = $this->stream->current;
     }
     return $node;
 }
Example #3
0
    public function parsePostfixExpression($node)
    {
        $token = $this->stream->current;
        while ($token->type == Token::PUNCTUATION_TYPE) {
            if ('.' === $token->value) {
                $this->stream->next();
                $token = $this->stream->current;
                $this->stream->next();

                if (
                    $token->type !== Token::NAME_TYPE
                    &&
                    // Operators like "not" and "matches" are valid method or property names,
                    //
                    // In other words, besides NAME_TYPE, OPERATOR_TYPE could also be parsed as a property or method.
                    // This is because operators are processed by the lexer prior to names. So "not" in "foo.not()" or "matches" in "foo.matches" will be recognized as an operator first.
                    // But in fact, "not" and "matches" in such expressions shall be parsed as method or property names.
                    //
                    // And this ONLY works if the operator consists of valid characters for a property or method name.
                    //
                    // Other types, such as STRING_TYPE and NUMBER_TYPE, can't be parsed as property nor method names.
                    //
                    // As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown.
                    ($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value))
                ) {
                    throw new SyntaxError('Expected name', $token->cursor);
                }

                $arg = new Node\ConstantNode($token->value);

                $arguments = new Node\ArgumentsNode();
                if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) {
                    $type = Node\GetAttrNode::METHOD_CALL;
                    foreach ($this->parseArguments()->nodes as $n) {
                        $arguments->addElement($n);
                    }
                } else {
                    $type = Node\GetAttrNode::PROPERTY_CALL;
                }

                $node = new Node\GetAttrNode($node, $arg, $arguments, $type);
            } elseif ('[' === $token->value) {
                $this->stream->next();
                $arg = $this->parseExpression();
                $this->stream->expect(Token::PUNCTUATION_TYPE, ']');

                $node = new Node\GetAttrNode($node, $arg, new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL);
            } else {
                break;
            }

            $token = $this->stream->current;
        }

        return $node;
    }