/** * Throw a syntax error * * @param string $expected * @throws ParserException */ private function syntaxError($expected) { $token = $this->lexer->lookahead; $tokenPosition = isset($token['position']) ? $token['position'] : '-1'; $message = sprintf('line 0, col %s: Error: Expected %s, got ', $tokenPosition, $expected); if ($this->lexer->lookahead === null) { $message .= 'end of string'; } else { $message .= $this->lexer->getLiteral($token['type']); } throw new ParserException($message); }
/** * Attempts to match the given token with the current lookahead token. * * If they match, updates the lookahead token; otherwise raises a syntax * error. * * @param int $token The token type. * * @return void * * @throws StatementException If the tokens don't match. */ public function match($token) { $lookaheadType = $this->lexer->lookahead['type']; // Short-circuit on first condition, usually types match if ($lookaheadType !== $token) { // If parameter is not identifier (1-99) must be exact match if ($token < Lexer::T_IDENTIFIER) { $this->syntaxError($this->lexer->getLiteral($token)); } // If parameter is keyword (200+) must be exact match if ($token > Lexer::T_IDENTIFIER) { $this->syntaxError($this->lexer->getLiteral($token)); } // If parameter is MATCH then FULL, PARTIAL or SIMPLE must follow if ($token === Lexer::T_MATCH && $lookaheadType !== Lexer::T_FULL && $lookaheadType !== Lexer::T_PARTIAL && $lookaheadType !== Lexer::T_SIMPLE) { $this->syntaxError($this->lexer->getLiteral($token)); } if ($token === Lexer::T_ON && $lookaheadType !== Lexer::T_DELETE && $lookaheadType !== Lexer::T_UPDATE) { $this->syntaxError($this->lexer->getLiteral($token)); } } $this->lexer->moveNext(); }