1use std::fmt::Display;
9use std::iter::Peekable;
10use std::path::Path;
11use std::str::Chars;
12
13use regex::Regex;
14use thiserror::Error;
15use tree_sitter::CaptureQuantifier;
16use tree_sitter::CaptureQuantifier::One;
17use tree_sitter::CaptureQuantifier::OneOrMore;
18use tree_sitter::CaptureQuantifier::Zero;
19use tree_sitter::CaptureQuantifier::ZeroOrMore;
20use tree_sitter::CaptureQuantifier::ZeroOrOne;
21use tree_sitter::Language;
22use tree_sitter::Query;
23use tree_sitter::QueryError;
24
25use crate::ast;
26use crate::parse_error::Excerpt;
27use crate::Identifier;
28
29pub const FULL_MATCH: &str = "__tsg__full_match";
30
31impl ast::File {
32 pub fn from_str(language: Language, source: &str) -> Result<Self, ParseError> {
34 let mut file = ast::File::new(language);
35 #[allow(deprecated)]
36 file.parse(source)?;
37 file.check()?;
38 Ok(file)
39 }
40
41 #[deprecated(
43 note = "Parsing multiple times into the same `File` instance is unsound. Use `File::from_str` instead."
44 )]
45 pub fn parse(&mut self, content: &str) -> Result<(), ParseError> {
46 Parser::new(content).parse_into_file(self)
47 }
48}
49
50#[derive(Debug, Error)]
55pub enum ParseError {
56 #[error("Expected quantifier at {0}")]
57 ExpectedQuantifier(Location),
58 #[error("Expected '{0}' at {1}")]
59 ExpectedToken(&'static str, Location),
60 #[error("Expected variable name at {0}")]
61 ExpectedVariable(Location),
62 #[error("Expected unscoped variable at {0}")]
63 ExpectedUnscopedVariable(Location),
64 #[error("Invalid regular expression /{0}/ at {1}")]
65 InvalidRegex(String, Location),
66 #[error("Expected integer constant in regex capture at {0}")]
67 InvalidRegexCapture(Location),
68 #[error("Invalid query pattern: {}", _0.message)]
69 QueryError(#[from] QueryError),
70 #[error("Unexpected character '{0}' in {1} at {2}")]
71 UnexpectedCharacter(char, &'static str, Location),
72 #[error("Unexpected end of file at {0}")]
73 UnexpectedEOF(Location),
74 #[error("Unexpected keyword '{0}' at {1}")]
75 UnexpectedKeyword(String, Location),
76 #[error("Unexpected literal '#{0}' at {1}")]
77 UnexpectedLiteral(String, Location),
78 #[error("Query contains multiple patterns at {0}")]
79 UnexpectedQueryPatterns(Location),
80 #[error(transparent)]
81 Check(#[from] crate::checker::CheckError),
82}
83
84impl ParseError {
85 pub fn display_pretty<'a>(
86 &'a self,
87 path: &'a Path,
88 source: &'a str,
89 ) -> impl std::fmt::Display + 'a {
90 DisplayParseErrorPretty {
91 error: self,
92 path,
93 source,
94 }
95 }
96}
97
98struct DisplayParseErrorPretty<'a> {
99 error: &'a ParseError,
100 path: &'a Path,
101 source: &'a str,
102}
103
104impl std::fmt::Display for DisplayParseErrorPretty<'_> {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 let location = match self.error {
107 ParseError::ExpectedQuantifier(location) => *location,
108 ParseError::ExpectedToken(_, location) => *location,
109 ParseError::ExpectedVariable(location) => *location,
110 ParseError::ExpectedUnscopedVariable(location) => *location,
111 ParseError::InvalidRegex(_, location) => *location,
112 ParseError::InvalidRegexCapture(location) => *location,
113 ParseError::QueryError(err) => Location {
114 row: err.row,
115 column: err.column,
116 },
117 ParseError::UnexpectedCharacter(_, _, location) => *location,
118 ParseError::UnexpectedEOF(location) => *location,
119 ParseError::UnexpectedKeyword(_, location) => *location,
120 ParseError::UnexpectedLiteral(_, location) => *location,
121 ParseError::UnexpectedQueryPatterns(location) => *location,
122 ParseError::Check(err) => {
123 write!(f, "{}", err.display_pretty(self.path, self.source))?;
124 return Ok(());
125 }
126 };
127 writeln!(f, "{}", self.error)?;
128 write!(
129 f,
130 "{}",
131 Excerpt::from_source(
132 self.path,
133 self.source,
134 location.row,
135 location.to_column_range(),
136 0
137 )
138 )?;
139 Ok(())
140 }
141}
142
143#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
148pub struct Location {
149 pub row: usize,
150 pub column: usize,
151}
152
153impl Location {
154 fn advance(&mut self, ch: char) {
155 if ch == '\n' {
156 self.row += 1;
157 self.column = 0;
158 } else {
159 self.column += 1;
160 }
161 }
162
163 pub(crate) fn to_column_range(&self) -> std::ops::Range<usize> {
164 self.column..self.column + 1
165 }
166}
167
168impl Display for Location {
169 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
170 write!(f, "({}, {})", self.row + 1, self.column + 1)
171 }
172}
173
174#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
179pub struct Range {
180 pub start: Location,
181 pub end: Location,
182}
183
184impl Display for Range {
185 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
186 write!(f, "{} - {}", self.start, self.end)
187 }
188}
189
190struct Parser<'a> {
194 source: &'a str,
195 chars: Peekable<Chars<'a>>,
196 offset: usize,
197 location: Location,
198 query_source: String,
199}
200
201fn is_ident_start(c: char) -> bool {
202 c == '_' || c.is_alphabetic()
203}
204
205fn is_ident(c: char) -> bool {
206 c == '_' || c == '-' || c.is_alphanumeric()
207}
208
209impl<'a> Parser<'a> {
210 fn new(source: &'a str) -> Parser<'a> {
211 let chars = source.chars().peekable();
212 let query_source = String::with_capacity(source.len());
213 Parser {
214 source,
215 chars,
216 offset: 0,
217 location: Location::default(),
218 query_source,
219 }
220 }
221}
222
223impl<'a> Parser<'a> {
224 fn peek(&mut self) -> Result<char, ParseError> {
225 self.chars
226 .peek()
227 .copied()
228 .ok_or_else(|| ParseError::UnexpectedEOF(self.location))
229 }
230
231 fn try_peek(&mut self) -> Option<char> {
232 self.peek().ok()
233 }
234
235 fn next(&mut self) -> Result<char, ParseError> {
236 let ch = self
237 .chars
238 .next()
239 .ok_or_else(|| ParseError::UnexpectedEOF(self.location))?;
240 self.offset += ch.len_utf8();
241 self.location.advance(ch);
242 Ok(ch)
243 }
244
245 fn skip(&mut self) -> Result<(), ParseError> {
246 self.next().map(|_| ())
247 }
248
249 fn consume_whitespace(&mut self) {
250 let mut in_comment = false;
251 while let Some(ch) = self.try_peek() {
252 if in_comment {
253 if ch == '\n' {
254 in_comment = false;
255 }
256 } else {
257 if ch == ';' {
258 in_comment = true;
259 } else if !ch.is_whitespace() {
260 return;
261 }
262 }
263 self.skip().unwrap();
264 }
265 }
266
267 fn consume_while(&mut self, mut f: impl FnMut(char) -> bool) {
268 while let Some(ch) = self.try_peek() {
269 if !f(ch) {
270 return;
271 }
272 self.skip().unwrap();
273 }
274 }
275
276 fn consume_n(&mut self, count: usize) -> Result<(), ParseError> {
277 for _ in 0..count {
278 self.next()?;
279 }
280 Ok(())
281 }
282
283 fn consume_token(&mut self, token: &'static str) -> Result<(), ParseError> {
284 if self.source[self.offset..].starts_with(token) {
285 self.consume_n(token.len())
286 } else {
287 Err(ParseError::ExpectedToken(token, self.location))
288 }
289 }
290
291 fn parse_into_file(&mut self, file: &mut ast::File) -> Result<(), ParseError> {
292 self.consume_whitespace();
293 while self.try_peek().is_some() {
294 if let Ok(_) = self.consume_token("attribute") {
295 self.consume_whitespace();
296 let shorthand = self.parse_shorthand()?;
297 file.shorthands.add(shorthand);
298 } else if let Ok(_) = self.consume_token("global") {
299 self.consume_whitespace();
300 let global = self.parse_global()?;
301 file.globals.push(global);
302 } else if let Ok(_) = self.consume_token("inherit") {
303 self.consume_whitespace();
304 self.consume_token(".")?;
305 let name = self.parse_identifier("inherit")?;
306 file.inherited_variables.insert(name);
307 } else {
308 let stanza = self.parse_stanza(&file.language)?;
309 file.stanzas.push(stanza);
310 }
311 self.consume_whitespace();
312 }
313 file.query = Some(Query::new(&file.language, &self.query_source).unwrap());
315 Ok(())
316 }
317
318 fn parse_global(&mut self) -> Result<ast::Global, ParseError> {
319 let location = self.location;
320 let name = self.parse_identifier("global variable")?;
321 let quantifier = self.parse_quantifier()?;
322 let mut default = None;
323 self.consume_whitespace();
324 if let Ok(_) = self.consume_token("=") {
325 self.consume_whitespace();
326 default = Some(self.parse_string()?);
327 }
328 Ok(ast::Global {
329 name,
330 quantifier,
331 default,
332 location,
333 })
334 }
335
336 fn parse_shorthand(&mut self) -> Result<ast::AttributeShorthand, ParseError> {
337 let location = self.location;
338 let name = self.parse_identifier("shorthand name")?;
339 self.consume_whitespace();
340 self.consume_token("=")?;
341 self.consume_whitespace();
342 let variable = self.parse_unscoped_variable()?;
343 self.consume_whitespace();
344 self.consume_token("=>")?;
345 self.consume_whitespace();
346 let attributes = self.parse_attributes()?;
347 Ok(ast::AttributeShorthand {
348 name,
349 variable,
350 attributes,
351 location,
352 })
353 }
354
355 fn parse_quantifier(&mut self) -> Result<CaptureQuantifier, ParseError> {
356 let mut quantifier = One;
357 if let Some(c) = self.try_peek() {
358 self.skip().unwrap();
359 if c == '?' {
360 quantifier = ZeroOrOne;
361 } else if c == '*' {
362 quantifier = ZeroOrMore;
363 } else if c == '+' {
364 quantifier = OneOrMore;
365 } else if !c.is_whitespace() {
366 return Err(ParseError::ExpectedQuantifier(self.location));
367 }
368 }
369 Ok(quantifier)
370 }
371
372 fn parse_stanza(&mut self, language: &Language) -> Result<ast::Stanza, ParseError> {
373 let start = self.location;
374 let (query, full_match_stanza_capture_index) = self.parse_query(language)?;
375 self.consume_whitespace();
376 let statements = self.parse_statements()?;
377 let end = self.location;
378 let range = Range { start, end };
379 Ok(ast::Stanza {
380 query,
381 statements,
382 full_match_stanza_capture_index,
383 full_match_file_capture_index: usize::MAX, range,
385 })
386 }
387
388 fn parse_query(&mut self, language: &Language) -> Result<(Query, usize), ParseError> {
389 let location = self.location;
390 let query_start = self.offset;
391 self.skip_query()?;
392 let query_end = self.offset;
393 let query_source = self.source[query_start..query_end].to_owned() + "@" + FULL_MATCH;
394 self.query_source += &query_source;
397 self.query_source += "\n";
398 let query = Query::new(language, &query_source).map_err(|mut e| {
399 if e.row == 0 {
402 e.column += location.column;
404 }
405 e.row += location.row;
406 e.offset += query_start;
407 e
408 })?;
409 if query.pattern_count() > 1 {
410 return Err(ParseError::UnexpectedQueryPatterns(location));
411 }
412 let full_match_capture_index = query
413 .capture_index_for_name(FULL_MATCH)
414 .expect("missing capture index for full match")
415 as usize;
416 Ok((query, full_match_capture_index))
417 }
418
419 fn skip_query(&mut self) -> Result<(), ParseError> {
420 let mut paren_depth = 0;
421 let mut in_string = false;
422 let mut in_escape = false;
423 let mut in_comment = false;
424 loop {
425 let ch = self.peek()?;
426 if in_escape {
427 in_escape = false;
428 } else if in_string {
429 match ch {
430 '\\' => {
431 in_escape = true;
432 }
433 '"' | '\n' => {
434 in_string = false;
435 }
436 _ => {}
437 }
438 } else if in_comment {
439 if ch == '\n' {
440 in_comment = false;
441 }
442 } else {
443 match ch {
444 '"' => in_string = true,
445 '(' => paren_depth += 1,
446 ')' => {
447 if paren_depth > 0 {
448 paren_depth -= 1;
449 }
450 }
451 '{' => return Ok(()),
452 ';' => in_comment = true,
453 _ => {}
454 }
455 }
456 self.skip().unwrap();
457 }
458 }
459
460 fn parse_statements(&mut self) -> Result<Vec<ast::Statement>, ParseError> {
461 self.consume_token("{")?;
462 let mut statements = Vec::new();
463 self.consume_whitespace();
464 while self.peek()? != '}' {
465 let statement = self.parse_statement()?;
466 statements.push(statement);
467 self.consume_whitespace();
468 }
469 self.consume_token("}")?;
470 Ok(statements)
471 }
472
473 fn parse_name(&mut self, within: &'static str) -> Result<&'a str, ParseError> {
474 let start = self.offset;
475 let ch = self.next()?;
476 if !is_ident_start(ch) {
477 return Err(ParseError::UnexpectedCharacter(ch, within, self.location));
478 }
479 self.consume_while(is_ident);
480 let end = self.offset;
481 Ok(&self.source[start..end])
482 }
483
484 fn parse_statement(&mut self) -> Result<ast::Statement, ParseError> {
485 let keyword_location = self.location;
486 let keyword = self.parse_name("keyword")?;
487 self.consume_whitespace();
488 if keyword == "let" {
489 let variable = self.parse_variable()?;
490 self.consume_whitespace();
491 self.consume_token("=")?;
492 self.consume_whitespace();
493 let value = self.parse_expression()?;
494 Ok(ast::DeclareImmutable {
495 variable,
496 value,
497 location: keyword_location,
498 }
499 .into())
500 } else if keyword == "var" {
501 let variable = self.parse_variable()?;
502 self.consume_whitespace();
503 self.consume_token("=")?;
504 self.consume_whitespace();
505 let value = self.parse_expression()?;
506 Ok(ast::DeclareMutable {
507 variable,
508 value,
509 location: keyword_location,
510 }
511 .into())
512 } else if keyword == "set" {
513 let variable = self.parse_variable()?;
514 self.consume_whitespace();
515 self.consume_token("=")?;
516 self.consume_whitespace();
517 let value = self.parse_expression()?;
518 Ok(ast::Assign {
519 variable,
520 value,
521 location: keyword_location,
522 }
523 .into())
524 } else if keyword == "node" {
525 let node = self.parse_variable()?;
526 Ok(ast::CreateGraphNode {
527 node,
528 location: keyword_location,
529 }
530 .into())
531 } else if keyword == "edge" {
532 let source = self.parse_expression()?;
533 self.consume_whitespace();
534 self.consume_token("->")?;
535 self.consume_whitespace();
536 let sink = self.parse_expression()?;
537 Ok(ast::CreateEdge {
538 source,
539 sink,
540 location: keyword_location,
541 }
542 .into())
543 } else if keyword == "attr" {
544 self.consume_token("(")?;
545 self.consume_whitespace();
546 let node_or_source = self.parse_expression()?;
547 self.consume_whitespace();
548
549 if self.peek()? == '-' {
550 let source = node_or_source;
551 self.consume_token("->")?;
552 self.consume_whitespace();
553 let sink = self.parse_expression()?;
554 self.consume_whitespace();
555 self.consume_token(")")?;
556 self.consume_whitespace();
557 let attributes = self.parse_attributes()?;
558 Ok(ast::AddEdgeAttribute {
559 source,
560 sink,
561 attributes,
562 location: keyword_location,
563 }
564 .into())
565 } else {
566 let node = node_or_source;
567 self.consume_whitespace();
568 self.consume_token(")")?;
569 self.consume_whitespace();
570 let attributes = self.parse_attributes()?;
571 Ok(ast::AddGraphNodeAttribute {
572 node,
573 attributes,
574 location: keyword_location,
575 }
576 .into())
577 }
578 } else if keyword == "print" {
579 let mut values = vec![self.parse_expression()?];
580 self.consume_whitespace();
581 while self.try_peek() == Some(',') {
582 self.consume_token(",")?;
583 self.consume_whitespace();
584 values.push(self.parse_expression()?);
585 self.consume_whitespace();
586 }
587 self.consume_whitespace();
588 Ok(ast::Print {
589 values,
590 location: keyword_location,
591 }
592 .into())
593 } else if keyword == "scan" {
594 let value = self.parse_expression()?;
595 self.consume_whitespace();
596 self.consume_token("{")?;
597 self.consume_whitespace();
598 let mut arms = Vec::new();
599 while self.peek()? != '}' {
600 let pattern_location = self.location;
601 let pattern = self.parse_string()?;
602 let regex = Regex::new(&pattern)
603 .map_err(|_| ParseError::InvalidRegex(pattern.into(), pattern_location))?;
604 self.consume_whitespace();
605 let statements = self.parse_statements()?;
606 arms.push(ast::ScanArm {
607 regex,
608 statements,
609 location: keyword_location,
610 });
611 self.consume_whitespace();
612 }
613 self.consume_token("}")?;
614 Ok(ast::Scan {
615 value,
616 arms,
617 location: keyword_location,
618 }
619 .into())
620 } else if keyword == "if" {
621 let mut arms = Vec::new();
622
623 let location = keyword_location;
625 self.consume_whitespace();
626 let conditions = self.parse_conditions()?;
627 self.consume_whitespace();
628 let statements = self.parse_statements()?;
629 self.consume_whitespace();
630 arms.push(ast::IfArm {
631 conditions,
632 statements,
633 location,
634 });
635
636 let mut location = self.location;
638 while let Ok(_) = self.consume_token("elif") {
639 self.consume_whitespace();
640 let conditions = self.parse_conditions()?;
641 self.consume_whitespace();
642 let statements = self.parse_statements()?;
643 self.consume_whitespace();
644 arms.push(ast::IfArm {
645 conditions,
646 statements,
647 location,
648 });
649 self.consume_whitespace();
650 location = self.location;
651 }
652
653 let location = self.location;
655 if let Ok(_) = self.consume_token("else") {
656 let conditions = vec![];
657 self.consume_whitespace();
658 let statements = self.parse_statements()?;
659 self.consume_whitespace();
660 arms.push(ast::IfArm {
661 conditions,
662 statements,
663 location,
664 });
665 self.consume_whitespace();
666 }
667
668 Ok(ast::If {
669 arms,
670 location: keyword_location,
671 }
672 .into())
673 } else if keyword == "for" {
674 self.consume_whitespace();
675 let variable = self.parse_unscoped_variable()?;
676 self.consume_whitespace();
677 self.consume_token("in")?;
678 self.consume_whitespace();
679 let value = self.parse_expression()?;
680 self.consume_whitespace();
681 let statements = self.parse_statements()?;
682 Ok(ast::ForIn {
683 variable,
684 value,
685 statements,
686 location: keyword_location,
687 }
688 .into())
689 } else {
690 Err(ParseError::UnexpectedKeyword(
691 keyword.into(),
692 keyword_location,
693 ))
694 }
695 }
696
697 fn parse_conditions(&mut self) -> Result<Vec<ast::Condition>, ParseError> {
698 let mut conditions = Vec::new();
699 let mut has_next = true;
700 while has_next {
701 conditions.push(self.parse_condition()?);
702 self.consume_whitespace();
703 if let Some(',') = self.try_peek() {
704 self.consume_token(",")?;
705 self.consume_whitespace();
706 has_next = true;
707 } else {
708 has_next = false;
709 }
710 }
711 Ok(conditions)
712 }
713
714 fn parse_condition(&mut self) -> Result<ast::Condition, ParseError> {
715 let location = self.location;
716 let condition = if let Ok(_) = self.consume_token("some") {
717 self.consume_whitespace();
718 let value = self.parse_expression()?;
719 ast::Condition::Some { value, location }
720 } else if let Ok(_) = self.consume_token("none") {
721 self.consume_whitespace();
722 let value = self.parse_expression()?;
723 ast::Condition::None { value, location }
724 } else if let Ok(value) = self.parse_expression() {
725 self.consume_whitespace();
726 ast::Condition::Bool { value, location }
727 } else {
728 return Err(ParseError::ExpectedToken(
729 "(some|none)? EXPRESSION",
730 location,
731 ));
732 };
733 self.consume_whitespace();
734 Ok(condition)
735 }
736
737 fn parse_identifier(&mut self, within: &'static str) -> Result<Identifier, ParseError> {
738 let content = self.parse_name(within)?;
739 Ok(Identifier::from(content))
740 }
741
742 fn parse_string(&mut self) -> Result<String, ParseError> {
743 self.consume_token("\"")?;
744 let mut escape = false;
745 let mut value = String::new();
746 loop {
747 let ch = self.next()?;
748 if escape {
749 escape = false;
750 value.push(match ch {
751 '0' => '\0',
752 'n' => '\n',
753 'r' => '\r',
754 't' => '\t',
755 _ => ch,
756 });
757 } else {
758 match ch {
759 '"' => return Ok(value),
760 '\\' => escape = true,
761 _ => value.push(ch),
762 }
763 }
764 }
765 }
766
767 fn parse_expression(&mut self) -> Result<ast::Expression, ParseError> {
768 let mut expression = match self.peek()? {
769 '#' => self.parse_literal()?,
770 '"' => self.parse_string()?.into(),
771 '@' => self.parse_capture()?.into(),
772 '$' => self.parse_regex_capture()?.into(),
773 '(' => self.parse_call()?,
774 '[' => self.parse_list()?,
775 '{' => self.parse_set()?,
776 ch if ch.is_ascii_digit() => self.parse_integer_constant()?,
777 ch if is_ident_start(ch) => {
778 let location = self.location;
779 let name = self.parse_identifier("variable name")?;
780 ast::UnscopedVariable { name, location }.into()
781 }
782 ch => {
783 return Err(ParseError::UnexpectedCharacter(
784 ch,
785 "expression",
786 self.location,
787 ))
788 }
789 };
790 self.consume_whitespace();
791 while self.try_peek() == Some('.') {
792 self.skip().unwrap();
793 self.consume_whitespace();
794 let location = self.location;
795 let scope = Box::new(expression);
796 let name = self.parse_identifier("scoped variable name")?;
797 self.consume_whitespace();
798 expression = ast::ScopedVariable {
799 scope,
800 name,
801 location,
802 }
803 .into();
804 }
805 Ok(expression)
806 }
807
808 fn parse_call(&mut self) -> Result<ast::Expression, ParseError> {
809 self.consume_token("(")?;
810 self.consume_whitespace();
811 let function = self.parse_identifier("function name")?;
812 self.consume_whitespace();
813 let mut parameters = Vec::new();
814 while self.peek()? != ')' {
815 parameters.push(self.parse_expression()?);
816 self.consume_whitespace();
817 }
818 self.consume_token(")")?;
819 Ok(ast::Call {
820 function,
821 parameters,
822 }
823 .into())
824 }
825
826 fn parse_sequence(&mut self, end_marker: char) -> Result<Vec<ast::Expression>, ParseError> {
827 let mut elements = Vec::new();
828 while self.peek()? != end_marker {
829 elements.push(self.parse_expression()?);
830 self.consume_whitespace();
831 if self.peek()? != end_marker {
832 self.consume_token(",")?;
833 self.consume_whitespace();
834 }
835 }
836 Ok(elements)
837 }
838
839 fn parse_list(&mut self) -> Result<ast::Expression, ParseError> {
840 let location = self.location;
841 self.consume_token("[")?;
842 self.consume_whitespace();
843 if let Ok(_) = self.consume_token("]") {
844 return Ok(ast::ListLiteral { elements: vec![] }.into());
845 }
846 let first_element = self.parse_expression()?;
847 self.consume_whitespace();
848 if let Ok(_) = self.consume_token("]") {
849 let elements = vec![first_element];
850 Ok(ast::ListLiteral { elements }.into())
851 } else if let Ok(_) = self.consume_token(",") {
852 self.consume_whitespace();
853 let mut elements = self.parse_sequence(']')?;
854 self.consume_whitespace();
855 self.consume_token("]")?;
856 elements.insert(0, first_element);
857 Ok(ast::ListLiteral { elements }.into())
858 } else {
859 self.consume_token("for")?;
860 self.consume_whitespace();
861 let variable = self.parse_unscoped_variable()?;
862 self.consume_whitespace();
863 self.consume_token("in")?;
864 self.consume_whitespace();
865 let value = self.parse_expression()?;
866 self.consume_whitespace();
867 self.consume_token("]")?;
868 Ok(ast::ListComprehension {
869 element: first_element.into(),
870 variable,
871 value: value.into(),
872 location,
873 }
874 .into())
875 }
876 }
877
878 fn parse_set(&mut self) -> Result<ast::Expression, ParseError> {
879 let location = self.location;
880 self.consume_token("{")?;
881 self.consume_whitespace();
882 if let Ok(_) = self.consume_token("}") {
883 return Ok(ast::SetLiteral { elements: vec![] }.into());
884 }
885 let first_element = self.parse_expression()?;
886 self.consume_whitespace();
887 if let Ok(_) = self.consume_token("}") {
888 let elements = vec![first_element];
889 Ok(ast::SetLiteral { elements }.into())
890 } else if let Ok(_) = self.consume_token(",") {
891 self.consume_whitespace();
892 let mut elements = self.parse_sequence('}')?;
893 self.consume_whitespace();
894 self.consume_token("}")?;
895 elements.insert(0, first_element);
896 Ok(ast::SetLiteral { elements }.into())
897 } else {
898 self.consume_token("for")?;
899 self.consume_whitespace();
900 let variable = self.parse_unscoped_variable()?;
901 self.consume_whitespace();
902 self.consume_token("in")?;
903 self.consume_whitespace();
904 let value = self.parse_expression()?;
905 self.consume_whitespace();
906 self.consume_token("}")?;
907 Ok(ast::SetComprehension {
908 element: first_element.into(),
909 variable,
910 value: value.into(),
911 location,
912 }
913 .into())
914 }
915 }
916
917 fn parse_capture(&mut self) -> Result<ast::Capture, ParseError> {
918 let location = self.location;
919 let start = self.offset;
920 self.consume_token("@")?;
921 let ch = self.next()?;
922 if !is_ident_start(ch) {
923 return Err(ParseError::UnexpectedCharacter(
924 ch,
925 "query capture",
926 self.location,
927 ));
928 }
929 self.consume_while(is_ident);
930 let end = self.offset;
931 let name = Identifier::from(&self.source[start + 1..end]);
932 Ok(ast::Capture {
933 name,
934 quantifier: Zero, file_capture_index: usize::MAX, stanza_capture_index: usize::MAX, location,
938 }
939 .into())
940 }
941
942 fn parse_integer_constant(&mut self) -> Result<ast::Expression, ParseError> {
943 let start = self.offset;
945 self.consume_while(|ch| ch.is_ascii_digit());
946 let end = self.offset;
947 let value = u32::from_str_radix(&self.source[start..end], 10).unwrap();
948 Ok(ast::IntegerConstant { value }.into())
949 }
950
951 fn parse_literal(&mut self) -> Result<ast::Expression, ParseError> {
952 let literal_location = self.location;
953 self.consume_token("#")?;
954 let literal = self.parse_name("literal")?;
955 if literal == "false" {
956 return Ok(ast::Expression::FalseLiteral);
957 } else if literal == "null" {
958 return Ok(ast::Expression::NullLiteral);
959 } else if literal == "true" {
960 return Ok(ast::Expression::TrueLiteral);
961 } else {
962 Err(ParseError::UnexpectedLiteral(
963 literal.into(),
964 literal_location,
965 ))
966 }
967 }
968
969 fn parse_regex_capture(&mut self) -> Result<ast::RegexCapture, ParseError> {
970 let regex_capture_location = self.location;
971 self.consume_token("$")?;
972 let start = self.offset;
973 self.consume_while(|ch| ch.is_ascii_digit());
974 let end = self.offset;
975 if start == end {
976 return Err(ParseError::InvalidRegexCapture(regex_capture_location));
977 }
978 let match_index = usize::from_str_radix(&self.source[start..end], 10).unwrap();
979 Ok(ast::RegexCapture { match_index }.into())
980 }
981
982 fn parse_attributes(&mut self) -> Result<Vec<ast::Attribute>, ParseError> {
983 let mut attributes = vec![self.parse_attribute()?];
984 self.consume_whitespace();
985 while self.try_peek() == Some(',') {
986 self.skip().unwrap();
987 self.consume_whitespace();
988 attributes.push(self.parse_attribute()?);
989 self.consume_whitespace();
990 }
991 Ok(attributes)
992 }
993
994 fn parse_attribute(&mut self) -> Result<ast::Attribute, ParseError> {
995 let name = self.parse_identifier("attribute name")?;
996 self.consume_whitespace();
997 let value = if self.try_peek() == Some('=') {
998 self.consume_token("=")?;
999 self.consume_whitespace();
1000 self.parse_expression()?
1001 } else {
1002 ast::Expression::TrueLiteral
1003 };
1004 Ok(ast::Attribute { name, value })
1005 }
1006
1007 fn parse_variable(&mut self) -> Result<ast::Variable, ParseError> {
1008 let expression_location = self.location;
1009 match self.parse_expression()? {
1010 ast::Expression::Variable(variable) => Ok(variable),
1011 _ => Err(ParseError::ExpectedVariable(expression_location)),
1012 }
1013 }
1014
1015 fn parse_unscoped_variable(&mut self) -> Result<ast::UnscopedVariable, ParseError> {
1016 match self.parse_variable()? {
1017 ast::Variable::Unscoped(variable) => Ok(variable),
1018 ast::Variable::Scoped(variable) => {
1019 Err(ParseError::ExpectedUnscopedVariable(variable.location))
1020 }
1021 }
1022 }
1023}