Skip to main content

rudb_parse/
matcher.rs

1//! Walking the rule table over a token vector, producing a parse tree.
2//!
3//! This is a PEG matcher and nothing more. It decides where every rule in the grammar started and
4//! stopped, and it does not know what any of them mean. Turning the tree into an AST is the
5//! transformer's job, and keeping the two apart is what lets the grammar be vendored: a grammar
6//! bump changes the table and this file does not move.
7//!
8//! Three things about it are worth knowing before reading it.
9//!
10//! It has no Rust stack recursion. A PEG over a grammar with a thousand rules nests as deep as the
11//! query does, and `a + (b + (c + ...))` nests as deep as the user cares to type. A recursive
12//! matcher blows the thread stack on input that is merely rude rather than adversarial, and it does
13//! it with a segfault rather than an error, so the recursion is an explicit `Vec` of frames with a
14//! cap on it and the cap reports a parser error like any other.
15//!
16//! Failure does not truncate the arena. A choice that tries thirty alternatives builds and
17//! abandons tree nodes for twenty nine of them, and the obvious cleanup is to roll the arena back
18//! to where the alternative started. That is wrong here, because a memoized rule that succeeded
19//! inside a failed alternative keeps its memo entry, and the entry points at nodes in the arena. So
20//! abandoned nodes stay, unreferenced, and the arena is a bump allocator that is freed all at once.
21//! For a query that parses, the waste is small; for one that does not, it does not matter.
22//!
23//! The FIRST filter is a superset test and only its negative answer is used. `Statement` is a
24//! choice of thirty six alternatives and upstream descends into each one far enough to fail. Here
25//! an alternative whose FIRST set does not contain the token in hand is skipped on one AND. A
26//! nullable node is never skipped, because it can match without looking at the token at all, which
27//! is why the guard reads `NULLABLE` before it reads `FIRST`.
28//!
29//! `spec/20-the-grammar.md` sections 3, 5 and 6.
30
31use rudb_common::{Error, Result};
32
33use crate::generated::keywords::{KEYWORDS, UNRESERVED};
34use crate::generated::rules::{CHILDREN, FIRST, NODES, NULLABLE, PROGRAM, RULES, SYMBOLS};
35use crate::rules::{Node, Op, Suggestion};
36use crate::token::{Flags, Kind, Token};
37use crate::tokenize::tokenize;
38
39/// No node.
40///
41/// `u32::MAX` rather than an `Option<u32>`, so that a `ParseNode` is twenty bytes and a tree of a
42/// hundred thousand nodes is two megabytes rather than four.
43pub const NONE: u32 = u32::MAX;
44
45/// How deep the frame stack may go before the parse is called a runaway.
46///
47/// Two hundred and sixty two thousand frames is far past anything a person writes and far short of
48/// anything that takes noticeable time or memory to reach. It exists because a PEG has no other
49/// bound: `(((((...)))))` nests one frame per paren and the grammar is happy to keep going. The
50/// number is a power of two for no reason other than that a round one invites being tuned.
51const MAX_DEPTH: usize = 262_144;
52
53/// An empty memo slot, meaning this rule has not been tried at this position.
54const MEMO_EMPTY: u32 = u32::MAX;
55/// A memo slot holding a failure, meaning this rule was tried here and did not match.
56const MEMO_FAILED: u32 = u32::MAX - 1;
57
58/// One node of the parse tree. Twenty bytes.
59///
60/// Children are a linked list rather than a slice, because a node's children are discovered one at
61/// a time and interleaved with the children of every other node being built at the same moment, so
62/// a contiguous list would need either a second pass or a per node vector. The list is built in
63/// order and read in order, which is the only access pattern the transformer has.
64///
65/// Terminals get no node. A keyword, a symbol and a literal are all recoverable from the token
66/// span of the rule that contains them, and giving each one a node would roughly triple the tree
67/// for information that is already in the token vector.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub struct ParseNode {
70    /// Which rule this is, as an index into `RULES`.
71    pub rule: u32,
72    /// The first token it covers.
73    pub start: u32,
74    /// One past the last token it covers.
75    pub end: u32,
76    /// Its first child, or `NONE`.
77    pub first_child: u32,
78    /// The next child of this node's parent, or `NONE`.
79    pub next_sibling: u32,
80}
81
82/// A parsed query.
83#[derive(Debug, Clone)]
84pub struct Tree {
85    nodes: Vec<ParseNode>,
86    root: u32,
87    steps: u64,
88}
89
90impl Tree {
91    /// The root node, which is the rule the parse was started from.
92    pub fn root(&self) -> u32 {
93        self.root
94    }
95
96    /// How many nodes the tree has, abandoned ones included.
97    ///
98    /// Not the size of the tree that is reachable from the root. It is the size of the arena, which
99    /// is what the parse cost, and telling the two apart is what the ratio between them is for.
100    pub fn arena_len(&self) -> usize {
101        self.nodes.len()
102    }
103
104    /// How many nodes of the rule table the matcher went into to produce this.
105    ///
106    /// The one number that says what a parse cost, and the one to watch when the grammar or the
107    /// filter changes. A parse that is linear in the query does a roughly constant number of these
108    /// per token; one that is backtracking badly does thousands.
109    pub fn steps(&self) -> u64 {
110        self.steps
111    }
112
113    /// One node.
114    pub fn node(&self, index: u32) -> ParseNode {
115        self.nodes[index as usize]
116    }
117
118    /// The name of the rule a node is.
119    pub fn name(&self, index: u32) -> &'static str {
120        RULES[self.node(index).rule as usize].name
121    }
122
123    /// The children of a node, in order.
124    pub fn children(&self, index: u32) -> Children<'_> {
125        Children { tree: self, next: self.node(index).first_child }
126    }
127
128    /// The text a node covers, given the query and its tokens.
129    ///
130    /// A node that covers no tokens, which is any rule whose body matched nothing, gets the empty
131    /// string at the point it started rather than a span running backwards.
132    pub fn text<'a>(&self, index: u32, query: &'a str, tokens: &[Token]) -> &'a str {
133        let node = self.node(index);
134        if node.end <= node.start {
135            let at = tokens.get(node.start as usize).map_or(query.len(), |t| t.start as usize);
136            return &query[at..at];
137        }
138        let start = tokens[node.start as usize].start as usize;
139        let end = tokens[node.end as usize - 1].end as usize;
140        &query[start..end]
141    }
142}
143
144/// The children of one node.
145#[derive(Debug)]
146pub struct Children<'a> {
147    tree: &'a Tree,
148    next: u32,
149}
150
151impl Iterator for Children<'_> {
152    type Item = u32;
153
154    fn next(&mut self) -> Option<u32> {
155        if self.next == NONE {
156            return None;
157        }
158        let current = self.next;
159        self.next = self.tree.node(current).next_sibling;
160        Some(current)
161    }
162}
163
164/// Parse a whole script.
165pub fn parse(query: &str) -> Result<Tree> {
166    let tokens = tokenize(query)?;
167    parse_tokens(query, &tokens, PROGRAM, true)
168}
169
170/// Parse from a named rule, for tests and for the differential harness.
171///
172/// `filter` off runs the same walk with the FIRST filter disabled, which is how the harness checks
173/// that the filter is the superset it claims to be: the two modes have to accept the same queries
174/// and build the same trees, and if they ever do not, the filter is wrong and not the grammar.
175pub fn parse_from(query: &str, rule_name: &str, filter: bool) -> Result<Tree> {
176    let index = RULES
177        .binary_search_by(|candidate| candidate.name.cmp(rule_name))
178        .map_err(|_| Error::parser(format!("no rule named {rule_name}")))?;
179    let tokens = tokenize(query)?;
180    parse_tokens(query, &tokens, index as u32, filter)
181}
182
183/// Parse tokens that have already been produced.
184pub fn parse_tokens(query: &str, tokens: &[Token], root: u32, filter: bool) -> Result<Tree> {
185    Matcher::new(query, tokens, filter).run(root)
186}
187
188/// Which frame this is, decided once when it is pushed rather than read back off the node.
189///
190/// The five composite ops are the five kinds of frame. Terminals never get one, because they match
191/// or they do not and there is nothing to come back to.
192#[derive(Debug, Clone, Copy, PartialEq, Eq)]
193enum FrameOp {
194    Rule,
195    Sequence,
196    Choice,
197    Optional,
198    Repeat,
199}
200
201/// One suspended node.
202///
203/// `a` and `b` mean what they mean on the node this came from: the rule index for a rule, the child
204/// node for an optional or a repeat, and the start and length of the child list for a sequence or a
205/// choice. Copying them in is what keeps the loop from touching `NODES` on the way back up.
206#[derive(Debug, Clone, Copy)]
207struct Frame {
208    op: FrameOp,
209    a: u32,
210    b: u32,
211    /// Where the token position was on entry, which is where a failure puts it back.
212    start: u32,
213    /// Which child a sequence or a choice is on, or how many times a repeat has gone round.
214    step: u32,
215    /// Where a repeat's last successful iteration ended.
216    mark: u32,
217    /// The children collected so far, as a list.
218    head: u32,
219    tail: u32,
220}
221
222/// What the loop does next.
223enum Action {
224    /// Go into this node.
225    Enter(u32),
226    /// The thing that just ran matched, and contributed this list of children.
227    Succeed(u32, u32),
228    /// The thing that just ran did not match.
229    Fail,
230    /// The stack is empty. `Some` is the root's node, `None` is a parse that failed.
231    Done(Option<u32>),
232}
233
234struct Matcher<'a> {
235    query: &'a str,
236    tokens: &'a [Token],
237    /// One FIRST key per token, computed once. The filter asks for the key of the token at the
238    /// current position on every node it enters, and the same token is entered on many times.
239    keys: Vec<u64>,
240    arena: Vec<ParseNode>,
241    stack: Vec<Frame>,
242    /// One slot per memoized rule per token position, holding an arena index, `MEMO_FAILED` or
243    /// `MEMO_EMPTY`. A flat array rather than a map: twenty two rules against the token count is a
244    /// few tens of kilobytes for a normal query, and the lookup is an index rather than a hash.
245    memo: Vec<u32>,
246    /// Which memo row a rule uses, or `NONE`.
247    slot_of: &'static [u32],
248    filter: bool,
249    pos: u32,
250    /// How many nodes have been entered. Diagnostic only, and free next to the work it counts.
251    steps: u64,
252    /// The furthest token any terminal was tried at, which is where the error goes. The furthest
253    /// failure is what a person reads as the place the query went wrong, and the place the matcher
254    /// finally gives up is usually the start of the statement.
255    furthest: u32,
256}
257
258/// The memo row each rule uses, built once for the process.
259///
260/// Twenty two rules memoize, out of one thousand and eighty eight, so a row per rule would be a
261/// table forty nine times bigger than it needs to be and the memo is sized per token on top of
262/// that.
263fn slots() -> &'static (Box<[u32]>, usize) {
264    use std::sync::OnceLock;
265    static SLOTS: OnceLock<(Box<[u32]>, usize)> = OnceLock::new();
266    SLOTS.get_or_init(build_slots)
267}
268
269fn build_slots() -> (Box<[u32]>, usize) {
270    let mut slots = vec![NONE; RULES.len()];
271    let mut next = 0;
272    for (index, rule) in RULES.iter().enumerate() {
273        if rule.memoized {
274            slots[index] = next;
275            next += 1;
276        }
277    }
278    (slots.into_boxed_slice(), next as usize)
279}
280
281impl<'a> Matcher<'a> {
282    fn new(query: &'a str, tokens: &'a [Token], filter: bool) -> Self {
283        let keys = tokens.iter().map(|token| crate::rules::token_key(*token)).collect();
284        // One row per memoized rule, one column per token plus one for the position past the end.
285        let memo = vec![MEMO_EMPTY; slots().1 * (tokens.len() + 1)];
286        Self {
287            query,
288            tokens,
289            keys,
290            // The arena grows as the tree does. A guess here saves a handful of reallocations on
291            // anything but the smallest query, and a token is worth about a node in practice.
292            arena: Vec::with_capacity(tokens.len()),
293            stack: Vec::with_capacity(64),
294            memo,
295            slot_of: &slots().0,
296            filter,
297            pos: 0,
298            steps: 0,
299            furthest: 0,
300        }
301    }
302
303    fn run(mut self, root: u32) -> Result<Tree> {
304        self.push(Frame {
305            op: FrameOp::Rule,
306            a: root,
307            b: 0,
308            start: 0,
309            step: 0,
310            mark: 0,
311            head: NONE,
312            tail: NONE,
313        })?;
314
315        let mut action = Action::Enter(RULES[root as usize].root);
316        let node = loop {
317            action = match action {
318                Action::Enter(node) => self.enter(node)?,
319                Action::Succeed(head, tail) => self.settle_ok(head, tail),
320                Action::Fail => self.settle_fail(),
321                Action::Done(result) => match result {
322                    Some(node) => break node,
323                    None => return Err(self.syntax_error(self.furthest)),
324                },
325            };
326        };
327
328        // Everything has to be consumed. `Program <- TopLevelStatement*` stops at the first token
329        // it cannot start a statement with and calls that a successful parse of the part it read,
330        // so without this `SELECT 1 rubbish here` parses as `SELECT 1` and the rest is silently
331        // dropped. The token vector always ends with an end of input token, so a parse that
332        // reached the end is at `len`, and one that stopped short is pointing at the offender.
333        if (self.pos as usize) < self.tokens.len()
334            && self.tokens[self.pos as usize].kind != Kind::EndOfInput
335        {
336            return Err(self.syntax_error(self.pos.max(self.furthest)));
337        }
338
339        Ok(Tree { nodes: self.arena, root: node, steps: self.steps })
340    }
341
342    /// The token at a position, or the end of input past the end.
343    ///
344    /// Only the FIRST filter asks past the end. The terminals all check the bound themselves,
345    /// because `EndOfInputMatcher` advancing over a synthetic token would let
346    /// `TopLevelStatement <- Statement? (';'+ / EndOfInput)` match forever at the end of a script.
347    fn token(&self, pos: u32) -> Token {
348        self.tokens.get(pos as usize).copied().unwrap_or(Token {
349            kind: Kind::EndOfInput,
350            flags: Flags::default(),
351            keyword: crate::token::NOT_A_KEYWORD,
352            start: self.query.len() as u32,
353            end: self.query.len() as u32,
354        })
355    }
356
357    fn key(&self, pos: u32) -> u64 {
358        self.keys.get(pos as usize).copied().unwrap_or(crate::rules::FIRST_END)
359    }
360
361    fn push(&mut self, frame: Frame) -> Result<()> {
362        if self.stack.len() >= MAX_DEPTH {
363            let token = self.token(self.pos);
364            return Err(Error::parser(format!(
365                "memory exhausted at or near \"{}\"",
366                token.text(self.query)
367            ))
368            .with_span(token.span()));
369        }
370        self.stack.push(frame);
371        Ok(())
372    }
373
374    fn alloc(&mut self, node: ParseNode) -> u32 {
375        self.arena.push(node);
376        (self.arena.len() - 1) as u32
377    }
378
379    /// Record that something was tried here, for the error message.
380    fn reached(&mut self, pos: u32) {
381        if pos > self.furthest {
382            self.furthest = pos;
383        }
384    }
385
386    fn syntax_error(&self, pos: u32) -> Error {
387        let token = self.token(pos);
388        if token.kind == Kind::EndOfInput {
389            return Error::parser("syntax error at end of input").with_span(token.span());
390        }
391        Error::parser(format!("syntax error at or near \"{}\"", token.text(self.query)))
392            .with_span(token.span())
393    }
394
395    /// Handle one node.
396    fn enter(&mut self, index: u32) -> Result<Action> {
397        self.steps += 1;
398        // The superset test, and only its no. A nullable node can match without reading a token at
399        // all, so its FIRST set says nothing about whether it applies and asking would reject the
400        // empty match that is the whole point of it.
401        if self.filter
402            && !NULLABLE[index as usize]
403            && FIRST[index as usize] & self.key(self.pos) == 0
404        {
405            self.reached(self.pos);
406            return Ok(Action::Fail);
407        }
408
409        let node = NODES[index as usize];
410        match node.op {
411            Op::Rule => self.enter_rule(node.a),
412            Op::Sequence => {
413                self.push(self.frame(FrameOp::Sequence, node.a, node.b))?;
414                Ok(Action::Enter(CHILDREN[node.a as usize]))
415            }
416            Op::Choice => {
417                self.push(self.frame(FrameOp::Choice, node.a, node.b))?;
418                Ok(Action::Enter(CHILDREN[node.a as usize]))
419            }
420            Op::Optional => {
421                self.push(self.frame(FrameOp::Optional, node.a, 0))?;
422                Ok(Action::Enter(node.a))
423            }
424            Op::Repeat => {
425                self.push(self.frame(FrameOp::Repeat, node.a, 0))?;
426                Ok(Action::Enter(node.a))
427            }
428            _ => Ok(self.terminal(node)),
429        }
430    }
431
432    fn frame(&self, op: FrameOp, a: u32, b: u32) -> Frame {
433        Frame { op, a, b, start: self.pos, step: 0, mark: self.pos, head: NONE, tail: NONE }
434    }
435
436    /// A reference to a rule, which is the only thing that makes a tree node.
437    fn enter_rule(&mut self, rule: u32) -> Result<Action> {
438        let slot = self.slot_of[rule as usize];
439        if slot != NONE {
440            match self.memo[self.memo_index(slot)] {
441                MEMO_EMPTY => {}
442                MEMO_FAILED => return Ok(Action::Fail),
443                stored => {
444                    // The stored node is shared by every parent that adopts it, and `next_sibling`
445                    // is written by whichever one that is, so the node itself is copied and only
446                    // its children are shared. The children are safe to share because nothing ever
447                    // rewrites a link inside a finished list, only the link out of its head.
448                    let source = self.arena[stored as usize];
449                    self.pos = source.end;
450                    let copy = self.alloc(ParseNode { next_sibling: NONE, ..source });
451                    return Ok(Action::Succeed(copy, copy));
452                }
453            }
454        }
455        self.push(self.frame(FrameOp::Rule, rule, 0))?;
456        Ok(Action::Enter(RULES[rule as usize].root))
457    }
458
459    fn memo_index(&self, slot: u32) -> usize {
460        slot as usize * (self.tokens.len() + 1) + self.pos as usize
461    }
462
463    /// Something matched. Give its children to the frame above and decide what that frame does now.
464    fn settle_ok(&mut self, head: u32, tail: u32) -> Action {
465        // Popped rather than looked at, and pushed back by the two cases that carry on. A frame is
466        // thirty two bytes of `Copy`, so this is a couple of moves, and the alternative is holding
467        // a mutable borrow of the stack across every write to the arena.
468        let Some(mut frame) = self.stack.pop() else {
469            return Action::Done(Some(head));
470        };
471
472        if head != NONE {
473            if frame.head == NONE {
474                frame.head = head;
475            } else {
476                self.arena[frame.tail as usize].next_sibling = head;
477            }
478            frame.tail = tail;
479        }
480
481        match frame.op {
482            FrameOp::Rule => {
483                let node = self.alloc(ParseNode {
484                    rule: frame.a,
485                    start: frame.start,
486                    end: self.pos,
487                    first_child: frame.head,
488                    next_sibling: NONE,
489                });
490                self.remember(frame.a, frame.start, node);
491                Action::Succeed(node, node)
492            }
493            FrameOp::Sequence => {
494                frame.step += 1;
495                if frame.step == frame.b {
496                    Action::Succeed(frame.head, frame.tail)
497                } else {
498                    let next = CHILDREN[(frame.a + frame.step) as usize];
499                    self.stack.push(frame);
500                    Action::Enter(next)
501                }
502            }
503            FrameOp::Choice | FrameOp::Optional => Action::Succeed(frame.head, frame.tail),
504            FrameOp::Repeat => {
505                // A repeat wraps something that cannot match nothing, which the generator checks
506                // and `a_repeat_never_wraps_something_that_matches_nothing` asserts, so this always
507                // moves. The guard is here because the alternative to a wrong answer would be a
508                // hang, and a hang in a parser is the failure nobody can diagnose from a bug
509                // report.
510                debug_assert!(self.pos != frame.mark, "a repeat went round without consuming");
511                if self.pos == frame.mark {
512                    return Action::Succeed(frame.head, frame.tail);
513                }
514                frame.mark = self.pos;
515                frame.step += 1;
516                let child = frame.a;
517                self.stack.push(frame);
518                Action::Enter(child)
519            }
520        }
521    }
522
523    /// Something did not match. Put the position back and decide what the frame above does now.
524    fn settle_fail(&mut self) -> Action {
525        let Some(mut frame) = self.stack.pop() else {
526            return Action::Done(None);
527        };
528
529        match frame.op {
530            FrameOp::Rule => {
531                self.pos = frame.start;
532                // A failure is worth remembering for the same reason a success is. The rules that
533                // memoize are the ones an expression re-enters at the same position from every
534                // alternative in turn, and most of those re-entries fail.
535                self.remember(frame.a, frame.start, MEMO_FAILED);
536                Action::Fail
537            }
538            FrameOp::Sequence => {
539                self.pos = frame.start;
540                Action::Fail
541            }
542            FrameOp::Choice => {
543                frame.step += 1;
544                self.pos = frame.start;
545                if frame.step == frame.b {
546                    Action::Fail
547                } else {
548                    // The children of a failed alternative are dropped by not being spliced. The
549                    // nodes stay in the arena, unreferenced, which is the trade this file's header
550                    // is about.
551                    frame.head = NONE;
552                    frame.tail = NONE;
553                    let next = CHILDREN[(frame.a + frame.step) as usize];
554                    self.stack.push(frame);
555                    Action::Enter(next)
556                }
557            }
558            FrameOp::Optional => {
559                self.pos = frame.start;
560                Action::Succeed(NONE, NONE)
561            }
562            FrameOp::Repeat => {
563                self.pos = frame.mark;
564                if frame.step == 0 { Action::Fail } else { Action::Succeed(frame.head, frame.tail) }
565            }
566        }
567    }
568
569    /// Write a memo entry, if this rule is one of the twenty two that get one.
570    fn remember(&mut self, rule: u32, start: u32, entry: u32) {
571        let slot = self.slot_of[rule as usize];
572        if slot != NONE {
573            let index = slot as usize * (self.tokens.len() + 1) + start as usize;
574            self.memo[index] = entry;
575        }
576    }
577
578    /// A node that matches tokens directly, or does not.
579    fn terminal(&mut self, node: Node) -> Action {
580        self.reached(self.pos);
581        if self.pos as usize >= self.tokens.len() {
582            return Action::Fail;
583        }
584        let token = self.tokens[self.pos as usize];
585        let matched = match node.op {
586            // An index compare, not a text compare. The tokenizer already folded the word and
587            // looked it up, and everything that is not a word carries `NOT_A_KEYWORD`, which is
588            // larger than any index, so the compare rejects them without asking what they are.
589            Op::Keyword => u32::from(token.keyword) == node.a,
590            Op::KeywordClass => {
591                token.kind == Kind::Keyword && u32::from(class_of(token)) & node.a != 0
592            }
593            // A text compare and nothing else, which is upstream's, and it matters. A `.` between
594            // two names arrives as a number token, because the tokenizer cannot tell `a.b` from
595            // `.5` until it has read past the dot, so a check that the token is an operator would
596            // make `DottedIdentifier` unmatchable. Nothing is lost by dropping it: every symbol is
597            // punctuation, no word or literal has punctuation for its whole text, and a quoted or
598            // string token carries its quotes in its text and so cannot collide either.
599            Op::Symbol => token.text(self.query) == SYMBOLS[node.a as usize],
600            // The other half of the same fact. Upstream rejects a lone dot here, and this is why:
601            // without it `a.b` would parse `.` as a numeric literal and `SELECT a.b` would come
602            // out as three expressions rather than one qualified name.
603            Op::Number => token.kind == Kind::Number && token.text(self.query) != ".",
604            Op::Operator => {
605                token.kind == Kind::Operator && is_bare_operator(token.text(self.query))
606            }
607            Op::EndOfInput => token.kind == Kind::EndOfInput,
608            Op::String => return self.string(token),
609            Op::Identifier => self.identifier(token, node),
610            other => unreachable!("{other:?} is a composite and never reaches here"),
611        };
612        if matched {
613            self.pos += 1;
614            Action::Succeed(NONE, NONE)
615        } else {
616            Action::Fail
617        }
618    }
619
620    /// A string literal and the literals that continue it.
621    ///
622    /// `'a'` on one line and `'b'` on the next is one string in SQL, and the rule for when it is
623    /// comes from PostgreSQL: the pieces have to be plain single quoted literals, there has to be a
624    /// line break between them, and a block comment in the gap stops the run. `'a' 'b'` on one line
625    /// is not a continuation and neither is `E'a'` followed by anything, so a prefixed or dollar
626    /// quoted literal matches alone.
627    fn string(&mut self, token: Token) -> Action {
628        if token.kind != Kind::String {
629            return Action::Fail;
630        }
631        self.pos += 1;
632        if !is_plain_string(token.text(self.query)) {
633            return Action::Succeed(NONE, NONE);
634        }
635        while let Some(next) = self.tokens.get(self.pos as usize) {
636            if next.kind != Kind::String
637                || !next.flags.has(Flags::NEWLINE)
638                || next.flags.has(Flags::BLOCK_COMMENT)
639                || !is_plain_string(next.text(self.query))
640            {
641                break;
642            }
643            self.pos += 1;
644        }
645        Action::Succeed(NONE, NONE)
646    }
647
648    /// A name, in whichever of the eleven positions the grammar is at.
649    ///
650    /// Two questions, in upstream's order. Is this the shape of a name at all, and if it is a
651    /// keyword, is this a position that lets that keyword through. The second is where the keyword
652    /// classes earn their existence: `SELECT * FROM binary` is an error and `SELECT binary(x)` is
653    /// not, and the only difference between them is which suggestion the matcher was built with.
654    fn identifier(&mut self, token: Token, node: Node) -> bool {
655        let suggestion = SUGGESTIONS[node.a as usize];
656        let shaped = match token.kind {
657            Kind::QuotedIdentifier => true,
658            Kind::Identifier | Kind::Keyword => true,
659            // `FROM 'file.parquet'` and `COPY t TO 'out.csv'`, and nowhere else. Anywhere else a
660            // single quoted string has to stay a string, or `SELECT 'x' FROM t` becomes a column.
661            Kind::String => {
662                suggestion.supports_string_literal() && is_plain_string(token.text(self.query))
663            }
664            _ => false,
665        };
666        if !shaped {
667            return false;
668        }
669        // The whole of `ReservedIdentifierMatcher`, which is what the rule named `ReservedKeyword`
670        // is overridden with. It skips the class check entirely, so it takes any word at all rather
671        // than the seventy five reserved ones. See `Node::RESERVED`.
672        if node.flags & Node::RESERVED != 0 {
673            return true;
674        }
675        if token.kind != Kind::Keyword {
676            return true;
677        }
678        let class = class_of(token);
679        class & UNRESERVED != 0 || class & suggestion.allowed_class() != 0
680    }
681}
682
683/// Which classes a token's word is in.
684fn class_of(token: Token) -> u8 {
685    KEYWORDS[token.keyword as usize].1
686}
687
688/// Whether a string literal is the plain single quoted kind.
689///
690/// Prefixed forms (`E'a'`, `x'ff'`) and dollar quoting start with something else, and the two
691/// places this is asked both care about the same distinction.
692fn is_plain_string(text: &str) -> bool {
693    text.starts_with('\'')
694}
695
696/// The characters `OperatorMatcher` will accept a token made entirely of.
697const OPERATOR_CHARACTERS: &[u8] = b"+-*/%^<>=~!@&|";
698
699/// The tokens that look like operators and are not, because the grammar spells them itself.
700///
701/// Upstream lists these out in `OperatorMatcher` and the reason is the same for all of them: a rule
702/// somewhere writes the token as a literal and means something specific by it, so letting the
703/// generic operator node take it first would make that rule unreachable. `->` is JSON extraction,
704/// the comparisons are comparisons, and the tilde family is the pattern matching operators.
705const NOT_OPERATORS: [&str; 15] = [
706    "->", "->>", "<=", ">=", "!=", "==", "<>", "~~", "~~*", "~~~", "~*", "!~~", "!~~*", "!~", "!~*",
707];
708
709/// Whether this text is an operator in the sense the `Operator` node means.
710///
711/// A single character is never one, which is not an oversight: every single character operator in
712/// the language is spelled by a rule, so the generic node is only ever for the multi character ones
713/// a user might define.
714fn is_bare_operator(text: &str) -> bool {
715    if text.len() < 2 || NOT_OPERATORS.contains(&text) {
716        return false;
717    }
718    text.bytes().all(|byte| OPERATOR_CHARACTERS.contains(&byte))
719}
720
721/// The eleven suggestions by discriminant, so that a node's `a` can be turned back into one.
722///
723/// A table rather than a `match`, because the discriminants are dense and written by the generator
724/// and the table is checked against them by `the_suggestions_are_dense_and_in_order`.
725const SUGGESTIONS: [Suggestion; 11] = [
726    Suggestion::Variable,
727    Suggestion::CatalogName,
728    Suggestion::SchemaName,
729    Suggestion::TableName,
730    Suggestion::ColumnName,
731    Suggestion::ScalarFunctionName,
732    Suggestion::TableFunctionName,
733    Suggestion::TypeName,
734    Suggestion::PragmaName,
735    Suggestion::SettingName,
736    Suggestion::FileName,
737];
738
739#[cfg(test)]
740mod tests {
741    use super::{
742        NONE, SUGGESTIONS, Tree, is_bare_operator, is_plain_string, parse, parse_from, parse_tokens,
743    };
744    use crate::corpus::CORPUS;
745    use crate::generated::rules::PROGRAM;
746    use crate::tokenize::tokenize;
747
748    /// The rules a tree has, outermost first, for asserting on shape without writing out the whole
749    /// thing.
750    fn names(tree: &Tree, node: u32, into: &mut Vec<&'static str>) {
751        into.push(tree.name(node));
752        for child in tree.children(node) {
753            names(tree, child, into);
754        }
755    }
756
757    /// The first node with this rule name, depth first.
758    fn find(tree: &Tree, node: u32, name: &str) -> Option<u32> {
759        if tree.name(node) == name {
760            return Some(node);
761        }
762        tree.children(node).find_map(|child| find(tree, child, name))
763    }
764
765    fn shape(query: &str) -> Vec<&'static str> {
766        let tree = parse(query).expect("parses");
767        let mut out = Vec::new();
768        names(&tree, tree.root(), &mut out);
769        out
770    }
771
772    #[test]
773    fn the_suggestions_are_dense_and_in_order() {
774        for (index, suggestion) in SUGGESTIONS.iter().enumerate() {
775            assert_eq!(*suggestion as usize, index);
776        }
777    }
778
779    #[test]
780    fn an_empty_script_parses() {
781        let tree = parse("").expect("an empty script is a script with no statements");
782        assert_eq!(tree.name(tree.root()), "Program");
783    }
784
785    #[test]
786    fn a_select_parses_and_the_root_is_the_program() {
787        let tree = parse("SELECT 1").expect("parses");
788        assert_eq!(tree.name(tree.root()), "Program");
789        let statements: Vec<_> = tree.children(tree.root()).collect();
790        assert_eq!(statements.len(), 1);
791        assert_eq!(tree.name(statements[0]), "TopLevelStatement");
792    }
793
794    #[test]
795    fn the_shape_has_the_rules_the_grammar_names() {
796        let shape = shape("SELECT 1");
797        assert!(shape.contains(&"SelectStatement"), "{shape:?}");
798    }
799
800    #[test]
801    fn a_statement_covers_the_text_it_came_from() {
802        let query = "  SELECT 1  ";
803        let tokens = tokenize(query).expect("tokenizes");
804        let tree = parse_tokens(query, &tokens, PROGRAM, true).expect("parses");
805        // The statement and not the `TopLevelStatement` that wraps it. `TopLevelStatement` covers
806        // the terminator too, and at the end of a script the terminator is the end of input token,
807        // whose span is the end of the query, so its text runs out to the trailing whitespace.
808        let statement = find(&tree, tree.root(), "SelectStatement").expect("there is one");
809        assert_eq!(tree.text(statement, query, &tokens), "SELECT 1");
810    }
811
812    #[test]
813    fn several_statements_parse_as_several() {
814        let tree = parse("SELECT 1; SELECT 2; SELECT 3").expect("parses");
815        let shape = shape("SELECT 1; SELECT 2; SELECT 3");
816        assert_eq!(shape.iter().filter(|name| **name == "SelectStatement").count(), 3);
817        assert!(tree.children(tree.root()).count() >= 3);
818    }
819
820    #[test]
821    fn a_trailing_semicolon_makes_an_empty_statement() {
822        // Not a bug and not worth working around here. `TopLevelStatement <- Statement? (';'+ /
823        // EndOfInput)` has both halves optional in effect, so at the end of `SELECT 1;` the
824        // repetition goes round once more, matches no statement and the end of input, and stops.
825        // The extra node has an `EndOfInput` child and no `Statement` one, which is how the
826        // transformer tells it apart, and upstream drops it in the same place for the same reason.
827        let one = parse("SELECT 1").expect("parses");
828        let two = parse("SELECT 1;").expect("parses");
829        assert_eq!(one.children(one.root()).count(), 1);
830        assert_eq!(two.children(two.root()).count(), 2);
831        let last = two.children(two.root()).last().expect("there is a last one");
832        let inside: Vec<_> = two.children(last).map(|child| two.name(child)).collect();
833        assert_eq!(inside, ["EndOfInput"], "the extra one holds no statement");
834    }
835
836    #[test]
837    fn rubbish_after_a_statement_is_an_error() {
838        // Without the consumed-everything check this parses as `SELECT 1` and drops the rest,
839        // because `Program <- TopLevelStatement*` is allowed to stop early.
840        let error = parse("SELECT 1 rubbish here").expect_err("not a query");
841        assert!(error.message().starts_with("syntax error at or near"), "{}", error.message());
842    }
843
844    #[test]
845    fn a_word_that_is_not_a_statement_is_an_error() {
846        let error = parse("SELCT 1").expect_err("not a query");
847        assert!(error.message().contains("syntax error"), "{}", error.message());
848    }
849
850    #[test]
851    fn the_error_points_at_the_furthest_token_reached() {
852        // The parse gives up at the start of the statement, having tried every alternative. The
853        // place worth reporting is the furthest one any of them got to, which is the `from`.
854        let error = parse("SELECT 1 FROM").expect_err("not a query");
855        assert!(error.span().is_some(), "an error about a place should say which place");
856    }
857
858    #[test]
859    fn a_soft_keyword_is_a_column_name_and_also_a_keyword() {
860        // `ascending` is spelled by a rule and is in no class, so it is both of these and the
861        // FIRST set for the literal has to be the identifier bit rather than a keyword bucket.
862        parse("SELECT ascending FROM t").expect("a soft word is a name");
863        parse("SELECT x FROM t ORDER BY x ASCENDING").expect("a soft word is also a literal");
864    }
865
866    #[test]
867    fn a_reserved_word_is_not_a_column_name() {
868        parse("SELECT x FROM t").expect("an ordinary name is fine");
869        parse("SELECT * FROM t WHERE all").expect_err("`all` is reserved");
870    }
871
872    #[test]
873    fn an_unreserved_word_is_a_column_name_everywhere() {
874        parse("SELECT abort FROM t").expect("`abort` is unreserved");
875    }
876
877    #[test]
878    fn a_function_name_keyword_is_a_function_and_not_a_column() {
879        // The whole point of the classes. `binary` is in the function name class and nowhere else,
880        // so the two positions disagree about it.
881        parse("SELECT binary(x) FROM t").expect("a function name position takes it");
882        parse("SELECT binary FROM t").expect_err("a column name position does not");
883    }
884
885    #[test]
886    fn a_quoted_name_is_a_name_whatever_it_spells() {
887        parse(r#"SELECT "all" FROM t"#).expect("quoting takes a word out of every class");
888    }
889
890    #[test]
891    fn adjacent_strings_across_a_line_are_one_literal() {
892        parse("SELECT 'a'\n'b'").expect("a continuation");
893        parse("SELECT 'a' 'b'").expect_err("on one line they are two strings and a syntax error");
894    }
895
896    #[test]
897    fn deep_nesting_is_an_error_and_not_a_crash() {
898        // A thread stack would be gone long before this. The number is well past the cap.
899        let query = format!("SELECT {}1{}", "(".repeat(200_000), ")".repeat(200_000));
900        let error = parse(&query).expect_err("too deep to parse");
901        assert!(error.message().contains("memory exhausted"), "{}", error.message());
902    }
903
904    #[test]
905    fn nesting_that_is_merely_rude_still_parses() {
906        let query = format!("SELECT {}1{}", "(".repeat(500), ")".repeat(500));
907        parse(&query).expect("five hundred deep is fine");
908    }
909
910    #[test]
911    fn a_named_rule_can_be_parsed_on_its_own() {
912        let tree = parse_from("SELECT 1", "SelectStatement", true).expect("parses");
913        assert_eq!(tree.name(tree.root()), "SelectStatement");
914    }
915
916    #[test]
917    fn asking_for_a_rule_that_does_not_exist_says_so() {
918        let error = parse_from("SELECT 1", "NoSuchRule", true).expect_err("no such rule");
919        assert!(error.message().contains("NoSuchRule"));
920    }
921
922    #[test]
923    fn the_children_of_a_leaf_rule_are_none() {
924        let tree = parse("SELECT 1").expect("parses");
925        let mut leaves = 0;
926        for index in 0..tree.arena_len() as u32 {
927            if tree.node(index).first_child == NONE {
928                leaves += 1;
929            }
930        }
931        assert!(leaves > 0, "every tree has leaves");
932    }
933
934    #[test]
935    fn what_counts_as_a_bare_operator() {
936        // The ones a user can define, which is the only thing the generic node is for.
937        for text in ["&&", "@>", "<@", "||", "^@", "<<", ">>", "//", "**", "<<=", ">>="] {
938            assert!(is_bare_operator(text), "{text} should be an operator");
939        }
940        // Spelled by a rule, so the generic node has to leave them alone.
941        for text in ["->", "->>", "<=", ">=", "!=", "==", "<>", "~~", "!~~*"] {
942            assert!(!is_bare_operator(text), "{text} is spelled by a rule");
943        }
944        // A colon is not an operator character, so neither of these is one.
945        for text in ["::", ":=", "+", "(", ","] {
946            assert!(!is_bare_operator(text), "{text} is not an operator");
947        }
948    }
949
950    #[test]
951    fn the_corpus_parses() {
952        for query in CORPUS {
953            parse(query).unwrap_or_else(|error| panic!("{query}\n  {}", error.message()));
954        }
955    }
956
957    #[test]
958    fn the_corpus_parses_the_same_with_the_filter_off() {
959        for query in CORPUS {
960            let filtered = parse_from(query, "Program", true).expect("parses");
961            let plain = parse_from(query, "Program", false).expect("parses unfiltered");
962            let mut a = Vec::new();
963            let mut b = Vec::new();
964            names(&filtered, filtered.root(), &mut a);
965            names(&plain, plain.root(), &mut b);
966            assert_eq!(a, b, "{query} parsed differently with the filter on");
967        }
968    }
969
970    #[test]
971    fn the_work_stays_proportional_to_the_query() {
972        // A guard against the kind of regression that does not fail a test: a grammar or filter
973        // change that leaves every query still parsing and quietly triples what it costs. The
974        // numbers are what the table does today with a little room, not a target. The expression
975        // grammar is about twenty rules deep from `Expression` down to `BaseExpression` and every
976        // operand walks all of them, which is where most of these go.
977        for query in CORPUS {
978            let tree = parse(query).expect("parses");
979            let tokens = tokenize(query).expect("tokenizes").len() as u64;
980            let per_token = tree.steps() / tokens;
981            assert!(per_token < 400, "{query} took {per_token} steps a token");
982        }
983    }
984
985    #[test]
986    fn what_counts_as_a_plain_string() {
987        assert!(is_plain_string("'a'"));
988        assert!(!is_plain_string("E'a'"));
989        assert!(!is_plain_string("$$a$$"));
990        assert!(!is_plain_string(r#""a""#));
991    }
992}