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 fn push(&mut self, frame: Frame) -> Result<()> {
363 if self.stack.len() >= MAX_DEPTH {
364 let token = self.token(self.pos);
365 return Err(Error::parser(format!(
366 "memory exhausted at or near \"{}\"",
367 token.text(self.query)
368 ))
369 .with_span(token.span()));
370 }
371 self.stack.push(frame);
372 Ok(())
373 }
374
375 fn alloc(&mut self, node: ParseNode) -> u32 {
376 self.arena.push(node);
377 (self.arena.len() - 1) as u32
378 }
379
380 /// Record that something was tried here, for the error message.
381 fn reached(&mut self, pos: u32) {
382 if pos > self.furthest {
383 self.furthest = pos;
384 }
385 }
386
387 fn syntax_error(&self, pos: u32) -> Error {
388 let token = self.token(pos);
389 if token.kind == Kind::EndOfInput {
390 return Error::parser("syntax error at end of input").with_span(token.span());
391 }
392 Error::parser(format!("syntax error at or near \"{}\"", token.text(self.query)))
393 .with_span(token.span())
394 }
395
396 /// Handle one node.
397 fn enter(&mut self, index: u32) -> Result<Action> {
398 self.steps += 1;
399 let node = NODES[index as usize];
400 // The superset test, and only its no. A nullable node can match without reading a token at
401 // all, so its FIRST set says nothing about whether it applies and asking would reject the
402 // empty match that is the whole point of it.
403 if self.filter && !node.can_start(self.key(self.pos)) {
404 self.reached(self.pos);
405 return Ok(Action::Fail);
406 }
407
408 match node.op {
409 Op::Rule => self.enter_rule(node.a, node.b),
410 Op::Sequence => {
411 self.push(self.frame(FrameOp::Sequence, node.a, node.b))?;
412 Ok(Action::Enter(CHILDREN[node.a as usize]))
413 }
414 Op::Choice => {
415 let step = self.viable(node.a, node.b, 0);
416 if step == node.b {
417 self.reached(self.pos);
418 return Ok(Action::Fail);
419 }
420 let mut frame = self.frame(FrameOp::Choice, node.a, node.b);
421 frame.step = step;
422 self.push(frame)?;
423 Ok(Action::Enter(CHILDREN[(node.a + step) as usize]))
424 }
425 Op::Optional => {
426 self.push(self.frame(FrameOp::Optional, node.a, 0))?;
427 Ok(Action::Enter(node.a))
428 }
429 Op::Repeat => {
430 self.push(self.frame(FrameOp::Repeat, node.a, 0))?;
431 Ok(Action::Enter(node.a))
432 }
433 _ => Ok(self.terminal(node)),
434 }
435 }
436
437 /// The first alternative at or after `step` that could match the token in hand.
438 ///
439 /// A choice used to enter every alternative in turn and let the guard at the top of `enter`
440 /// reject it, and `Statement` has thirty six of them. That costs a step, a stack push and a
441 /// stack pop per rejection, for a test that is a load and an AND. Doing the test here means an
442 /// alternative that cannot match never becomes a step at all, which is why the step counts in
443 /// the bench moved and not only the times.
444 fn viable(&self, a: u32, b: u32, mut step: u32) -> u32 {
445 if !self.filter {
446 return step;
447 }
448 let key = self.key(self.pos);
449 while step < b && !NODES[CHILDREN[(a + step) as usize] as usize].can_start(key) {
450 step += 1;
451 }
452 step
453 }
454
455 fn frame(&self, op: FrameOp, a: u32, b: u32) -> Frame {
456 Frame { op, a, b, start: self.pos, step: 0, mark: self.pos, head: NONE, tail: NONE }
457 }
458
459 /// A reference to a rule, which is the only thing that makes a tree node.
460 fn enter_rule(&mut self, rule: u32, root: u32) -> Result<Action> {
461 let slot = self.slot_of[rule as usize];
462 if slot != NONE {
463 match self.memo[self.memo_index(slot)] {
464 MEMO_EMPTY => {}
465 MEMO_FAILED => return Ok(Action::Fail),
466 stored => {
467 // The stored node is shared by every parent that adopts it, and `next_sibling`
468 // is written by whichever one that is, so the node itself is copied and only
469 // its children are shared. The children are safe to share because nothing ever
470 // rewrites a link inside a finished list, only the link out of its head.
471 let source = self.arena[stored as usize];
472 self.pos = source.end;
473 let copy = self.alloc(ParseNode { next_sibling: NONE, ..source });
474 return Ok(Action::Succeed(copy, copy));
475 }
476 }
477 }
478 self.push(self.frame(FrameOp::Rule, rule, 0))?;
479 Ok(Action::Enter(root))
480 }
481
482 fn memo_index(&self, slot: u32) -> usize {
483 slot as usize * (self.tokens.len() + 1) + self.pos as usize
484 }
485
486 /// Something matched. Give its children to the frame above and decide what that frame does now.
487 fn settle_ok(&mut self, head: u32, tail: u32) -> Action {
488 // Popped rather than looked at, and pushed back by the two cases that carry on. A frame is
489 // thirty two bytes of `Copy`, so this is a couple of moves, and the alternative is holding
490 // a mutable borrow of the stack across every write to the arena.
491 let Some(mut frame) = self.stack.pop() else {
492 return Action::Done(Some(head));
493 };
494
495 if head != NONE {
496 if frame.head == NONE {
497 frame.head = head;
498 } else {
499 self.arena[frame.tail as usize].next_sibling = head;
500 }
501 frame.tail = tail;
502 }
503
504 match frame.op {
505 FrameOp::Rule => {
506 let node = self.alloc(ParseNode {
507 rule: frame.a,
508 start: frame.start,
509 end: self.pos,
510 first_child: frame.head,
511 next_sibling: NONE,
512 });
513 self.remember(frame.a, frame.start, node);
514 Action::Succeed(node, node)
515 }
516 FrameOp::Sequence => {
517 frame.step += 1;
518 if frame.step == frame.b {
519 Action::Succeed(frame.head, frame.tail)
520 } else {
521 let next = CHILDREN[(frame.a + frame.step) as usize];
522 self.stack.push(frame);
523 Action::Enter(next)
524 }
525 }
526 FrameOp::Choice | FrameOp::Optional => Action::Succeed(frame.head, frame.tail),
527 FrameOp::Repeat => {
528 // A repeat wraps something that cannot match nothing, which the generator checks
529 // and `a_repeat_never_wraps_something_that_matches_nothing` asserts, so this always
530 // moves. The guard is here because the alternative to a wrong answer would be a
531 // hang, and a hang in a parser is the failure nobody can diagnose from a bug
532 // report.
533 debug_assert!(self.pos != frame.mark, "a repeat went round without consuming");
534 if self.pos == frame.mark {
535 return Action::Succeed(frame.head, frame.tail);
536 }
537 frame.mark = self.pos;
538 frame.step += 1;
539 let child = frame.a;
540 self.stack.push(frame);
541 Action::Enter(child)
542 }
543 }
544 }
545
546 /// Something did not match. Put the position back and decide what the frame above does now.
547 fn settle_fail(&mut self) -> Action {
548 let Some(mut frame) = self.stack.pop() else {
549 return Action::Done(None);
550 };
551
552 match frame.op {
553 FrameOp::Rule => {
554 self.pos = frame.start;
555 // A failure is worth remembering for the same reason a success is. The rules that
556 // memoize are the ones an expression re-enters at the same position from every
557 // alternative in turn, and most of those re-entries fail.
558 self.remember(frame.a, frame.start, MEMO_FAILED);
559 Action::Fail
560 }
561 FrameOp::Sequence => {
562 self.pos = frame.start;
563 Action::Fail
564 }
565 FrameOp::Choice => {
566 self.pos = frame.start;
567 frame.step = self.viable(frame.a, frame.b, frame.step + 1);
568 if frame.step == frame.b {
569 Action::Fail
570 } else {
571 // The children of a failed alternative are dropped by not being spliced. The
572 // nodes stay in the arena, unreferenced, which is the trade this file's header
573 // is about.
574 frame.head = NONE;
575 frame.tail = NONE;
576 let next = CHILDREN[(frame.a + frame.step) as usize];
577 self.stack.push(frame);
578 Action::Enter(next)
579 }
580 }
581 FrameOp::Optional => {
582 self.pos = frame.start;
583 Action::Succeed(NONE, NONE)
584 }
585 FrameOp::Repeat => {
586 self.pos = frame.mark;
587 if frame.step == 0 { Action::Fail } else { Action::Succeed(frame.head, frame.tail) }
588 }
589 }
590 }
591
592 /// Write a memo entry, if this rule is one of the twenty two that get one.
593 fn remember(&mut self, rule: u32, start: u32, entry: u32) {
594 let slot = self.slot_of[rule as usize];
595 if slot != NONE {
596 let index = slot as usize * (self.tokens.len() + 1) + start as usize;
597 self.memo[index] = entry;
598 }
599 }
600
601 /// A node that matches tokens directly, or does not.
602 fn terminal(&mut self, node: Node) -> Action {
603 self.reached(self.pos);
604 if self.pos as usize >= self.tokens.len() {
605 return Action::Fail;
606 }
607 let token = self.tokens[self.pos as usize];
608 let matched = match node.op {
609 // An index compare, not a text compare. The tokenizer already folded the word and
610 // looked it up, and everything that is not a word carries `NOT_A_KEYWORD`, which is
611 // larger than any index, so the compare rejects them without asking what they are.
612 Op::Keyword => u32::from(token.keyword) == node.a,
613 Op::KeywordClass => {
614 token.kind == Kind::Keyword && u32::from(class_of(token)) & node.a != 0
615 }
616 // A text compare and nothing else, which is upstream's, and it matters. A `.` between
617 // two names arrives as a number token, because the tokenizer cannot tell `a.b` from
618 // `.5` until it has read past the dot, so a check that the token is an operator would
619 // make `DottedIdentifier` unmatchable. Nothing is lost by dropping it: every symbol is
620 // punctuation, no word or literal has punctuation for its whole text, and a quoted or
621 // string token carries its quotes in its text and so cannot collide either.
622 Op::Symbol => token.text(self.query) == SYMBOLS[node.a as usize],
623 // The other half of the same fact. Upstream rejects a lone dot here, and this is why:
624 // without it `a.b` would parse `.` as a numeric literal and `SELECT a.b` would come
625 // out as three expressions rather than one qualified name.
626 Op::Number => token.kind == Kind::Number && token.text(self.query) != ".",
627 Op::Operator => {
628 token.kind == Kind::Operator && is_bare_operator(token.text(self.query))
629 }
630 Op::EndOfInput => token.kind == Kind::EndOfInput,
631 Op::String => return self.string(token),
632 Op::Identifier => self.identifier(token, node),
633 other => unreachable!("{other:?} is a composite and never reaches here"),
634 };
635 if matched {
636 self.pos += 1;
637 Action::Succeed(NONE, NONE)
638 } else {
639 Action::Fail
640 }
641 }
642
643 /// A string literal and the literals that continue it.
644 ///
645 /// `'a'` on one line and `'b'` on the next is one string in SQL, and the rule for when it is
646 /// comes from PostgreSQL: the pieces have to be plain single quoted literals, there has to be a
647 /// line break between them, and a block comment in the gap stops the run. `'a' 'b'` on one line
648 /// is not a continuation and neither is `E'a'` followed by anything, so a prefixed or dollar
649 /// quoted literal matches alone.
650 fn string(&mut self, token: Token) -> Action {
651 if token.kind != Kind::String {
652 return Action::Fail;
653 }
654 self.pos += 1;
655 if !is_plain_string(token.text(self.query)) {
656 return Action::Succeed(NONE, NONE);
657 }
658 while let Some(next) = self.tokens.get(self.pos as usize) {
659 if next.kind != Kind::String
660 || !next.flags.has(Flags::NEWLINE)
661 || next.flags.has(Flags::BLOCK_COMMENT)
662 || !is_plain_string(next.text(self.query))
663 {
664 break;
665 }
666 self.pos += 1;
667 }
668 Action::Succeed(NONE, NONE)
669 }
670
671 /// A name, in whichever of the eleven positions the grammar is at.
672 ///
673 /// Two questions, in upstream's order. Is this the shape of a name at all, and if it is a
674 /// keyword, is this a position that lets that keyword through. The second is where the keyword
675 /// classes earn their existence: `SELECT * FROM binary` is an error and `SELECT binary(x)` is
676 /// not, and the only difference between them is which suggestion the matcher was built with.
677 fn identifier(&mut self, token: Token, node: Node) -> bool {
678 let suggestion = SUGGESTIONS[node.a as usize];
679 let shaped = match token.kind {
680 Kind::QuotedIdentifier => true,
681 Kind::Identifier | Kind::Keyword => true,
682 // `FROM 'file.parquet'` and `COPY t TO 'out.csv'`, and nowhere else. Anywhere else a
683 // single quoted string has to stay a string, or `SELECT 'x' FROM t` becomes a column.
684 Kind::String => {
685 suggestion.supports_string_literal() && is_plain_string(token.text(self.query))
686 }
687 _ => false,
688 };
689 if !shaped {
690 return false;
691 }
692 // The whole of `ReservedIdentifierMatcher`, which is what the rule named `ReservedKeyword`
693 // is overridden with. It skips the class check entirely, so it takes any word at all rather
694 // than the seventy five reserved ones. See `Node::RESERVED`.
695 if node.flags & Node::RESERVED != 0 {
696 return true;
697 }
698 if token.kind != Kind::Keyword {
699 return true;
700 }
701 let class = class_of(token);
702 class & UNRESERVED != 0 || class & suggestion.allowed_class() != 0
703 }
704}
705
706/// Which classes a token's word is in.
707fn class_of(token: Token) -> u8 {
708 KEYWORDS[token.keyword as usize].1
709}
710
711/// Whether a string literal is the plain single quoted kind.
712///
713/// Prefixed forms (`E'a'`, `x'ff'`) and dollar quoting start with something else, and the two
714/// places this is asked both care about the same distinction.
715fn is_plain_string(text: &str) -> bool {
716 text.starts_with('\'')
717}
718
719/// The characters `OperatorMatcher` will accept a token made entirely of.
720const OPERATOR_CHARACTERS: &[u8] = b"+-*/%^<>=~!@&|";
721
722/// The tokens that look like operators and are not, because the grammar spells them itself.
723///
724/// Upstream lists these out in `OperatorMatcher` and the reason is the same for all of them: a rule
725/// somewhere writes the token as a literal and means something specific by it, so letting the
726/// generic operator node take it first would make that rule unreachable. `->` is JSON extraction,
727/// the comparisons are comparisons, and the tilde family is the pattern matching operators.
728const NOT_OPERATORS: [&str; 15] = [
729 "->", "->>", "<=", ">=", "!=", "==", "<>", "~~", "~~*", "~~~", "~*", "!~~", "!~~*", "!~", "!~*",
730];
731
732/// Whether this text is an operator in the sense the `Operator` node means.
733///
734/// A single character is never one, which is not an oversight: every single character operator in
735/// the language is spelled by a rule, so the generic node is only ever for the multi character ones
736/// a user might define.
737fn is_bare_operator(text: &str) -> bool {
738 if text.len() < 2 || NOT_OPERATORS.contains(&text) {
739 return false;
740 }
741 text.bytes().all(|byte| OPERATOR_CHARACTERS.contains(&byte))
742}
743
744/// The eleven suggestions by discriminant, so that a node's `a` can be turned back into one.
745///
746/// A table rather than a `match`, because the discriminants are dense and written by the generator
747/// and the table is checked against them by `the_suggestions_are_dense_and_in_order`.
748const SUGGESTIONS: [Suggestion; 11] = [
749 Suggestion::Variable,
750 Suggestion::CatalogName,
751 Suggestion::SchemaName,
752 Suggestion::TableName,
753 Suggestion::ColumnName,
754 Suggestion::ScalarFunctionName,
755 Suggestion::TableFunctionName,
756 Suggestion::TypeName,
757 Suggestion::PragmaName,
758 Suggestion::SettingName,
759 Suggestion::FileName,
760];
761
762#[cfg(test)]
763mod tests {
764 use super::{
765 NONE, SUGGESTIONS, Tree, is_bare_operator, is_plain_string, parse, parse_from, parse_tokens,
766 };
767 use crate::corpus::CORPUS;
768 use crate::generated::rules::PROGRAM;
769 use crate::tokenize::tokenize;
770
771 /// The rules a tree has, outermost first, for asserting on shape without writing out the whole
772 /// thing.
773 fn names(tree: &Tree, node: u32, into: &mut Vec<&'static str>) {
774 into.push(tree.name(node));
775 for child in tree.children(node) {
776 names(tree, child, into);
777 }
778 }
779
780 /// The first node with this rule name, depth first.
781 fn find(tree: &Tree, node: u32, name: &str) -> Option<u32> {
782 if tree.name(node) == name {
783 return Some(node);
784 }
785 tree.children(node).find_map(|child| find(tree, child, name))
786 }
787
788 fn shape(query: &str) -> Vec<&'static str> {
789 let tree = parse(query).expect("parses");
790 let mut out = Vec::new();
791 names(&tree, tree.root(), &mut out);
792 out
793 }
794
795 #[test]
796 fn the_suggestions_are_dense_and_in_order() {
797 for (index, suggestion) in SUGGESTIONS.iter().enumerate() {
798 assert_eq!(*suggestion as usize, index);
799 }
800 }
801
802 #[test]
803 fn an_empty_script_parses() {
804 let tree = parse("").expect("an empty script is a script with no statements");
805 assert_eq!(tree.name(tree.root()), "Program");
806 }
807
808 #[test]
809 fn a_select_parses_and_the_root_is_the_program() {
810 let tree = parse("SELECT 1").expect("parses");
811 assert_eq!(tree.name(tree.root()), "Program");
812 let statements: Vec<_> = tree.children(tree.root()).collect();
813 assert_eq!(statements.len(), 1);
814 assert_eq!(tree.name(statements[0]), "TopLevelStatement");
815 }
816
817 #[test]
818 fn the_shape_has_the_rules_the_grammar_names() {
819 let shape = shape("SELECT 1");
820 assert!(shape.contains(&"SelectStatement"), "{shape:?}");
821 }
822
823 #[test]
824 fn a_statement_covers_the_text_it_came_from() {
825 let query = " SELECT 1 ";
826 let tokens = tokenize(query).expect("tokenizes");
827 let tree = parse_tokens(query, &tokens, PROGRAM, true).expect("parses");
828 // The statement and not the `TopLevelStatement` that wraps it. `TopLevelStatement` covers
829 // the terminator too, and at the end of a script the terminator is the end of input token,
830 // whose span is the end of the query, so its text runs out to the trailing whitespace.
831 let statement = find(&tree, tree.root(), "SelectStatement").expect("there is one");
832 assert_eq!(tree.text(statement, query, &tokens), "SELECT 1");
833 }
834
835 #[test]
836 fn several_statements_parse_as_several() {
837 let tree = parse("SELECT 1; SELECT 2; SELECT 3").expect("parses");
838 let shape = shape("SELECT 1; SELECT 2; SELECT 3");
839 assert_eq!(shape.iter().filter(|name| **name == "SelectStatement").count(), 3);
840 assert!(tree.children(tree.root()).count() >= 3);
841 }
842
843 #[test]
844 fn a_trailing_semicolon_makes_an_empty_statement() {
845 // Not a bug and not worth working around here. `TopLevelStatement <- Statement? (';'+ /
846 // EndOfInput)` has both halves optional in effect, so at the end of `SELECT 1;` the
847 // repetition goes round once more, matches no statement and the end of input, and stops.
848 // The extra node has an `EndOfInput` child and no `Statement` one, which is how the
849 // transformer tells it apart, and upstream drops it in the same place for the same reason.
850 let one = parse("SELECT 1").expect("parses");
851 let two = parse("SELECT 1;").expect("parses");
852 assert_eq!(one.children(one.root()).count(), 1);
853 assert_eq!(two.children(two.root()).count(), 2);
854 let last = two.children(two.root()).last().expect("there is a last one");
855 let inside: Vec<_> = two.children(last).map(|child| two.name(child)).collect();
856 assert_eq!(inside, ["EndOfInput"], "the extra one holds no statement");
857 }
858
859 #[test]
860 fn rubbish_after_a_statement_is_an_error() {
861 // Without the consumed-everything check this parses as `SELECT 1` and drops the rest,
862 // because `Program <- TopLevelStatement*` is allowed to stop early.
863 let error = parse("SELECT 1 rubbish here").expect_err("not a query");
864 assert!(error.message().starts_with("syntax error at or near"), "{}", error.message());
865 }
866
867 #[test]
868 fn a_word_that_is_not_a_statement_is_an_error() {
869 let error = parse("SELCT 1").expect_err("not a query");
870 assert!(error.message().contains("syntax error"), "{}", error.message());
871 }
872
873 #[test]
874 fn the_error_points_at_the_furthest_token_reached() {
875 // The parse gives up at the start of the statement, having tried every alternative. The
876 // place worth reporting is the furthest one any of them got to, which is the `from`.
877 let error = parse("SELECT 1 FROM").expect_err("not a query");
878 assert!(error.span().is_some(), "an error about a place should say which place");
879 }
880
881 #[test]
882 fn a_soft_keyword_is_a_column_name_and_also_a_keyword() {
883 // `ascending` is spelled by a rule and is in no class, so it is both of these and the
884 // FIRST set for the literal has to be the identifier bit rather than a keyword bucket.
885 parse("SELECT ascending FROM t").expect("a soft word is a name");
886 parse("SELECT x FROM t ORDER BY x ASCENDING").expect("a soft word is also a literal");
887 }
888
889 #[test]
890 fn a_reserved_word_is_not_a_column_name() {
891 parse("SELECT x FROM t").expect("an ordinary name is fine");
892 parse("SELECT * FROM t WHERE all").expect_err("`all` is reserved");
893 }
894
895 #[test]
896 fn an_unreserved_word_is_a_column_name_everywhere() {
897 parse("SELECT abort FROM t").expect("`abort` is unreserved");
898 }
899
900 #[test]
901 fn a_function_name_keyword_is_a_function_and_not_a_column() {
902 // The whole point of the classes. `binary` is in the function name class and nowhere else,
903 // so the two positions disagree about it.
904 parse("SELECT binary(x) FROM t").expect("a function name position takes it");
905 parse("SELECT binary FROM t").expect_err("a column name position does not");
906 }
907
908 #[test]
909 fn a_quoted_name_is_a_name_whatever_it_spells() {
910 parse(r#"SELECT "all" FROM t"#).expect("quoting takes a word out of every class");
911 }
912
913 #[test]
914 fn adjacent_strings_across_a_line_are_one_literal() {
915 parse("SELECT 'a'\n'b'").expect("a continuation");
916 parse("SELECT 'a' 'b'").expect_err("on one line they are two strings and a syntax error");
917 }
918
919 #[test]
920 fn deep_nesting_is_an_error_and_not_a_crash() {
921 // A thread stack would be gone long before this. The number is well past the cap.
922 let query = format!("SELECT {}1{}", "(".repeat(200_000), ")".repeat(200_000));
923 let error = parse(&query).expect_err("too deep to parse");
924 assert!(error.message().contains("memory exhausted"), "{}", error.message());
925 }
926
927 #[test]
928 fn nesting_that_is_merely_rude_still_parses() {
929 let query = format!("SELECT {}1{}", "(".repeat(500), ")".repeat(500));
930 parse(&query).expect("five hundred deep is fine");
931 }
932
933 #[test]
934 fn a_named_rule_can_be_parsed_on_its_own() {
935 let tree = parse_from("SELECT 1", "SelectStatement", true).expect("parses");
936 assert_eq!(tree.name(tree.root()), "SelectStatement");
937 }
938
939 #[test]
940 fn asking_for_a_rule_that_does_not_exist_says_so() {
941 let error = parse_from("SELECT 1", "NoSuchRule", true).expect_err("no such rule");
942 assert!(error.message().contains("NoSuchRule"));
943 }
944
945 #[test]
946 fn the_children_of_a_leaf_rule_are_none() {
947 let tree = parse("SELECT 1").expect("parses");
948 let mut leaves = 0;
949 for index in 0..tree.arena_len() as u32 {
950 if tree.node(index).first_child == NONE {
951 leaves += 1;
952 }
953 }
954 assert!(leaves > 0, "every tree has leaves");
955 }
956
957 #[test]
958 fn what_counts_as_a_bare_operator() {
959 // The ones a user can define, which is the only thing the generic node is for.
960 for text in ["&&", "@>", "<@", "||", "^@", "<<", ">>", "//", "**", "<<=", ">>="] {
961 assert!(is_bare_operator(text), "{text} should be an operator");
962 }
963 // Spelled by a rule, so the generic node has to leave them alone.
964 for text in ["->", "->>", "<=", ">=", "!=", "==", "<>", "~~", "!~~*"] {
965 assert!(!is_bare_operator(text), "{text} is spelled by a rule");
966 }
967 // A colon is not an operator character, so neither of these is one.
968 for text in ["::", ":=", "+", "(", ","] {
969 assert!(!is_bare_operator(text), "{text} is not an operator");
970 }
971 }
972
973 #[test]
974 fn the_corpus_parses() {
975 for query in CORPUS {
976 parse(query).unwrap_or_else(|error| panic!("{query}\n {}", error.message()));
977 }
978 }
979
980 #[test]
981 fn the_corpus_parses_the_same_with_the_filter_off() {
982 for query in CORPUS {
983 let filtered = parse_from(query, "Program", true).expect("parses");
984 let plain = parse_from(query, "Program", false).expect("parses unfiltered");
985 let mut a = Vec::new();
986 let mut b = Vec::new();
987 names(&filtered, filtered.root(), &mut a);
988 names(&plain, plain.root(), &mut b);
989 assert_eq!(a, b, "{query} parsed differently with the filter on");
990 }
991 }
992
993 #[test]
994 fn the_work_stays_proportional_to_the_query() {
995 // A guard against the kind of regression that does not fail a test: a grammar or filter
996 // change that leaves every query still parsing and quietly triples what it costs. The
997 // numbers are what the table does today with a little room, not a target. The expression
998 // grammar is about twenty rules deep from `Expression` down to `BaseExpression` and every
999 // operand walks all of them, which is where most of these go.
1000 for query in CORPUS {
1001 let tree = parse(query).expect("parses");
1002 let tokens = tokenize(query).expect("tokenizes").len() as u64;
1003 let per_token = tree.steps() / tokens;
1004 assert!(per_token < 200, "{query} took {per_token} steps a token");
1005 }
1006 }
1007
1008 #[test]
1009 fn what_counts_as_a_plain_string() {
1010 assert!(is_plain_string("'a'"));
1011 assert!(!is_plain_string("E'a'"));
1012 assert!(!is_plain_string("$$a$$"));
1013 assert!(!is_plain_string(r#""a""#));
1014 }
1015}