1use crate::{
16 ExpressionSyntax, GraphEdgeDirection, GraphEdgePatternSyntax, GraphElementPatternSyntax,
17 GraphPathFactorSyntax, GraphPathPrimarySyntax, GraphPathSyntax, GraphPatternQuantifier,
18 GraphPatternSyntax, GraphTable, GraphTableColumn, Identifier, LabeledExpressionSyntax,
19 PgqStatement, PostgresSelectSyntax, PostgresStatementSyntax, QualifiedName, Span, SyntaxError,
20 SyntaxErrorCode, TableAlias, Token, TokenKind,
21};
22
23mod expression;
24mod frontend;
25mod property_graph;
26mod select;
27
28pub fn parse_postgres_statement(input: &str) -> Result<PostgresStatementSyntax, SyntaxError> {
29 match frontend::parse(input, "SqlInput")? {
30 frontend::Output::Select(select) => Ok(PostgresStatementSyntax::Select(select)),
31 frontend::Output::Create(create) => {
32 Ok(PostgresStatementSyntax::CreatePropertyGraph(*create))
33 }
34 frontend::Output::Explain { .. } | frontend::Output::GraphTable(_) => {
35 unreachable!("SQL entry excludes standalone GRAPH_TABLE")
36 }
37 }
38}
39
40pub fn parse_relational_statement(
42 input: &str,
43) -> Result<crate::RelationalStatementSyntax, SyntaxError> {
44 match frontend::parse(input, "RelationalStatementInput")? {
45 frontend::Output::Select(select) => Ok(crate::RelationalStatementSyntax::Select(select)),
46 frontend::Output::Explain { analyze, select } => {
47 Ok(crate::RelationalStatementSyntax::Explain { analyze, select })
48 }
49 _ => unreachable!("relational entry returns SELECT or EXPLAIN SELECT"),
50 }
51}
52
53pub fn parse_postgres_select(input: &str) -> Result<PostgresSelectSyntax, SyntaxError> {
54 let frontend::Output::Select(select) = frontend::parse(input, "SelectInput")? else {
55 unreachable!("SELECT entry produces a SELECT AST")
56 };
57 Ok(*select)
58}
59
60pub fn parse_pgq_statement(input: &str) -> Result<PgqStatement, SyntaxError> {
61 let frontend::Output::Create(create) = frontend::parse(input, "PgqInput")? else {
62 unreachable!("PGQ entry produces CREATE PROPERTY GRAPH")
63 };
64 Ok(PgqStatement::CreatePropertyGraph(*create))
65}
66
67pub fn parse_graph_table(input: &str) -> Result<GraphTable, SyntaxError> {
68 let frontend::Output::GraphTable(table) = frontend::parse(input, "GraphTableInput")? else {
69 unreachable!("GRAPH_TABLE entry produces a GRAPH_TABLE AST")
70 };
71 Ok(*table)
72}
73
74const MAX_GRAPH_PATTERN_NESTING: usize = 128;
75const MAX_EXPRESSION_NESTING: usize = 128;
76
77struct Parser<'a> {
78 input: &'a str,
79 tokens: &'a [Token],
80 position: usize,
81 graph_pattern_nesting: usize,
82}
83
84struct ParsedGraphElementFields {
85 variable: Option<Identifier>,
86 labels: Vec<Identifier>,
87 predicate: Option<ExpressionSyntax>,
88}
89
90impl<'a> Parser<'a> {
91 fn new(input: &'a str, tokens: &'a [Token]) -> Self {
92 Self {
93 input,
94 tokens,
95 position: 0,
96 graph_pattern_nesting: 0,
97 }
98 }
99
100 fn parse_identifier_list(&mut self) -> Result<Vec<Identifier>, SyntaxError> {
101 self.expect_kind(TokenKind::LeftParen, "(")?;
102 let identifiers = self.parse_nonempty_comma_separated(
103 TokenKind::RightParen,
104 Self::parse_identifier,
105 "at least one identifier",
106 )?;
107 self.expect_kind(TokenKind::RightParen, ")")?;
108 Ok(identifiers)
109 }
110
111 fn parse_labeled_expressions(
112 &mut self,
113 expected: &'static str,
114 ) -> Result<Vec<LabeledExpressionSyntax>, SyntaxError> {
115 if self.current().kind == TokenKind::RightParen {
116 return Err(self.unexpected(expected));
117 }
118 let mut expressions = Vec::new();
119 loop {
120 let start_position = self.position;
121 let end_position = self.scan_to_top_level_delimiter()?;
122 expressions.push(self.labeled_expression_from_range(start_position, end_position)?);
123 if !self.consume_kind(TokenKind::Comma) {
124 break;
125 }
126 }
127 Ok(expressions)
128 }
129
130 fn parse_graph_pattern(&mut self) -> Result<GraphPatternSyntax, SyntaxError> {
131 let start = self.current().span.start;
132 let mut paths = vec![self.parse_graph_path()?];
133 while self.consume_kind(TokenKind::Comma) {
134 paths.push(self.parse_graph_path()?);
135 }
136 let predicate = if self.consume_keyword("WHERE") {
137 Some(self.parse_expression_until_keyword("COLUMNS", "an expression after WHERE")?)
138 } else {
139 None
140 };
141 let end = predicate.as_ref().map_or_else(
142 || paths.last().expect("graph path exists").span.end,
143 |value| value.span.end,
144 );
145 Ok(GraphPatternSyntax {
146 paths,
147 predicate,
148 span: Span::new(start, end),
149 })
150 }
151
152 fn parse_graph_path(&mut self) -> Result<GraphPathSyntax, SyntaxError> {
153 let start = self.current().span.start;
154 let mut factors = Vec::new();
155 while self.can_start_graph_primary() {
156 factors.push(self.parse_graph_path_factor()?);
157 }
158 if factors.is_empty() {
159 return Err(self.unexpected("a graph path pattern"));
160 }
161 Ok(GraphPathSyntax {
162 span: Span::new(start, self.previous_end()),
163 factors,
164 })
165 }
166
167 fn parse_graph_path_factor(&mut self) -> Result<GraphPathFactorSyntax, SyntaxError> {
168 let start = self.current().span.start;
169 let primary = self.parse_graph_path_primary()?;
170 let quantifier = self.parse_optional_graph_quantifier()?;
171 Ok(GraphPathFactorSyntax {
172 primary,
173 quantifier,
174 span: Span::new(start, self.previous_end()),
175 })
176 }
177
178 fn parse_graph_path_primary(&mut self) -> Result<GraphPathPrimarySyntax, SyntaxError> {
179 if self.current().kind == TokenKind::LeftParen {
180 return self.parse_parenthesized_or_vertex_pattern();
181 }
182 self.parse_graph_edge_pattern()
183 .map(GraphPathPrimarySyntax::Edge)
184 }
185
186 fn parse_parenthesized_or_vertex_pattern(
187 &mut self,
188 ) -> Result<GraphPathPrimarySyntax, SyntaxError> {
189 let start = self.expect_kind(TokenKind::LeftParen, "(")?.span.start;
190 if self.can_start_graph_primary() {
191 if self.graph_pattern_nesting >= MAX_GRAPH_PATTERN_NESTING {
192 return Err(SyntaxError::new(
193 SyntaxErrorCode::GraphPatternNestingLimitExceeded,
194 Span::new(start, self.current().span.end),
195 ));
196 }
197 self.graph_pattern_nesting += 1;
198 let nested = self.parse_nested_graph_path(start);
199 self.graph_pattern_nesting -= 1;
200 return nested;
201 }
202
203 let fields = self.parse_graph_element_fields(TokenKind::RightParen)?;
204 self.expect_kind(TokenKind::RightParen, ")")?;
205 Ok(GraphPathPrimarySyntax::Vertex(GraphElementPatternSyntax {
206 variable: fields.variable,
207 labels: fields.labels,
208 predicate: fields.predicate,
209 span: Span::new(start, self.previous_end()),
210 }))
211 }
212
213 fn parse_nested_graph_path(
214 &mut self,
215 start: usize,
216 ) -> Result<GraphPathPrimarySyntax, SyntaxError> {
217 let path = Box::new(self.parse_graph_path()?);
218 let predicate =
219 if self.consume_keyword("WHERE") {
220 Some(self.parse_expression_until_kind(
221 TokenKind::RightParen,
222 "an expression after WHERE",
223 )?)
224 } else {
225 None
226 };
227 self.expect_kind(TokenKind::RightParen, ")")?;
228 Ok(GraphPathPrimarySyntax::Parenthesized {
229 path,
230 predicate,
231 span: Span::new(start, self.previous_end()),
232 })
233 }
234
235 fn parse_graph_edge_pattern(&mut self) -> Result<GraphEdgePatternSyntax, SyntaxError> {
236 let start = self.current().span.start;
237 match self.current().kind {
238 TokenKind::ArrowLeft => {
239 self.advance();
240 self.parse_left_edge_tail(start)
241 }
242 TokenKind::Less => {
243 self.advance();
244 self.expect_kind(TokenKind::Minus, "- after <")?;
245 self.parse_left_edge_tail(start)
246 }
247 TokenKind::ArrowRight => {
248 self.advance();
249 Ok(self.abbreviated_edge(start, GraphEdgeDirection::Right))
250 }
251 TokenKind::Minus => {
252 self.advance();
253 if self.consume_kind(TokenKind::LeftBracket) {
254 let fields = self.parse_graph_element_fields(TokenKind::RightBracket)?;
255 self.expect_kind(TokenKind::RightBracket, "]")?;
256 let direction = if self.consume_kind(TokenKind::ArrowRight) {
257 GraphEdgeDirection::Right
258 } else {
259 self.expect_kind(TokenKind::Minus, "- or -> after edge pattern")?;
260 if self.consume_kind(TokenKind::Greater) {
261 GraphEdgeDirection::Right
262 } else {
263 GraphEdgeDirection::Any
264 }
265 };
266 Ok(GraphEdgePatternSyntax {
267 direction,
268 variable: fields.variable,
269 labels: fields.labels,
270 predicate: fields.predicate,
271 abbreviated: false,
272 span: Span::new(start, self.previous_end()),
273 })
274 } else {
275 let direction = if self.consume_kind(TokenKind::Greater) {
276 GraphEdgeDirection::Right
277 } else {
278 GraphEdgeDirection::Any
279 };
280 Ok(self.abbreviated_edge(start, direction))
281 }
282 }
283 _ => Err(self.unexpected("a graph vertex or edge pattern")),
284 }
285 }
286
287 fn parse_left_edge_tail(
288 &mut self,
289 start: usize,
290 ) -> Result<GraphEdgePatternSyntax, SyntaxError> {
291 if !self.consume_kind(TokenKind::LeftBracket) {
292 return Ok(self.abbreviated_edge(start, GraphEdgeDirection::Left));
293 }
294 let fields = self.parse_graph_element_fields(TokenKind::RightBracket)?;
295 self.expect_kind(TokenKind::RightBracket, "]")?;
296 self.expect_kind(TokenKind::Minus, "- after left edge pattern")?;
297 Ok(GraphEdgePatternSyntax {
298 direction: GraphEdgeDirection::Left,
299 variable: fields.variable,
300 labels: fields.labels,
301 predicate: fields.predicate,
302 abbreviated: false,
303 span: Span::new(start, self.previous_end()),
304 })
305 }
306
307 fn abbreviated_edge(
308 &self,
309 start: usize,
310 direction: GraphEdgeDirection,
311 ) -> GraphEdgePatternSyntax {
312 GraphEdgePatternSyntax {
313 direction,
314 variable: None,
315 labels: Vec::new(),
316 predicate: None,
317 abbreviated: true,
318 span: Span::new(start, self.previous_end()),
319 }
320 }
321
322 fn parse_graph_element_fields(
323 &mut self,
324 terminator: TokenKind,
325 ) -> Result<ParsedGraphElementFields, SyntaxError> {
326 let variable = if is_identifier_kind(self.current().kind)
327 && !self.at_keyword("IS")
328 && !self.at_keyword("WHERE")
329 {
330 Some(self.parse_identifier()?)
331 } else {
332 None
333 };
334 let labels = if self.consume_keyword("IS") {
335 let mut labels = vec![self.parse_identifier()?];
336 while self.consume_kind(TokenKind::Pipe) {
337 labels.push(self.parse_identifier()?);
338 }
339 labels
340 } else {
341 Vec::new()
342 };
343 let predicate = if self.consume_keyword("WHERE") {
344 Some(self.parse_expression_until_kind(terminator, "an expression after WHERE")?)
345 } else {
346 None
347 };
348 Ok(ParsedGraphElementFields {
349 variable,
350 labels,
351 predicate,
352 })
353 }
354
355 fn parse_optional_graph_quantifier(
356 &mut self,
357 ) -> Result<Option<GraphPatternQuantifier>, SyntaxError> {
358 if !self.consume_kind(TokenKind::LeftBrace) {
359 return Ok(None);
360 }
361 let start = self.tokens[self.position - 1].span.start;
362 let (min, max) = if self.consume_kind(TokenKind::Comma) {
363 (0, self.parse_nonnegative_integer()?)
364 } else {
365 let min = self.parse_nonnegative_integer()?;
366 if self.consume_kind(TokenKind::RightBrace) {
367 return Ok(Some(GraphPatternQuantifier {
368 min,
369 max: min,
370 span: Span::new(start, self.previous_end()),
371 }));
372 }
373 self.expect_kind(TokenKind::Comma, ", or } in graph pattern quantifier")?;
374 (min, self.parse_nonnegative_integer()?)
375 };
376 self.expect_kind(TokenKind::RightBrace, "}")?;
377 Ok(Some(GraphPatternQuantifier {
378 min,
379 max,
380 span: Span::new(start, self.previous_end()),
381 }))
382 }
383
384 fn parse_nonnegative_integer(&mut self) -> Result<u32, SyntaxError> {
385 let token = self.current();
386 if token.kind != TokenKind::Number {
387 return Err(self.unexpected("a non-negative integer"));
388 }
389 let value = token
390 .text(self.input)
391 .parse::<u32>()
392 .map_err(|_| self.unexpected("a non-negative integer"))?;
393 self.advance();
394 Ok(value)
395 }
396
397 fn can_start_graph_primary(&self) -> bool {
398 matches!(
399 self.current().kind,
400 TokenKind::LeftParen
401 | TokenKind::ArrowLeft
402 | TokenKind::ArrowRight
403 | TokenKind::Less
404 | TokenKind::Minus
405 )
406 }
407
408 fn parse_graph_table_columns(&mut self) -> Result<Vec<GraphTableColumn>, SyntaxError> {
409 if self.current().kind == TokenKind::RightParen {
410 return Err(self.unexpected("at least one GRAPH_TABLE column"));
411 }
412 let mut columns = Vec::new();
413 loop {
414 let start_position = self.position;
415 let end_position = self.scan_to_top_level_delimiter()?;
416 columns.push(self.graph_table_column_from_range(start_position, end_position)?);
417 if !self.consume_kind(TokenKind::Comma) {
418 break;
419 }
420 }
421 Ok(columns)
422 }
423
424 fn graph_table_column_from_range(
425 &self,
426 start_position: usize,
427 end_position: usize,
428 ) -> Result<GraphTableColumn, SyntaxError> {
429 let expression = self.labeled_expression_from_range(start_position, end_position)?;
430 Ok(GraphTableColumn {
431 expression: expression.expression,
432 alias: expression.alias,
433 span: expression.span,
434 })
435 }
436
437 fn labeled_expression_from_range(
438 &self,
439 start_position: usize,
440 end_position: usize,
441 ) -> Result<LabeledExpressionSyntax, SyntaxError> {
442 if start_position == end_position {
443 return Err(self.unexpected("an expression"));
444 }
445 let mut alias_position = None;
446 let mut depths = Depths::default();
447 for position in start_position..end_position {
448 let token = self.tokens[position];
449 self.update_expression_depths(&mut depths, token)?;
450 if depths.is_zero() && token.is_keyword(self.input, "AS") {
451 alias_position = Some(position);
452 }
453 }
454 let (expression_end_position, alias) = if let Some(as_position) = alias_position {
455 let alias_token = self.tokens.get(as_position + 1).copied().ok_or_else(|| {
456 SyntaxError::new(SyntaxErrorCode::UnexpectedEnd, self.current().span)
457 .expected("a GRAPH_TABLE column alias")
458 })?;
459 if as_position + 2 != end_position || !is_identifier_kind(alias_token.kind) {
460 return Err(
461 SyntaxError::new(SyntaxErrorCode::UnexpectedToken, alias_token.span)
462 .expected("one column alias after AS")
463 .found(alias_token.text(self.input)),
464 );
465 }
466 (as_position, Some(identifier_from_token(alias_token)))
467 } else {
468 (end_position, None)
469 };
470 let start = self.tokens[start_position].span.start;
471 let end = self.tokens[end_position - 1].span.end;
472 if start_position == expression_end_position {
473 return Err(
474 SyntaxError::new(SyntaxErrorCode::UnexpectedToken, Span::new(start, end))
475 .expected("an expression before AS"),
476 );
477 }
478 Ok(LabeledExpressionSyntax {
479 expression: self.parse_expression_range(start_position, expression_end_position)?,
480 alias,
481 span: Span::new(start, end),
482 })
483 }
484
485 fn parse_optional_table_alias(&mut self) -> Result<Option<TableAlias>, SyntaxError> {
486 let has_as = self.consume_keyword("AS");
487 if !has_as && (!is_identifier_kind(self.current().kind) || self.at_table_alias_boundary()) {
488 return Ok(None);
489 }
490 if has_as && self.at_table_alias_boundary() {
491 return Err(self.unexpected("a table alias"));
492 }
493 let start = self.current().span.start;
494 let name = self.parse_identifier()?;
495 let columns = if self.current().kind == TokenKind::LeftParen {
496 self.parse_identifier_list()?
497 } else {
498 Vec::new()
499 };
500 Ok(Some(TableAlias {
501 name,
502 columns,
503 span: Span::new(start, self.previous_end()),
504 }))
505 }
506
507 fn at_table_alias_boundary(&self) -> bool {
508 matches!(
509 self.current().kind,
510 TokenKind::Comma | TokenKind::RightParen | TokenKind::Semicolon | TokenKind::End
511 ) || [
512 "WHERE",
513 "GROUP",
514 "HAVING",
515 "ORDER",
516 "LIMIT",
517 "OFFSET",
518 "FETCH",
519 "FOR",
520 "JOIN",
521 "INNER",
522 "LEFT",
523 "RIGHT",
524 "FULL",
525 "CROSS",
526 "ON",
527 "USING",
528 "NATURAL",
529 "UNION",
530 "EXCEPT",
531 "INTERSECT",
532 "LATERAL",
533 "TABLESAMPLE",
534 "WINDOW",
535 ]
536 .into_iter()
537 .any(|keyword| self.at_keyword(keyword))
538 }
539
540 fn parse_expression_until_keyword(
541 &mut self,
542 keyword: &'static str,
543 expected: &'static str,
544 ) -> Result<ExpressionSyntax, SyntaxError> {
545 let start_position = self.position;
546 let mut depths = Depths::default();
547 while self.current().kind != TokenKind::End {
548 if depths.is_zero() && self.at_keyword(keyword) {
549 if start_position == self.position {
550 return Err(self.unexpected(expected));
551 }
552 return self.parse_expression_range(start_position, self.position);
553 }
554 self.update_expression_depths(&mut depths, self.current())?;
555 self.advance();
556 }
557 if !depths.is_zero() {
558 return Err(self.unclosed_expression_error(&depths));
559 }
560 Err(SyntaxError::new(SyntaxErrorCode::UnexpectedEnd, self.current().span).expected(keyword))
561 }
562
563 fn parse_expression_until_kind(
564 &mut self,
565 terminator: TokenKind,
566 expected: &'static str,
567 ) -> Result<ExpressionSyntax, SyntaxError> {
568 let start_position = self.position;
569 let mut depths = Depths::default();
570 while self.current().kind != TokenKind::End {
571 if depths.is_zero() && self.current().kind == terminator {
572 if start_position == self.position {
573 return Err(self.unexpected(expected));
574 }
575 return self.parse_expression_range(start_position, self.position);
576 }
577 self.update_expression_depths(&mut depths, self.current())?;
578 self.advance();
579 }
580 if !depths.is_zero() {
581 return Err(self.unclosed_expression_error(&depths));
582 }
583 Err(
584 SyntaxError::new(SyntaxErrorCode::UnexpectedEnd, self.current().span)
585 .expected("a closing graph element delimiter"),
586 )
587 }
588
589 fn scan_to_top_level_delimiter(&mut self) -> Result<usize, SyntaxError> {
590 let mut depths = Depths::default();
591 while self.current().kind != TokenKind::End {
592 if depths.is_zero()
593 && matches!(
594 self.current().kind,
595 TokenKind::Comma | TokenKind::RightParen
596 )
597 {
598 return Ok(self.position);
599 }
600 self.update_expression_depths(&mut depths, self.current())?;
601 self.advance();
602 }
603 if !depths.is_zero() {
604 return Err(self.unclosed_expression_error(&depths));
605 }
606 Err(
607 SyntaxError::new(SyntaxErrorCode::UnexpectedEnd, self.current().span)
608 .expected("a comma or closing parenthesis"),
609 )
610 }
611
612 fn parse_qualified_name(&mut self) -> Result<QualifiedName, SyntaxError> {
613 let first = self.parse_identifier()?;
614 let start = first.span.start;
615 let mut end = first.span.end;
616 let mut parts = vec![first];
617 while self.consume_kind(TokenKind::Dot) {
618 let part = self.parse_identifier()?;
619 end = part.span.end;
620 parts.push(part);
621 }
622 Ok(QualifiedName {
623 parts,
624 span: Span::new(start, end),
625 })
626 }
627
628 fn parse_identifier(&mut self) -> Result<Identifier, SyntaxError> {
629 let token = self.current();
630 if !is_identifier_kind(token.kind) {
631 return Err(self.unexpected("an identifier"));
632 }
633 self.advance();
634 Ok(identifier_from_token(token))
635 }
636
637 fn parse_comma_separated<T>(
638 &mut self,
639 terminator: TokenKind,
640 parse_item: fn(&mut Self) -> Result<T, SyntaxError>,
641 ) -> Result<Vec<T>, SyntaxError> {
642 if self.current().kind == terminator {
643 return Ok(Vec::new());
644 }
645 let mut items = Vec::new();
646 loop {
647 items.push(parse_item(self)?);
648 if !self.consume_kind(TokenKind::Comma) {
649 break;
650 }
651 }
652 Ok(items)
653 }
654
655 fn parse_nonempty_comma_separated<T>(
656 &mut self,
657 terminator: TokenKind,
658 parse_item: fn(&mut Self) -> Result<T, SyntaxError>,
659 expected: &'static str,
660 ) -> Result<Vec<T>, SyntaxError> {
661 if self.current().kind == terminator {
662 return Err(self.unexpected(expected));
663 }
664 self.parse_comma_separated(terminator, parse_item)
665 }
666
667 fn current(&self) -> Token {
668 self.tokens
669 .get(self.position)
670 .copied()
671 .unwrap_or(Token::new(
672 TokenKind::End,
673 Span::new(self.input.len(), self.input.len()),
674 ))
675 }
676
677 fn previous_end(&self) -> usize {
678 self.position
679 .checked_sub(1)
680 .and_then(|position| self.tokens.get(position))
681 .map_or(0, |token| token.span.end)
682 }
683
684 fn advance(&mut self) -> Token {
685 let token = self.current();
686 if token.kind != TokenKind::End {
687 self.position += 1;
688 }
689 token
690 }
691
692 fn at_keyword(&self, keyword: &str) -> bool {
693 self.current().is_keyword(self.input, keyword)
694 }
695
696 fn consume_keyword(&mut self, keyword: &str) -> bool {
697 if self.at_keyword(keyword) {
698 self.advance();
699 true
700 } else {
701 false
702 }
703 }
704
705 fn expect_keyword(&mut self, keyword: &'static str) -> Result<Token, SyntaxError> {
706 if self.at_keyword(keyword) {
707 Ok(self.advance())
708 } else {
709 Err(self.unexpected(keyword))
710 }
711 }
712
713 fn consume_kind(&mut self, kind: TokenKind) -> bool {
714 if self.current().kind == kind {
715 self.advance();
716 true
717 } else {
718 false
719 }
720 }
721
722 fn expect_kind(
723 &mut self,
724 kind: TokenKind,
725 expected: &'static str,
726 ) -> Result<Token, SyntaxError> {
727 if self.current().kind == kind {
728 Ok(self.advance())
729 } else {
730 Err(self.unexpected(expected))
731 }
732 }
733
734 fn unexpected(&self, expected: &'static str) -> SyntaxError {
735 let token = self.current();
736 let code = if token.kind == TokenKind::End {
737 SyntaxErrorCode::UnexpectedEnd
738 } else {
739 SyntaxErrorCode::UnexpectedToken
740 };
741 SyntaxError::new(code, token.span)
742 .expected(expected)
743 .found(token.text(self.input))
744 }
745
746 fn update_expression_depths(
747 &self,
748 depths: &mut Depths,
749 token: Token,
750 ) -> Result<(), SyntaxError> {
751 depths.update(token.kind).map_err(|error| match error {
752 DepthError::MismatchedDelimiter(expected) => {
753 SyntaxError::new(SyntaxErrorCode::UnexpectedToken, token.span)
754 .expected(expected)
755 .found(token.text(self.input))
756 }
757 DepthError::NestingLimitExceeded => {
758 SyntaxError::new(SyntaxErrorCode::ExpressionNestingLimitExceeded, token.span)
759 .expected("expression nesting within the configured parser limit")
760 }
761 })
762 }
763
764 fn unclosed_expression_error(&self, depths: &Depths) -> SyntaxError {
765 SyntaxError::new(SyntaxErrorCode::UnexpectedEnd, self.current().span)
766 .expected(depths.expected_closing().unwrap_or("a closing delimiter"))
767 }
768}
769
770#[derive(Debug)]
771struct Depths {
772 closing_delimiters: [TokenKind; MAX_EXPRESSION_NESTING],
773 len: usize,
774}
775
776impl Default for Depths {
777 fn default() -> Self {
778 Self {
779 closing_delimiters: [TokenKind::End; MAX_EXPRESSION_NESTING],
780 len: 0,
781 }
782 }
783}
784
785enum DepthError {
786 MismatchedDelimiter(&'static str),
787 NestingLimitExceeded,
788}
789
790impl Depths {
791 fn update(&mut self, kind: TokenKind) -> Result<(), DepthError> {
792 match kind {
793 TokenKind::LeftParen => self.push(TokenKind::RightParen)?,
794 TokenKind::LeftBracket => self.push(TokenKind::RightBracket)?,
795 TokenKind::LeftBrace => self.push(TokenKind::RightBrace)?,
796 TokenKind::RightParen | TokenKind::RightBracket | TokenKind::RightBrace => {
797 if self.last() != Some(kind) {
798 return Err(DepthError::MismatchedDelimiter(
799 self.expected_closing().unwrap_or("an opening delimiter"),
800 ));
801 }
802 self.len -= 1;
803 }
804 _ => return Ok(()),
805 }
806 Ok(())
807 }
808
809 fn is_zero(&self) -> bool {
810 self.len == 0
811 }
812
813 fn expected_closing(&self) -> Option<&'static str> {
814 match self.last() {
815 Some(TokenKind::RightParen) => Some(")"),
816 Some(TokenKind::RightBracket) => Some("]"),
817 Some(TokenKind::RightBrace) => Some("}"),
818 _ => None,
819 }
820 }
821
822 fn last(&self) -> Option<TokenKind> {
823 self.len
824 .checked_sub(1)
825 .map(|position| self.closing_delimiters[position])
826 }
827
828 fn push(&mut self, kind: TokenKind) -> Result<(), DepthError> {
829 if self.len == MAX_EXPRESSION_NESTING {
830 return Err(DepthError::NestingLimitExceeded);
831 }
832 self.closing_delimiters[self.len] = kind;
833 self.len += 1;
834 Ok(())
835 }
836}
837
838fn is_identifier_kind(kind: TokenKind) -> bool {
839 matches!(kind, TokenKind::Word | TokenKind::QuotedIdentifier)
840}
841
842fn identifier_from_token(token: Token) -> Identifier {
843 Identifier {
844 span: token.span,
845 quoted: token.kind == TokenKind::QuotedIdentifier,
846 }
847}