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; }
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; }
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; }