Line data Source code
1 : //! The parse context.
2 : //!
3 : //! The grammar actions build the AST through the parse context. Nodes are appended to a flat buffer
4 : //! in post-order: `object` and `array` emit the children of a node and return the node itself,
5 : //! which the enclosing rule emits later. Every method takes `&self` (the state sits in a
6 : //! [`StateCell`]) so that the translated actions can nest calls like
7 : //! `ctx.object(.., &[attr(.., ctx.array(..))])`, which emit nodes in argument evaluation order.
8 :
9 : // Release builds hand out a plain `&mut State` from `StateCell::borrow_mut`, so the `mut` that the
10 : // debug `RefMut` guard needs on `let mut state = ..` is unused there.
11 : #![cfg_attr(not(debug_assertions), allow(unused_mut))]
12 :
13 : use super::value::{ExprVariant, NodeList};
14 : use crate::names::NameRegistry;
15 : use crate::scanner::Symbol;
16 : use crate::span::TextSpan;
17 : use dashql_buffers::parser::{AttributeKey, ExpressionOperator, Node, NodeType, NumericType, SampleCountUnit, StatementType, SymbolSpan};
18 :
19 : /// The cell of the parse context state.
20 : ///
21 : /// Methods of the parse context borrow the state only within their own body and never call each
22 : /// other while holding a borrow. Debug builds check this with a `RefCell`, release builds skip the
23 : /// bookkeeping, which is a hot path of parsing (about a thousand borrows per statement).
24 : #[cfg(debug_assertions)]
25 : pub(crate) struct StateCell<T>(std::cell::RefCell<T>);
26 :
27 : #[cfg(debug_assertions)]
28 : impl<T> StateCell<T> {
29 7918 : fn new(value: T) -> Self {
30 7918 : Self(std::cell::RefCell::new(value))
31 7918 : }
32 706855 : pub(crate) fn borrow(&self) -> std::cell::Ref<'_, T> {
33 706855 : self.0.borrow()
34 706855 : }
35 2736904 : pub(crate) fn borrow_mut(&self) -> std::cell::RefMut<'_, T> {
36 2736904 : self.0.borrow_mut()
37 2736904 : }
38 7918 : fn into_inner(self) -> T {
39 7918 : self.0.into_inner()
40 7918 : }
41 : }
42 :
43 : /// The cell of the parse context state, unchecked in release builds
44 : #[cfg(not(debug_assertions))]
45 : pub(crate) struct StateCell<T>(std::cell::UnsafeCell<T>);
46 :
47 : #[cfg(not(debug_assertions))]
48 : impl<T> StateCell<T> {
49 : fn new(value: T) -> Self {
50 : Self(std::cell::UnsafeCell::new(value))
51 : }
52 : pub(crate) fn borrow(&self) -> &T {
53 : // SAFETY: borrows never overlap with a mutable borrow, checked by debug builds.
54 : unsafe { &*self.0.get() }
55 : }
56 : #[allow(clippy::mut_from_ref)]
57 : pub(crate) fn borrow_mut(&self) -> &mut T {
58 : // SAFETY: borrows never overlap, checked by debug builds.
59 : unsafe { &mut *self.0.get() }
60 : }
61 : fn into_inner(self) -> T {
62 : self.0.into_inner()
63 : }
64 : }
65 :
66 : /// The parent of nodes that have none (yet)
67 : pub const NO_PARENT: u32 = u32::MAX;
68 :
69 : /// A parsed statement
70 : #[derive(Clone, Copy, Debug, PartialEq, Eq)]
71 : pub struct Statement {
72 : /// The statement type, derived from the type of the root node
73 : pub statement_type: StatementType,
74 : /// The root node
75 : pub root: u32,
76 : /// The first node of the statement
77 : pub nodes_begin: u32,
78 : /// The number of nodes of the statement
79 : pub node_count: u32,
80 : }
81 :
82 : impl Default for Statement {
83 16855 : fn default() -> Self {
84 16855 : Self {
85 16855 : statement_type: StatementType::NONE,
86 16855 : root: u32::MAX,
87 16855 : nodes_begin: 0,
88 16855 : node_count: 0,
89 16855 : }
90 16855 : }
91 : }
92 :
93 : /// A parser error, located by symbol indexes
94 : #[derive(Clone, Debug, PartialEq)]
95 : pub struct ParseError {
96 : /// The symbol indexes of the error
97 : pub location: SymbolSpan,
98 : /// The error message
99 : pub message: String,
100 : /// A hint how to fix the error, empty if there is none
101 : pub hint: String,
102 : }
103 :
104 : /// An n-ary expression whose materialization is deferred to flatten conjunctions and disjunctions
105 : #[derive(Clone, Copy, Debug)]
106 : struct NaryExpression {
107 : /// The symbol indexes of the expression
108 : location: SymbolSpan,
109 : /// The operator, AND or OR
110 : op: ExpressionOperator,
111 : /// The operator node
112 : op_node: Node,
113 : /// The flattened arguments
114 : args: NodeList,
115 : }
116 :
117 : /// The mutable state of the parse context
118 : #[derive(Default)]
119 : pub(crate) struct State {
120 : /// The AST nodes in post-order
121 : pub(crate) nodes: Vec<Node>,
122 : /// The finished statements
123 : pub(crate) statements: Vec<Statement>,
124 : /// The parser errors
125 : pub(crate) errors: Vec<ParseError>,
126 : /// The names of the scanned script, extended by names the parser registers
127 : pub(crate) names: NameRegistry,
128 : /// The hint of the next error, produced while building a syntax error message
129 : pub(crate) pending_hint: String,
130 : /// Set by an action to drop the lookahead (`yyclearin`)
131 : pub(crate) clear_lookahead: bool,
132 : /// The statement being parsed, its nodes start at `nodes_begin`
133 : current_statement: Statement,
134 : /// The node lists indexed by list id
135 : lists: Vec<Vec<Node>>,
136 : /// Consumed lists whose allocation can be reused
137 : free_lists: Vec<u32>,
138 : /// The deferred n-ary expressions indexed by `ExprVariant::Nary` id
139 : nary_expressions: Vec<NaryExpression>,
140 : }
141 :
142 : impl State {
143 : /// A copy of the nodes of a list
144 82 : pub(crate) fn lists_snapshot(&self, list: NodeList) -> Vec<Node> {
145 82 : self.lists[list.0 as usize].clone()
146 82 : }
147 : }
148 :
149 : /// The parse context
150 : pub struct ParseContext<'a> {
151 : /// The script text
152 : text: &'a str,
153 : /// The scanned symbols, located by byte spans
154 : symbols: &'a [Symbol],
155 : /// The mutable parser state
156 : pub(crate) state: StateCell<State>,
157 : }
158 :
159 : /// Arguments that are node lists: list ids and node slices
160 : pub trait IntoNodeList {
161 : fn into_node_list(self, ctx: &ParseContext) -> NodeList;
162 : }
163 :
164 : impl IntoNodeList for NodeList {
165 219617 : fn into_node_list(self, _ctx: &ParseContext) -> NodeList {
166 219617 : self
167 219617 : }
168 : }
169 :
170 : impl<const N: usize> IntoNodeList for &[Node; N] {
171 177952 : fn into_node_list(self, ctx: &ParseContext) -> NodeList {
172 177952 : ctx.list(&self[..])
173 177952 : }
174 : }
175 :
176 : impl IntoNodeList for &[Node] {
177 0 : fn into_node_list(self, ctx: &ParseContext) -> NodeList {
178 0 : ctx.list(self)
179 0 : }
180 : }
181 :
182 : /// A node with replaced fields
183 982118 : fn with_parent(n: &Node, parent: u32) -> Node {
184 982118 : Node::new(n.symbol_span(), n.node_type(), n.attribute_key(), parent, n.children_begin_or_value(), n.children_count())
185 982118 : }
186 :
187 : /// The null node, skipped by `object` and `array`
188 146913 : pub fn null() -> Node {
189 146913 : Node::new(&SymbolSpan::default(), NodeType::NONE, AttributeKey::NONE, NO_PARENT, 0, 0)
190 146913 : }
191 :
192 : impl<'a> ParseContext<'a> {
193 7918 : pub fn new(text: &'a str, symbols: &'a [Symbol], names: NameRegistry) -> Self {
194 7918 : Self {
195 7918 : text,
196 7918 : symbols,
197 7918 : state: StateCell::new(State {
198 7918 : names,
199 7918 : nodes: Vec::with_capacity(symbols.len() * 3),
200 7918 : ..Default::default()
201 7918 : }),
202 7918 : }
203 7918 : }
204 :
205 : /// The scanned symbols
206 349971 : pub fn symbols(&self) -> &'a [Symbol] {
207 349971 : self.symbols
208 349971 : }
209 :
210 : /// Finish parsing and return the state
211 7918 : pub(crate) fn into_state(self) -> State {
212 7918 : self.state.into_inner()
213 7918 : }
214 :
215 : /// Resolve a span of symbol indexes to a span of bytes
216 596 : pub fn resolve_text_span(&self, span: SymbolSpan) -> TextSpan {
217 596 : resolve_text_span(self.text, self.symbols, span)
218 596 : }
219 :
220 : /// The text of a span of symbols
221 130 : fn text_at(&self, span: SymbolSpan) -> &'a str {
222 130 : let ts = self.resolve_text_span(span);
223 130 : &self.text[ts.offset as usize..ts.end() as usize]
224 130 : }
225 :
226 : // -----------------------------------------------------------------------------------------
227 : // Lists
228 : // -----------------------------------------------------------------------------------------
229 :
230 : /// Create a list
231 378531 : pub fn list(&self, nodes: &[Node]) -> NodeList {
232 378531 : let mut state = self.state.borrow_mut();
233 378531 : if let Some(id) = state.free_lists.pop() {
234 346497 : state.lists[id as usize].extend_from_slice(nodes);
235 346497 : return NodeList(id);
236 32034 : }
237 32034 : state.lists.push(nodes.to_vec());
238 32034 : NodeList(state.lists.len() as u32 - 1)
239 378531 : }
240 :
241 : /// Release a consumed list, keeping its allocation for reuse
242 376655 : fn recycle(&self, list: NodeList, mut nodes: Vec<Node>) {
243 376655 : nodes.clear();
244 376655 : let mut state = self.state.borrow_mut();
245 376655 : state.lists[list.0 as usize] = nodes;
246 376655 : state.free_lists.push(list.0);
247 376655 : }
248 :
249 : /// Append a node
250 101876 : pub fn push_back(&self, list: NodeList, node: Node) {
251 101876 : self.state.borrow_mut().lists[list.0 as usize].push(node);
252 101876 : }
253 :
254 : /// Prepend a node
255 9907 : pub fn push_front(&self, list: NodeList, node: Node) {
256 9907 : self.state.borrow_mut().lists[list.0 as usize].insert(0, node);
257 9907 : }
258 :
259 : /// Is a list empty?
260 1672 : pub fn list_is_empty(&self, list: NodeList) -> bool {
261 1672 : self.state.borrow().lists[list.0 as usize].is_empty()
262 1672 : }
263 :
264 : /// Move the nodes of a list
265 376655 : fn take_list(&self, list: NodeList) -> Vec<Node> {
266 376655 : std::mem::take(&mut self.state.borrow_mut().lists[list.0 as usize])
267 376655 : }
268 :
269 : /// Append the nodes of `other` to `list`
270 30727 : fn append(&self, list: NodeList, other: impl IntoNodeList) {
271 30727 : let other = other.into_node_list(self);
272 30727 : if other == list {
273 0 : return;
274 30727 : }
275 30727 : let nodes = self.take_list(other);
276 30727 : self.state.borrow_mut().lists[list.0 as usize].extend_from_slice(&nodes);
277 30727 : self.recycle(other, nodes);
278 30727 : }
279 :
280 : /// `Concat(l, r)`
281 19543 : pub fn concat2(&self, l: impl IntoNodeList, r: impl IntoNodeList) -> NodeList {
282 19543 : let l = l.into_node_list(self);
283 19543 : self.append(l, r);
284 19543 : l
285 19543 : }
286 :
287 : /// `Concat(v0, v1, v2)`
288 780 : pub fn concat3(&self, v0: impl IntoNodeList, v1: impl IntoNodeList, v2: impl IntoNodeList) -> NodeList {
289 780 : let v0 = v0.into_node_list(self);
290 780 : self.append(v0, v1);
291 780 : self.append(v0, v2);
292 780 : v0
293 780 : }
294 :
295 : /// `Concat(v0, v1, v2, v3)`
296 591 : pub fn concat4(
297 591 : &self,
298 591 : v0: impl IntoNodeList,
299 591 : v1: impl IntoNodeList,
300 591 : v2: impl IntoNodeList,
301 591 : v3: impl IntoNodeList,
302 591 : ) -> NodeList {
303 591 : let v0 = v0.into_node_list(self);
304 591 : self.append(v0, v1);
305 591 : self.append(v0, v2);
306 591 : self.append(v0, v3);
307 591 : v0
308 591 : }
309 :
310 : // -----------------------------------------------------------------------------------------
311 : // Nodes
312 : // -----------------------------------------------------------------------------------------
313 :
314 : /// Emit a node and set the parent of its children
315 495715 : pub fn add_node(&self, node: Node) -> u32 {
316 495715 : let mut state = self.state.borrow_mut();
317 495715 : let node_id = state.nodes.len() as u32;
318 495715 : state.nodes.push(with_parent(&node, node_id));
319 495715 : let node_type = node.node_type();
320 495715 : if (node_type == NodeType::ARRAY || node_type.0 > NodeType::OBJECT_KEYS_.0) && node.children_count() > 0 {
321 312574 : let begin = node.children_begin_or_value() as usize;
322 312574 : let end = begin + node.children_count() as usize;
323 486403 : for child in &mut state.nodes[begin..end] {
324 486403 : *child = with_parent(child, node_id);
325 486403 : }
326 183141 : }
327 495715 : node_id
328 495715 : }
329 :
330 : /// Emit the children of a list and return their range, skipping null nodes
331 345928 : fn emit_children(&self, list: NodeList) -> (u32, u32) {
332 345928 : let begin = self.state.borrow().nodes.len() as u32;
333 345928 : let nodes = self.take_list(list);
334 628284 : for node in &nodes {
335 628284 : if node.node_type() == NodeType::NONE {
336 141506 : continue;
337 486778 : }
338 486778 : self.add_node(*node);
339 : }
340 345928 : self.recycle(list, nodes);
341 345928 : let n = self.state.borrow().nodes.len() as u32 - begin;
342 345928 : (begin, n)
343 345928 : }
344 :
345 : /// The span from the first to the last of `n` nodes starting at `begin`
346 0 : fn shrunk_location(&self, begin: u32, n: u32) -> SymbolSpan {
347 0 : let state = self.state.borrow();
348 0 : let first = state.nodes[begin as usize].symbol_span().offset();
349 0 : let last = state.nodes[(begin + n - 1) as usize].symbol_span();
350 0 : SymbolSpan::new(first, last.offset().wrapping_add(last.length()).wrapping_sub(first))
351 0 : }
352 :
353 : /// An array of nodes
354 168540 : pub fn array(&self, loc: SymbolSpan, values: impl IntoNodeList) -> Node {
355 168540 : self.array_ex(loc, values, true, false)
356 168540 : }
357 :
358 : /// An array of nodes with explicit options
359 168852 : pub fn array_ex(&self, mut loc: SymbolSpan, values: impl IntoNodeList, null_if_empty: bool, shrink_location: bool) -> Node {
360 168852 : let list = values.into_node_list(self);
361 168852 : let (begin, n) = self.emit_children(list);
362 168852 : if n == 0 && null_if_empty {
363 32569 : return null();
364 136283 : }
365 136283 : if n > 0 && shrink_location {
366 0 : loc = self.shrunk_location(begin, n);
367 136283 : }
368 136283 : Node::new(&loc, NodeType::ARRAY, AttributeKey::NONE, NO_PARENT, begin, n)
369 168852 : }
370 :
371 : /// An array of expressions
372 22672 : pub(crate) fn expression_array(&self, loc: SymbolSpan, exprs: &[ExprVariant]) -> Node {
373 22672 : let nodes = self.list(&[]);
374 46324 : for &expr in exprs {
375 46324 : let node = self.expression(expr);
376 46324 : self.push_back(nodes, node);
377 46324 : }
378 22672 : self.array(loc, nodes)
379 22672 : }
380 :
381 : /// An object
382 176475 : pub fn object(&self, loc: SymbolSpan, node_type: NodeType, attrs: impl IntoNodeList) -> Node {
383 176475 : self.object_ex(loc, node_type, attrs, true, false)
384 176475 : }
385 :
386 : /// An object with explicit options
387 177076 : pub fn object_ex(
388 177076 : &self,
389 177076 : mut loc: SymbolSpan,
390 177076 : node_type: NodeType,
391 177076 : attrs: impl IntoNodeList,
392 177076 : null_if_empty: bool,
393 177076 : shrink_location: bool,
394 177076 : ) -> Node {
395 177076 : let list = attrs.into_node_list(self);
396 177076 : let (begin, n) = self.emit_children(list);
397 177076 : if n == 0 && null_if_empty {
398 212 : return null();
399 176864 : }
400 176864 : if n > 0 && shrink_location {
401 0 : loc = self.shrunk_location(begin, n);
402 176864 : }
403 176864 : Node::new(&loc, node_type, AttributeKey::NONE, NO_PARENT, begin, n)
404 177076 : }
405 :
406 : /// Materialize an expression
407 101893 : pub fn expression(&self, expr: impl Into<ExprVariant>) -> Node {
408 101893 : match expr.into() {
409 97823 : ExprVariant::Node(node) => node,
410 4070 : ExprVariant::Nary(id) => {
411 4070 : let nary = self.state.borrow().nary_expressions[id as usize];
412 4070 : let args = self.array(nary.location, nary.args);
413 4070 : self.object(
414 4070 : nary.location,
415 : NodeType::OBJECT_SQL_NARY_EXPRESSION,
416 4070 : &[
417 4070 : super::actions::attr(AttributeKey::SQL_EXPRESSION_OPERATOR, nary.op_node),
418 4070 : super::actions::attr(AttributeKey::SQL_EXPRESSION_ARGS, args),
419 4070 : ],
420 : )
421 : }
422 : }
423 101893 : }
424 :
425 : /// Flatten an AND / OR expression with nested expressions of the same operator
426 34070 : pub(crate) fn try_merge(&self, loc: SymbolSpan, op_node: Node, args: &[ExprVariant]) -> Option<ExprVariant> {
427 34070 : if op_node.node_type() != NodeType::ENUM_SQL_EXPRESSION_OPERATOR {
428 96 : return None;
429 33974 : }
430 33974 : let op = ExpressionOperator(op_node.children_begin_or_value() as u8);
431 33974 : if op != ExpressionOperator::AND && op != ExpressionOperator::OR {
432 22051 : return None;
433 11923 : }
434 11923 : let nary_args = self.list(&[]);
435 11923 : let id = {
436 11923 : let mut state = self.state.borrow_mut();
437 11923 : state.nary_expressions.push(NaryExpression {
438 11923 : location: loc,
439 11923 : op,
440 11923 : op_node,
441 11923 : args: nary_args,
442 11923 : });
443 11923 : state.nary_expressions.len() as u32 - 1
444 : };
445 23846 : for &arg in args {
446 23846 : match arg {
447 14682 : ExprVariant::Node(node) => self.push_back(nary_args, node),
448 9164 : ExprVariant::Nary(child_id) => {
449 9164 : let child = self.state.borrow().nary_expressions[child_id as usize];
450 9164 : if child.op != op {
451 1313 : let node = self.expression(arg);
452 1313 : self.push_back(nary_args, node);
453 7853 : } else {
454 7851 : self.append(nary_args, child.args);
455 7851 : }
456 : }
457 : }
458 : }
459 11923 : Some(ExprVariant::Nary(id))
460 34070 : }
461 :
462 : // -----------------------------------------------------------------------------------------
463 : // Names
464 : // -----------------------------------------------------------------------------------------
465 :
466 : /// A name from a keyword. The symbol span, a span of token indexes, is registered as the name
467 : /// location (see docs/design/core_quirks.md).
468 1577 : pub fn name_from_keyword(&self, loc: SymbolSpan, text: &str) -> Node {
469 1577 : let id = self.state.borrow_mut().names.register(text, TextSpan::new(loc.offset(), loc.length()));
470 1577 : Node::new(&loc, NodeType::NAME, AttributeKey::NONE, NO_PARENT, id, 0)
471 1577 : }
472 :
473 : /// A name from a string literal. Only double quotes are trimmed, so single quotes are kept.
474 49 : pub fn name_from_string_literal(&self, loc: SymbolSpan) -> Node {
475 49 : let text = self.text_at(loc).trim_matches('"');
476 49 : let id = self.state.borrow_mut().names.register(text, TextSpan::new(loc.offset(), loc.length()));
477 49 : Node::new(&loc, NodeType::NAME, AttributeKey::NONE, NO_PARENT, id, 0)
478 49 : }
479 :
480 : /// Mark a trailing dot
481 48 : pub fn trailing_dot(&self, loc: SymbolSpan) -> Node {
482 48 : self.add_error(loc, "name has a trailing dot");
483 48 : Node::new(&loc, NodeType::OBJECT_EXT_TRAILING_DOT, AttributeKey::NONE, NO_PARENT, 0, 0)
484 48 : }
485 :
486 : // -----------------------------------------------------------------------------------------
487 : // Checks
488 : // -----------------------------------------------------------------------------------------
489 :
490 : /// The unit of a sample count written without one: the sampling methods of the SQL standard
491 : /// (`bernoulli`, `system`) take a percentage, every other sample takes a number of rows
492 11 : pub fn bare_sample_unit(&self, method: &Node, loc: SymbolSpan) -> Node {
493 11 : let is_percentage = method.node_type() == NodeType::NAME && {
494 11 : let state = self.state.borrow();
495 11 : matches!(state.names.get(method.children_begin_or_value()).text.as_str(), "bernoulli" | "system")
496 : };
497 11 : let unit = if is_percentage { SampleCountUnit::PERCENT } else { SampleCountUnit::ROWS };
498 11 : Node::new(&loc, NodeType::ENUM_SQL_SAMPLE_UNIT_TYPE, AttributeKey::NONE, NO_PARENT, unit.0 as u32, 0)
499 11 : }
500 :
501 : /// Report a FROM keyword that is not followed by a table reference. The rule stays lenient to
502 : /// keep the tree of an unfinished statement, but only the end of the input may follow the keyword.
503 33 : pub fn require_table_ref_after_from(&self, from: SymbolSpan) {
504 33 : let next = (from.offset() + from.length()) as usize;
505 33 : if self.symbols.get(next).is_some_and(|symbol| symbol.kind != crate::symbol_kind::S_YYEOF) {
506 18 : self.error(from, "expected a table reference after FROM");
507 29 : }
508 33 : }
509 :
510 : /// Read the precision of a float type
511 10 : pub fn read_float_type(&self, bits_loc: SymbolSpan) -> NumericType {
512 10 : let text = self.text_at(bits_loc);
513 10 : let digits: &str = &text[..text.bytes().take_while(u8::is_ascii_digit).count()];
514 10 : let bits: i64 = digits.parse().unwrap_or(0);
515 10 : if bits < 1 {
516 2 : self.add_error(bits_loc, "precision for float type must be least 1 bit");
517 8 : } else if bits < 24 {
518 4 : return NumericType::FLOAT4;
519 4 : } else if bits < 53 {
520 2 : return NumericType::FLOAT8;
521 2 : } else {
522 2 : self.add_error(bits_loc, "precision for float type must be less than 54 bits");
523 2 : }
524 4 : NumericType::FLOAT4
525 10 : }
526 :
527 : /// Require punctuation tokens to be adjacent in the source text
528 233 : pub fn require_adjacent(&self, left: SymbolSpan, right: SymbolSpan, spelling: &str) {
529 233 : let l = self.resolve_text_span(left);
530 233 : let r = self.resolve_text_span(right);
531 233 : if l.end() != r.offset {
532 12 : self.add_error(super::actions::loc(&[left, right]), &format!("expected adjacent punctuation \"{spelling}\""));
533 221 : }
534 233 : }
535 :
536 : /// Require a generic operator token to use an exact spelling
537 71 : pub fn require_operator(&self, loc: SymbolSpan, spelling: &str) {
538 71 : if self.text_at(loc) != spelling {
539 2 : self.add_error(loc, &format!("expected operator \"{spelling}\""));
540 69 : }
541 71 : }
542 :
543 : // -----------------------------------------------------------------------------------------
544 : // Statements and errors
545 : // -----------------------------------------------------------------------------------------
546 :
547 : /// Add a statement
548 13837 : pub fn add_statement(&self, node: Node) {
549 13837 : if node.node_type() == NodeType::NONE {
550 4900 : return;
551 8937 : }
552 8937 : let root = self.add_node(node);
553 8937 : let mut state = self.state.borrow_mut();
554 8937 : let statement_type = match node.node_type() {
555 31 : NodeType::OBJECT_EXT_SET => StatementType::SET,
556 74 : NodeType::OBJECT_SQL_CREATE_AS => StatementType::CREATE_TABLE_AS,
557 1730 : NodeType::OBJECT_SQL_CREATE => StatementType::CREATE_TABLE,
558 75 : NodeType::OBJECT_SQL_VIEW => StatementType::CREATE_VIEW,
559 75 : NodeType::OBJECT_SQL_CREATE_FUNCTION => StatementType::CREATE_FUNCTION,
560 5934 : NodeType::OBJECT_SQL_SELECT => select_statement_type(&state.nodes, node),
561 67 : NodeType::OBJECT_SQL_DROP_TABLE => StatementType::DROP_TABLE,
562 28 : NodeType::OBJECT_SQL_DROP_VIEW => StatementType::DROP_VIEW,
563 155 : NodeType::OBJECT_SQL_ALTER_TABLE => StatementType::ALTER_TABLE,
564 14 : NodeType::OBJECT_SQL_ALTER_VIEW => StatementType::ALTER_VIEW,
565 8 : NodeType::OBJECT_SQL_CREATE_SCHEMA => StatementType::CREATE_SCHEMA,
566 17 : NodeType::OBJECT_SQL_DROP_SCHEMA => StatementType::DROP_SCHEMA,
567 8 : NodeType::OBJECT_SQL_ALTER_SCHEMA => StatementType::ALTER_SCHEMA,
568 21 : NodeType::OBJECT_SQL_ATTACH_DATABASE => StatementType::ATTACH_DATABASE,
569 194 : NodeType::OBJECT_SQL_INSERT => StatementType::INSERT,
570 100 : NodeType::OBJECT_SQL_DELETE => StatementType::DELETE,
571 195 : NodeType::OBJECT_EXT_EXPLAIN => StatementType::EXPLAIN,
572 211 : NodeType::OBJECT_SQL_CALL => StatementType::CALL,
573 0 : other => panic!("unexpected statement root {:?}", other.variant_name()),
574 : };
575 8937 : let nodes_len = state.nodes.len() as u32;
576 8937 : let mut statement = state.current_statement;
577 8937 : statement.root = root;
578 8937 : statement.statement_type = statement_type;
579 8937 : statement.node_count = nodes_len - statement.nodes_begin;
580 8937 : state.statements.push(statement);
581 8937 : state.current_statement = Statement {
582 8937 : nodes_begin: nodes_len,
583 8937 : ..Default::default()
584 8937 : };
585 13837 : }
586 :
587 : /// Drop the nodes of the current statement after an error
588 444 : pub fn reset_statement(&self) {
589 444 : let mut state = self.state.borrow_mut();
590 444 : state.current_statement.nodes_begin = state.nodes.len() as u32;
591 444 : }
592 :
593 : /// Add an error without a hint
594 66 : pub fn add_error(&self, loc: SymbolSpan, message: &str) {
595 66 : self.state.borrow_mut().errors.push(ParseError {
596 66 : location: loc,
597 66 : message: message.to_string(),
598 66 : hint: String::new(),
599 66 : });
600 66 : }
601 :
602 : /// Report an error from the parser or an action, attaching the pending hint
603 375 : pub fn error(&self, loc: SymbolSpan, message: &str) {
604 375 : let mut state = self.state.borrow_mut();
605 375 : let hint = std::mem::take(&mut state.pending_hint);
606 375 : state.errors.push(ParseError {
607 375 : location: loc,
608 375 : message: message.to_string(),
609 375 : hint,
610 375 : });
611 375 : }
612 :
613 : /// Drop the lookahead after the action (`yyclearin`)
614 713 : pub fn clear_lookahead(&self) {
615 713 : self.state.borrow_mut().clear_lookahead = true;
616 713 : }
617 : }
618 :
619 : /// SELECT or SELECT INTO, following the inputs of set operations
620 5934 : fn select_statement_type(nodes: &[Node], root: Node) -> StatementType {
621 5934 : let mut current = root;
622 5979 : while current.node_type() == NodeType::OBJECT_SQL_SELECT {
623 5979 : let mut next = None;
624 5979 : let begin = current.children_begin_or_value() as usize;
625 14489 : for child in &nodes[begin..begin + current.children_count() as usize] {
626 14489 : if child.attribute_key() == AttributeKey::SQL_SELECT_INTO && child.node_type() != NodeType::NONE {
627 56 : return StatementType::SELECT_INTO;
628 14433 : }
629 14433 : if child.attribute_key() == AttributeKey::SQL_COMBINE_INPUT
630 45 : && child.node_type() == NodeType::ARRAY
631 45 : && child.children_count() > 0
632 45 : {
633 45 : next = Some(nodes[child.children_begin_or_value() as usize]);
634 14388 : }
635 : }
636 5923 : match next {
637 45 : Some(n) => current = n,
638 5878 : None => break,
639 : }
640 : }
641 5878 : StatementType::SELECT
642 5934 : }
643 :
644 : /// Resolve a span of symbol indexes to a span of bytes
645 239983 : pub fn resolve_text_span(text: &str, symbols: &[Symbol], span: SymbolSpan) -> TextSpan {
646 239983 : if span.length() == 0 {
647 244 : return match symbols.get(span.offset() as usize) {
648 244 : Some(symbol) => TextSpan::new(symbol.location.offset, 0),
649 0 : None => TextSpan::new(text.len() as u32, 0),
650 : };
651 239739 : }
652 239739 : let first = symbols[span.offset() as usize].location;
653 239739 : let last = symbols[(span.offset() + span.length() - 1) as usize].location;
654 239739 : TextSpan::new(first.offset, last.end() - first.offset)
655 239983 : }
|