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