packages/sql-parser/src/Sqlite/Lexer/QuotedScanner.php

1<?php
2
3declare(strict_types=1);
4
5namespace SqlParser\Sqlite\Lexer;
6
7use SqlParser\Lexer\Lexeme;
8use SqlParser\Lexer\LexicalException;
9
10/**
11 * Reads SQLite's quoted tokens: strings, quoted identifiers and blob literals.
12 *
13 * Single quotes delimit strings; double quotes, backticks and brackets
14 * delimit identifiers. A quote inside doubles itself, except in brackets.
15 *
16 * @visibility root
17 */
18final class QuotedScanner
19{
20    /**
21     * Reads the quoted token at the cursor, if one starts there.
22     *
23     * @param Scan $scan The tokenization in progress
24     *
25     * @return Lexeme|null The lexeme, or null when no quoted token starts here
26     *
27     * @throws LexicalException When the token never closes or a blob is malformed
28     */
29    public function scan(Scan $scan): ?Lexeme
30    {
31        $cursor = $scan->cursor;
32        $start = $cursor->offset();
33        $character = $cursor->peek();
34        if ($character === "'" || $character === '"' || $character === '`') {
35            if ($cursor->takeQuoted($character) === null) {
36                throw LexicalException::unterminated($character === "'" ? 'string' : 'quoted identifier', $cursor->source, $start);
37            }
38
39            return $scan->lexeme($character === "'" ? 'STRING' : 'ID', $start);
40        }
41        if ($character === '[') {
42            if (!$cursor->skipPastOrEnd(']')) {
43                throw LexicalException::unterminated('bracketed identifier', $cursor->source, $start);
44            }
45
46            return $scan->lexeme('ID', $start);
47        }
48        if (($character === 'x' || $character === 'X') && $cursor->peek(1) === "'") {
49            if ($cursor->match("[xX]'(?:[0-9A-Fa-f]{2})*'") === null) {
50                throw LexicalException::unexpectedCharacter($cursor->source, $start);
51            }
52
53            return $scan->lexeme('BLOB', $start);
54        }
55
56        return null;
57    }
58}
59