1use super::{
2 ast::*,
3 error::{
4 ErrorMsg,
5 MsgType::{self, *},
6 },
7 lexer::{self, Position},
8 token::{self, SocketPlug, Token},
9};
10
11use std::{cmp::Ordering, marker::PhantomData, mem, result};
12
13use codespan_reporting::{
14 diagnostic::{Diagnostic, Label},
15 files::SimpleFiles,
16 term,
17};
18use displaydoc::Display;
19
20#[cfg(feature = "std")]
21use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
22#[cfg(feature = "std")]
23use std::{borrow::Cow, collections::BTreeSet, rc::Rc};
24
25#[cfg(not(feature = "std"))]
26use alloc::{
27 borrow::{Cow, ToOwned},
28 boxed::Box,
29 collections::BTreeSet,
30 rc::Rc,
31 string::{String, ToString},
32 vec::Vec,
33};
34
35#[cfg(target_arch = "wasm32")]
36use wasm_bindgen::prelude::*;
37
38#[cfg(target_arch = "wasm32")]
39use serde::Serialize;
40
41pub type Result<T> = result::Result<T, Error>;
43
44pub struct Parser<'a> {
46 tokens: Box<dyn Iterator<Item = lexer::Item<'a>> + 'a>,
47 str_input: &'a str,
48 cur_token: Token<'a>,
49 peek_token: Token<'a>,
50 lexer_position: Position,
51 peek_lexer_position: Position,
52 #[cfg(feature = "ast-span")]
53 parser_position: Position,
54 pub errors: Vec<Error>,
56 current_rule_generic_param_idents: Option<Vec<&'a str>>,
57 typenames: Rc<BTreeSet<&'a str>>,
58 groupnames: Rc<BTreeSet<&'a str>>,
59 #[cfg(feature = "ast-span")]
60 unknown_rule_idents: Vec<(&'a str, Span)>,
61 #[cfg(not(feature = "ast-span"))]
62 unknown_rule_idents: Vec<&'a str>,
63 is_guaranteed: bool,
64}
65
66#[derive(Debug, Display)]
68pub enum Error {
69 #[displaydoc("{0}")]
71 CDDL(String),
72 #[cfg_attr(
73 feature = "ast-span",
74 displaydoc("parsing error: position {position:?}, msg: {msg}")
75 )]
76 #[cfg_attr(not(feature = "ast-span"), displaydoc("parsing error: msg: {msg}"))]
77 PARSER {
79 #[cfg(feature = "ast-span")]
81 position: Position,
82 msg: ErrorMsg,
84 },
85 #[displaydoc("{0}")]
86 LEXER(lexer::Error),
88 #[displaydoc("regex parsing error: {0}")]
90 REGEX(regex::Error),
91 #[displaydoc("incremental parsing error")]
92 INCREMENTAL,
94 #[displaydoc("defer parsing error")]
95 GROUP,
97}
98
99#[cfg(feature = "std")]
100impl std::error::Error for Error {}
101
102impl<'a> Parser<'a> {
103 pub fn new(
116 str_input: &'a str,
117 tokens: Box<dyn Iterator<Item = lexer::Item<'a>> + 'a>,
118 ) -> Result<Parser<'a>> {
119 let mut p = Parser {
120 tokens,
121 str_input,
122 cur_token: Token::EOF,
123 peek_token: Token::EOF,
124 errors: Vec::default(),
125 lexer_position: Position::default(),
126 peek_lexer_position: Position::default(),
127 #[cfg(feature = "ast-span")]
128 parser_position: Position::default(),
129 current_rule_generic_param_idents: None,
130 typenames: Rc::new(BTreeSet::from([
131 "any",
132 "uint",
133 "nint",
134 "int",
135 "bstr",
136 "bytes",
137 "tstr",
138 "text",
139 "tdate",
140 "time",
141 "number",
142 "biguint",
143 "bignint",
144 "bigint",
145 "integer",
146 "unsigned",
147 "decfrac",
148 "bigfloat",
149 "eb64url",
150 "eb64legacy",
151 "eb16",
152 "encoded-cbor",
153 "uri",
154 "b64url",
155 "b64legacy",
156 "regexp",
157 "mime-message",
158 "cbor-any",
159 "float16",
160 "float32",
161 "float64",
162 "float16-32",
163 "float32-64",
164 "float",
165 "false",
166 "true",
167 "bool",
168 "nil",
169 "null",
170 "undefined",
171 ])),
172 groupnames: Rc::new(BTreeSet::default()),
173 unknown_rule_idents: Vec::default(),
174 is_guaranteed: false,
175 };
176
177 p.next_token()?;
178 p.next_token()?;
179
180 Ok(p)
181 }
182
183 #[cfg(feature = "std")]
204 pub fn report_errors(
205 &self,
206 to_stderr: bool,
207 ) -> std::result::Result<Option<String>, Box<dyn std::error::Error>> {
208 if self.errors.is_empty() {
209 return Ok(None);
210 }
211
212 let mut files = SimpleFiles::new();
213
214 let file_id = files.add("input", self.str_input);
215
216 let mut labels = Vec::new();
217 for error in self.errors.iter() {
218 if let Error::PARSER {
219 #[cfg(feature = "ast-span")]
220 position,
221 msg,
222 } = error
223 {
224 labels.push(
225 #[cfg(feature = "ast-span")]
226 Label::primary(file_id, position.range.0..position.range.1).with_message(msg.to_string()),
227 #[cfg(not(feature = "ast-span"))]
228 Label::primary(file_id, 0..0).with_message(msg.to_string()),
229 );
230 }
231 }
232
233 let diagnostic = Diagnostic::error()
234 .with_message("parser errors")
235 .with_labels(labels);
236
237 let config = term::Config::default();
238
239 if to_stderr {
240 let writer = StandardStream::stderr(ColorChoice::Auto);
241 match term::emit(&mut writer.lock(), &config, &files, &diagnostic) {
244 Ok(_) => return Ok(None),
245 Err(e) => return Err(Box::from(e)),
246 };
247 }
248
249 let mut buffer = Vec::new();
250 let mut writer = term::termcolor::NoColor::new(&mut buffer);
251
252 term::emit(&mut writer, &config, &files, &diagnostic)?;
253
254 Ok(Some(String::from_utf8(buffer)?))
255 }
256
257 #[cfg(not(feature = "std"))]
274 pub fn report_errors(&self) -> Option<String> {
275 if self.errors.is_empty() {
276 return None;
277 }
278
279 let mut files = SimpleFiles::new();
280
281 let file_id = files.add("input", self.str_input);
282
283 let mut labels = Vec::new();
284 for error in self.errors.iter() {
285 if let Error::PARSER {
286 #[cfg(feature = "ast-span")]
287 position,
288 msg,
289 } = error
290 {
291 labels.push(
292 #[cfg(feature = "ast-span")]
293 Label::primary(file_id, position.range.0..position.range.1).with_message(msg.to_string()),
294 #[cfg(not(feature = "ast-span"))]
295 Label::primary(file_id, 0..0).with_message(msg.to_string()),
296 );
297 }
298 }
299
300 let diagnostic = Diagnostic::error()
301 .with_message("parser errors")
302 .with_labels(labels);
303
304 let config = term::Config::default();
305
306 let mut buffer = Vec::new();
307 let mut writer = term::termcolor::NoColor::new(&mut buffer);
308
309 term::emit(&mut writer, &config, &files, &diagnostic).ok()?;
310
311 String::from_utf8(buffer).ok()
312 }
313
314 fn next_token(&mut self) -> Result<()> {
315 mem::swap(&mut self.cur_token, &mut self.peek_token);
316 mem::swap(&mut self.lexer_position, &mut self.peek_lexer_position);
317
318 if let Some(next_token) = self.tokens.next() {
319 let nt = next_token.map_err(Error::LEXER)?;
320 self.peek_token = nt.1;
321 self.peek_lexer_position = nt.0;
322 }
323
324 Ok(())
325 }
326
327 fn advance_to_next_rule(&mut self) -> Result<()> {
328 let mut is_possible_rule = false;
329
330 while !is_possible_rule {
331 self.next_token()?;
332 if let Token::IDENT(..) = self.cur_token {
333 match self.peek_token {
334 Token::ASSIGN | Token::TCHOICEALT | Token::GCHOICEALT => is_possible_rule = true,
335 _ => continue,
336 }
337 } else if let Token::EOF = self.cur_token {
338 is_possible_rule = true;
339 }
340 }
341
342 Ok(())
343 }
344
345 #[cfg(feature = "ast-comments")]
346 fn collect_comments(&mut self) -> Result<Option<Comments<'a>>> {
347 #[cfg_attr(not(feature = "lsp"), allow(unused_mut))]
348 let mut comments: Option<Comments> = None;
349
350 while let Token::COMMENT(_comment) = self.cur_token {
351 #[cfg(not(feature = "lsp"))]
352 comments.get_or_insert(Comments::default()).0.push(_comment);
353
354 self.next_token()?;
355 }
356
357 while let Token::NEWLINE = self.cur_token {
358 #[cfg(feature = "lsp")]
359 comments.get_or_insert(Comments::default()).0.push("\n");
360
361 self.next_token()?;
362 }
363
364 if let Token::COMMENT(_) = self.cur_token {
365 if let Some(c) = self.collect_comments()? {
366 #[cfg_attr(not(feature = "lsp"), allow(unused_mut))]
367 for comment in c.0.iter() {
368 comments.get_or_insert(Comments::default()).0.push(comment);
369 }
370 }
371 }
372
373 Ok(comments)
374 }
375
376 #[cfg(not(feature = "ast-comments"))]
377 fn advance_newline(&mut self) -> Result<()> {
378 while let Token::NEWLINE = self.cur_token {
379 #[cfg(feature = "lsp")]
380 comments.get_or_insert(Comments::default()).0.push("\n");
381
382 self.next_token()?;
383 }
384
385 Ok(())
386 }
387
388 fn register_rule(&mut self, rule: &Rule<'a>) {
389 match &rule {
390 Rule::Type { rule, .. } => Rc::make_mut(&mut self.typenames).insert(rule.name.ident),
391 Rule::Group { rule, .. } => Rc::make_mut(&mut self.groupnames).insert(rule.name.ident),
392 };
393 }
394
395 pub fn parse_cddl(&mut self) -> Result<CDDL<'a>> {
397 #[cfg(not(feature = "ast-comments"))]
398 self.advance_newline()?;
399
400 let mut c = CDDL {
401 #[cfg(feature = "ast-comments")]
402 comments: self.collect_comments()?,
403 ..Default::default()
404 };
405
406 struct UnknownRule<'a> {
407 rule: Rule<'a>,
408 index: usize,
409 range: (usize, usize),
410 }
411
412 let mut all_rules = Vec::default();
414 while self.cur_token != Token::EOF {
417 let begin_rule_range = self.lexer_position.range.0;
418
419 match self.parse_rule(false) {
420 Ok(r) => {
421 let rule_exists =
422 |existing_rule: &Rule| r.name() == existing_rule.name() && !r.is_choice_alternate();
423
424 if c.rules.iter().any(rule_exists) || all_rules.iter().any(|(rule, _)| rule_exists(rule))
425 {
426 #[cfg(feature = "ast-span")]
427 {
428 self.parser_position.range = (r.span().0, r.span().1);
429 self.parser_position.line = r.span().2;
430 }
431
432 self.errors.push(Error::PARSER {
433 #[cfg(feature = "ast-span")]
434 position: self.parser_position,
435 msg: DuplicateRuleIdentifier.into(),
436 });
437
438 continue;
439 }
440
441 self.register_rule(&r);
443
444 all_rules.push((r, begin_rule_range));
445 self.is_guaranteed = false;
446 }
447 Err(Error::INCREMENTAL) => {
448 if !self.cur_token_is(Token::EOF) {
449 self.advance_to_next_rule()?;
450 }
451 }
452 Err(e) => return Err(e),
453 }
454 }
455
456 let mut unknown_rules = Vec::default();
458
459 for (rule, begin_rule_range) in all_rules {
460 if !self.unknown_rule_idents.is_empty() {
462 unknown_rules.push(UnknownRule {
463 rule,
464 index: c.rules.len(),
465 range: (begin_rule_range, self.lexer_position.range.1),
466 });
467 self.unknown_rule_idents = Vec::default();
468 } else {
469 c.rules.push(rule);
470 }
471 }
472
473 unknown_rules.reverse();
476
477 {
479 let mut errors;
480 let mut known_rules = Vec::default();
481 loop {
482 let mut resolved_rules = Vec::default();
483 let mut unresolved_rules = Vec::default();
484
485 errors = Vec::default();
486 for unknown_rule in unknown_rules {
487 match self.resolve_rule(unknown_rule.range, false) {
488 Ok(rule) => resolved_rules.push((unknown_rule.index, rule)),
489 Err(_) => match self.resolve_rule(unknown_rule.range, true) {
490 Ok(rule) => resolved_rules.push((unknown_rule.index, rule)),
491 Err(mut error) => {
492 errors.append(&mut error);
493 unresolved_rules.push(unknown_rule);
494 }
495 },
496 }
497 }
498 if resolved_rules.is_empty() {
499 break;
500 }
501 for (_, rule) in &resolved_rules {
502 self.register_rule(rule);
503 }
504 known_rules.append(&mut resolved_rules);
505 unknown_rules = unresolved_rules;
506 }
507 self.errors.append(&mut errors);
508 known_rules.sort_by(|(a, _), (b, _)| b.partial_cmp(a).unwrap());
509 for (index, rule) in known_rules {
510 c.rules.insert(index, rule);
511 }
512 }
513
514 if !self.errors.is_empty() {
515 return Err(Error::INCREMENTAL);
516 }
517
518 Ok(c)
523 }
524
525 fn resolve_rule(
526 &mut self,
527 range: (usize, usize),
528 parse_group_rule: bool,
529 ) -> result::Result<Rule<'a>, Vec<Error>> {
530 let tokens = Box::new(lexer::Lexer::new(&self.str_input[range.0..range.1]).iter());
531 let mut parser = Parser::new(self.str_input, tokens).map_err(|err| vec![err])?;
532 parser.groupnames = self.groupnames.clone();
533 parser.typenames = self.typenames.clone();
534 let rule = parser
535 .parse_rule(parse_group_rule)
536 .map_err(|err| vec![err])?;
537 if !parser.unknown_rule_idents.is_empty() {
538 Err(
539 #[cfg(feature = "ast-span")]
540 parser
541 .unknown_rule_idents
542 .into_iter()
543 .map(|(ident, span)| Error::PARSER {
544 position: Position {
545 column: 0,
546 index: span.0,
547 line: span.2,
548 range: (span.0 + range.0, span.1 + range.0),
549 },
550 msg: ErrorMsg {
551 short: format!("missing definition for rule {}", ident),
552 extended: None,
553 },
554 })
555 .collect(),
556 #[cfg(not(feature = "ast-span"))]
557 parser
558 .unknown_rule_idents
559 .into_iter()
560 .map(|ident| Error::PARSER {
561 msg: ErrorMsg {
562 short: format!("missing definition for rule {}", ident),
563 extended: None,
564 },
565 })
566 .collect(),
567 )
568 } else {
569 Ok(rule)
570 }
571 }
572
573 #[allow(missing_docs)]
574 pub fn parse_rule(&mut self, parse_group_rule: bool) -> Result<Rule<'a>> {
575 #[cfg(feature = "ast-span")]
576 let begin_rule_range = self.lexer_position.range.0;
577 #[cfg(feature = "ast-span")]
578 let begin_rule_line = self.lexer_position.line;
579 #[cfg(feature = "ast-span")]
580 let begin_rule_col = self.lexer_position.column;
581
582 let ident = match &self.cur_token {
583 Token::IDENT(i, s) => self.identifier_from_ident_token(i, *s),
584 _ => {
585 #[cfg(feature = "ast-span")]
586 {
587 self.parser_position.range = self.lexer_position.range;
588 self.parser_position.line = self.lexer_position.line;
589 }
590
591 self.errors.push(Error::PARSER {
592 #[cfg(feature = "ast-span")]
593 position: self.parser_position,
594 msg: InvalidRuleIdentifier.into(),
595 });
596
597 return Err(Error::INCREMENTAL);
598 }
599 };
600
601 let gp = if self.peek_token_is(&Token::LANGLEBRACKET) {
602 self.next_token()?;
603
604 let params = self.parse_genericparm()?;
605 let mut param_list = Vec::default();
606
607 for param in params.params.iter() {
608 param_list.push(param.param.ident);
609 }
610
611 self.current_rule_generic_param_idents = Some(param_list);
612
613 Some(params)
614 } else {
615 None
616 };
617
618 #[cfg(feature = "ast-comments")]
619 let comments_before_assign = self.collect_comments()?;
620 #[cfg(not(feature = "ast-comments"))]
621 self.advance_newline()?;
622
623 if !self.expect_peek(&Token::ASSIGN)?
624 && !self.expect_peek(&Token::TCHOICEALT)?
625 && !self.expect_peek(&Token::GCHOICEALT)?
626 {
627 #[cfg(feature = "ast-span")]
628 {
629 self.parser_position.range = (begin_rule_range, self.lexer_position.range.1);
630 self.parser_position.line = self.lexer_position.line;
631 }
632
633 self.errors.push(Error::PARSER {
634 #[cfg(feature = "ast-span")]
635 position: self.parser_position,
636 msg: MsgType::MissingAssignmentToken.into(),
637 });
638
639 return Err(Error::INCREMENTAL);
640 }
641
642 let mut is_type_choice_alternate = false;
643 let mut is_group_choice_alternate = false;
644
645 if let Token::TCHOICEALT = &self.cur_token {
646 is_type_choice_alternate = true;
647 } else if let Token::GCHOICEALT = &self.cur_token {
648 is_group_choice_alternate = true;
649 }
650
651 if let Some(socket) = &ident.socket {
652 match socket {
653 SocketPlug::TYPE if !is_type_choice_alternate => {
654 #[cfg(feature = "ast-span")]
655 {
656 self.parser_position.range = (begin_rule_range, self.lexer_position.range.1);
657 self.parser_position.line = self.lexer_position.line;
658 }
659
660 self.errors.push(Error::PARSER {
661 #[cfg(feature = "ast-span")]
662 position: self.parser_position,
663 msg: MsgType::TypeSocketNamesMustBeTypeAugmentations.into(),
664 });
665
666 return Err(Error::INCREMENTAL);
667 }
668 SocketPlug::GROUP if !is_group_choice_alternate => {
669 #[cfg(feature = "ast-span")]
670 {
671 self.parser_position.range = (begin_rule_range, self.lexer_position.range.1);
672 self.parser_position.line = self.lexer_position.line;
673 }
674
675 self.errors.push(Error::PARSER {
676 #[cfg(feature = "ast-span")]
677 position: self.parser_position,
678 msg: MsgType::GroupSocketNamesMustBeGroupAugmentations.into(),
679 });
680
681 return Err(Error::INCREMENTAL);
682 }
683 _ => (),
684 }
685 }
686
687 self.next_token()?;
688
689 #[cfg(feature = "ast-comments")]
690 let comments_after_assign = self.collect_comments()?;
691 #[cfg(not(feature = "ast-comments"))]
692 self.advance_newline()?;
693
694 if matches!(self.cur_token, Token::IDENT(_, Some(SocketPlug::GROUP)))
697 || is_group_choice_alternate
698 || parse_group_rule
699 {
700 let ge = self.parse_grpent(true)?;
701
702 #[cfg(feature = "ast-comments")]
703 let comments_after_rule = self.collect_comments()?;
704 #[cfg(not(feature = "ast-comments"))]
705 self.advance_newline()?;
706
707 #[cfg(feature = "ast-span")]
708 let span = (
709 begin_rule_range,
710 self.parser_position.range.1,
711 begin_rule_line,
712 );
713
714 self.current_rule_generic_param_idents = None;
715 self.is_guaranteed = true;
716
717 return Ok(Rule::Group {
718 rule: Box::from(GroupRule {
719 name: ident,
720 generic_params: gp,
721 is_group_choice_alternate,
722 entry: ge,
723 #[cfg(feature = "ast-comments")]
724 comments_before_assigng: comments_before_assign,
725 #[cfg(feature = "ast-comments")]
726 comments_after_assigng: comments_after_assign,
727 }),
728 #[cfg(feature = "ast-comments")]
729 comments_after_rule,
730 #[cfg(feature = "ast-span")]
731 span,
732 });
733 }
734
735 match self.cur_token {
736 Token::LPAREN | Token::ASTERISK | Token::ONEORMORE | Token::OPTIONAL => {
737 #[cfg(feature = "ast-span")]
738 let begin_pt_range = self.lexer_position.range.0;
739
740 let ge = self.parse_grpent(true)?;
741
742 #[cfg(feature = "ast-span")]
743 let mut end_rule_range = self.parser_position.range.1;
744
745 #[cfg(feature = "ast-comments")]
746 let comments_after_rule = self.collect_comments()?;
747 #[cfg(not(feature = "ast-comments"))]
748 self.advance_newline()?;
749
750 if let GroupEntry::InlineGroup {
761 occur: None,
762 group,
763 #[cfg(feature = "ast-comments")]
764 comments_before_group,
765 #[cfg(feature = "ast-comments")]
766 comments_after_group,
767 ..
768 } = &ge
769 {
770 if group.group_choices.len() == 1 {
771 if let Some(gc) = group.group_choices.first() {
772 if gc.group_entries.len() == 1 {
773 if let Some(group_entry) = gc.group_entries.first() {
774 if !group_entry.1.optional_comma {
776 if let GroupEntry::TypeGroupname {
778 ge,
779 #[cfg(feature = "ast-comments")]
780 leading_comments,
781 #[cfg(feature = "ast-comments")]
782 trailing_comments,
783 ..
784 } = &group_entry.0
785 {
786 if ge.occur.is_none() && matches!(self.cur_token, Token::ControlOperator(_)) {
787 let value = self.parse_type(Some(Type2::ParenthesizedType {
788 #[cfg(feature = "ast-comments")]
789 comments_before_type: comments_before_group.clone(),
790 pt: Type {
791 type_choices: vec![TypeChoice {
792 #[cfg(feature = "ast-comments")]
793 comments_before_type: leading_comments.clone(),
794 #[cfg(feature = "ast-comments")]
795 comments_after_type: trailing_comments.clone(),
796 type1: Type1 {
797 type2: Type2::Typename {
798 ident: ge.name.clone(),
799 generic_args: ge.generic_args.clone(),
800 #[cfg(feature = "ast-span")]
801 span: ge.name.span,
802 },
803 operator: None,
804 #[cfg(feature = "ast-span")]
805 span: ge.name.span,
806 #[cfg(feature = "ast-comments")]
807 comments_after_type: None,
808 },
809 }],
810 #[cfg(feature = "ast-span")]
811 span: ge.name.span,
812 },
813 #[cfg(feature = "ast-comments")]
814 comments_after_type: comments_after_group.clone(),
815 #[cfg(feature = "ast-span")]
816 span: (
817 begin_pt_range,
818 self.parser_position.range.1,
819 begin_rule_line,
820 ),
821 }))?;
822
823 #[cfg(feature = "ast-span")]
824 {
825 end_rule_range = self.parser_position.range.1;
826 }
827
828 self.current_rule_generic_param_idents = None;
829
830 return Ok(Rule::Type {
831 rule: TypeRule {
832 name: ident,
833 generic_params: gp,
834 is_type_choice_alternate,
835 value,
836 #[cfg(feature = "ast-comments")]
837 comments_before_assignt: comments_before_assign,
838 #[cfg(feature = "ast-comments")]
839 comments_after_assignt: comments_after_assign,
840 },
841 #[cfg(feature = "ast-comments")]
842 comments_after_rule,
843 #[cfg(feature = "ast-span")]
844 span: (begin_rule_range, end_rule_range, begin_rule_line),
845 });
846 }
847 }
848
849 if let GroupEntry::ValueMemberKey { ge, .. } = &group_entry.0 {
851 if ge.occur.is_none() && ge.member_key.is_none() {
852 let value = self.parse_type(Some(Type2::ParenthesizedType {
853 #[cfg(feature = "ast-comments")]
854 comments_before_type: comments_before_group.clone(),
855 pt: ge.entry_type.clone(),
856 #[cfg(feature = "ast-comments")]
857 comments_after_type: comments_after_group.clone(),
858 #[cfg(feature = "ast-span")]
859 span: (
860 begin_pt_range,
861 self.parser_position.range.1,
862 begin_rule_line,
863 ),
864 }))?;
865
866 #[cfg(feature = "ast-span")]
867 {
868 end_rule_range = self.parser_position.range.1;
869 }
870
871 self.current_rule_generic_param_idents = None;
872
873 return Ok(Rule::Type {
874 rule: TypeRule {
875 name: ident,
876 generic_params: gp,
877 is_type_choice_alternate,
878 value,
879 #[cfg(feature = "ast-comments")]
880 comments_before_assignt: comments_before_assign,
881 #[cfg(feature = "ast-comments")]
882 comments_after_assignt: comments_after_assign,
883 },
884 #[cfg(feature = "ast-comments")]
885 comments_after_rule,
886 #[cfg(feature = "ast-span")]
887 span: (begin_rule_range, end_rule_range, begin_rule_line),
888 });
889 }
890 }
891 }
892 }
893 }
894 }
895 }
896 }
897
898 self.current_rule_generic_param_idents = None;
899
900 Ok(Rule::Group {
901 rule: Box::from(GroupRule {
902 name: ident,
903 generic_params: gp,
904 is_group_choice_alternate,
905 entry: ge,
906 #[cfg(feature = "ast-comments")]
907 comments_before_assigng: comments_before_assign,
908 #[cfg(feature = "ast-comments")]
909 comments_after_assigng: comments_after_assign,
910 }),
911 #[cfg(feature = "ast-comments")]
912 comments_after_rule,
913 #[cfg(feature = "ast-span")]
914 span: (begin_rule_range, end_rule_range, begin_rule_line),
915 })
916 }
917 _ => {
918 let advance_token = matches!(self.cur_token, Token::UNWRAP);
920
921 #[cfg(feature = "ast-comments")]
922 let mut t = self.parse_type(None)?;
923 #[cfg(not(feature = "ast-comments"))]
924 let t = self.parse_type(None)?;
925
926 if advance_token {
927 self.next_token()?;
928 }
929
930 #[cfg(feature = "ast-comments")]
931 let comments_after_rule = if let Some(comments) = t.split_comments_after_type() {
932 Some(comments)
933 } else {
934 self.collect_comments()?
935 };
936
937 #[cfg(not(feature = "ast-comments"))]
938 self.advance_newline()?;
939
940 if let Token::ASSIGN | Token::TCHOICEALT | Token::GCHOICEALT = &self.cur_token {
941 self.errors.push(Error::PARSER {
942 #[cfg(feature = "ast-span")]
943 position: Position {
944 line: begin_rule_line,
945 column: begin_rule_col,
946 range: (ident.span.0, ident.span.1),
947 index: self.parser_position.range.0,
948 },
949 msg: IncompleteRuleEntry.into(),
950 });
951
952 return Err(Error::INCREMENTAL);
953 }
954
955 #[cfg(feature = "ast-span")]
956 let span = (
957 begin_rule_range,
958 self.parser_position.range.1,
959 begin_rule_line,
960 );
961
962 self.current_rule_generic_param_idents = None;
963
964 if t.type_choices.len() > 1
965 || !matches!(
966 t.type_choices[0].type1.type2,
967 Type2::ParenthesizedType { .. } | Type2::Typename { .. }
968 )
969 {
970 self.is_guaranteed = true;
971 }
972
973 Ok(Rule::Type {
974 rule: TypeRule {
975 name: ident,
976 generic_params: gp,
977 is_type_choice_alternate,
978 value: t,
979 #[cfg(feature = "ast-comments")]
980 comments_before_assignt: comments_before_assign,
981 #[cfg(feature = "ast-comments")]
982 comments_after_assignt: comments_after_assign,
983 },
984 #[cfg(feature = "ast-comments")]
985 comments_after_rule,
986 #[cfg(feature = "ast-span")]
987 span,
988 })
989 }
990 }
991 }
992
993 #[allow(missing_docs)]
994 pub fn parse_genericparm(&mut self) -> Result<GenericParams<'a>> {
995 #[cfg(feature = "ast-span")]
996 let begin_range = self.lexer_position.range.0;
997
998 if let Token::LANGLEBRACKET = &self.cur_token {
999 self.next_token()?;
1000 }
1001
1002 let mut generic_params = GenericParams::default();
1003
1004 while !self.cur_token_is(Token::RANGLEBRACKET) {
1005 #[cfg(feature = "ast-comments")]
1006 let comments_before_ident = self.collect_comments()?;
1007 #[cfg(not(feature = "ast-comments"))]
1008 self.advance_newline()?;
1009
1010 match &self.cur_token {
1011 Token::IDENT(ident, socket) => {
1012 let param = self.identifier_from_ident_token(ident, *socket);
1013
1014 self.next_token()?;
1015
1016 #[cfg(feature = "ast-comments")]
1017 let comments_after_ident = self.collect_comments()?;
1018 #[cfg(not(feature = "ast-comments"))]
1019 self.advance_newline()?;
1020
1021 generic_params.params.push(GenericParam {
1022 param,
1023 #[cfg(feature = "ast-comments")]
1024 comments_before_ident,
1025 #[cfg(feature = "ast-comments")]
1026 comments_after_ident,
1027 });
1028
1029 if !self.cur_token_is(Token::COMMA) && !self.cur_token_is(Token::RANGLEBRACKET) {
1030 #[cfg(feature = "ast-span")]
1031 {
1032 self.parser_position.range = (begin_range + 1, self.peek_lexer_position.range.0);
1033 self.parser_position.line = self.lexer_position.line;
1034 }
1035
1036 self.errors.push(Error::PARSER {
1037 #[cfg(feature = "ast-span")]
1038 position: self.parser_position,
1039 msg: InvalidGenericSyntax.into(),
1040 });
1041
1042 return Err(Error::INCREMENTAL);
1043 }
1044 }
1045 Token::COMMA => self.next_token()?,
1046 Token::VALUE(_) => {
1047 #[cfg(feature = "ast-span")]
1048 {
1049 self.parser_position.range = (self.lexer_position.range.0, self.lexer_position.range.1);
1050 self.parser_position.line = self.lexer_position.line;
1051 }
1052
1053 self.errors.push(Error::PARSER {
1054 #[cfg(feature = "ast-span")]
1055 position: self.parser_position,
1056 msg: InvalidGenericIdentifier.into(),
1057 });
1058
1059 return Err(Error::INCREMENTAL);
1060 }
1061 _ => {
1062 #[cfg(feature = "ast-span")]
1063 {
1064 self.parser_position.range = (begin_range, self.lexer_position.range.0);
1065 self.parser_position.line = self.lexer_position.line;
1066 }
1067
1068 self.errors.push(Error::PARSER {
1069 #[cfg(feature = "ast-span")]
1070 position: self.parser_position,
1071 msg: InvalidGenericSyntax.into(),
1072 });
1073
1074 return Err(Error::INCREMENTAL);
1075 }
1076 }
1077 }
1078
1079 #[cfg(feature = "ast-span")]
1084 {
1085 let end_range = self.lexer_position.range.1;
1086 generic_params.span = (begin_range, end_range, self.lexer_position.line);
1087 }
1088
1089 Ok(generic_params)
1090 }
1091
1092 #[allow(missing_docs)]
1093 pub fn parse_genericargs(&mut self) -> Result<GenericArgs<'a>> {
1094 if self.peek_token_is(&Token::LANGLEBRACKET) {
1095 self.next_token()?;
1096 }
1097
1098 #[cfg(feature = "ast-span")]
1099 let begin_generic_arg_range = self.lexer_position.range.0;
1100 #[cfg(feature = "ast-span")]
1101 let begin_generic_arg_line = self.lexer_position.line;
1102
1103 if let Token::LANGLEBRACKET = &self.cur_token {
1105 self.next_token()?;
1106 }
1107
1108 let mut generic_args = GenericArgs::default();
1109
1110 while !self.cur_token_is(Token::RANGLEBRACKET) {
1111 #[cfg(feature = "ast-comments")]
1112 let leading_comments = self.collect_comments()?;
1113 #[cfg(not(feature = "ast-comments"))]
1114 self.advance_newline()?;
1115
1116 let t1 = self.parse_type1(None)?;
1117
1118 #[cfg(feature = "ast-comments")]
1119 let trailing_comments = self.collect_comments()?;
1120 #[cfg(not(feature = "ast-comments"))]
1121 self.advance_newline()?;
1122
1123 generic_args.args.push(GenericArg {
1124 #[cfg(feature = "ast-comments")]
1125 comments_before_type: leading_comments,
1126 arg: Box::from(t1),
1127 #[cfg(feature = "ast-comments")]
1128 comments_after_type: trailing_comments,
1129 });
1130
1131 if let Token::COMMA = self.cur_token {
1132 self.next_token()?;
1133 }
1134
1135 if let Token::EOF = &self.cur_token {
1136 self.errors.push(Error::PARSER {
1137 #[cfg(feature = "ast-span")]
1138 position: self.parser_position,
1139 msg: MissingGenericClosingDelimiter.into(),
1140 });
1141
1142 return Err(Error::INCREMENTAL);
1143 }
1144 }
1145
1146 if let Token::RANGLEBRACKET = &self.cur_token {
1147 #[cfg(feature = "ast-span")]
1148 {
1149 self.parser_position.range.1 = self.lexer_position.range.1;
1150 }
1151 self.next_token()?;
1152 }
1153
1154 #[cfg(feature = "ast-span")]
1155 {
1156 generic_args.span = (
1157 begin_generic_arg_range,
1158 self.parser_position.range.1,
1159 begin_generic_arg_line,
1160 );
1161 }
1162
1163 Ok(generic_args)
1164 }
1165
1166 #[allow(missing_docs)]
1169 pub fn parse_type(&mut self, parenthesized_type: Option<Type2<'a>>) -> Result<Type<'a>> {
1170 #[cfg(feature = "ast-span")]
1171 {
1172 self.parser_position.range = self.lexer_position.range;
1173 self.parser_position.line = self.lexer_position.line;
1174 }
1175
1176 #[cfg(feature = "ast-span")]
1177 let begin_type_range = if let Some(Type2::ParenthesizedType { span, .. }) = parenthesized_type {
1178 self.parser_position.line = span.2;
1179
1180 span.0
1181 } else {
1182 self.parser_position.range.0
1183 };
1184
1185 let mut t = Type {
1186 type_choices: Vec::new(),
1187 #[cfg(feature = "ast-span")]
1188 span: (begin_type_range, 0, self.parser_position.line),
1189 };
1190
1191 #[cfg(feature = "ast-comments")]
1192 let mut tc = TypeChoice {
1193 type1: self.parse_type1(parenthesized_type)?,
1194 comments_before_type: None,
1195 comments_after_type: None,
1196 };
1197
1198 #[cfg(not(feature = "ast-comments"))]
1199 let tc = TypeChoice {
1200 type1: self.parse_type1(parenthesized_type)?,
1201 };
1202
1203 #[cfg(feature = "ast-comments")]
1204 {
1205 tc.comments_after_type = self.collect_comments()?;
1206 }
1207 #[cfg(not(feature = "ast-comments"))]
1208 self.advance_newline()?;
1209
1210 t.type_choices.push(tc);
1211
1212 while let Token::TCHOICE = &self.cur_token {
1213 self.next_token()?;
1214
1215 #[cfg(feature = "ast-comments")]
1216 let comments_before_type = self.collect_comments()?;
1217 #[cfg(not(feature = "ast-comments"))]
1218 self.advance_newline()?;
1219
1220 #[cfg(feature = "ast-comments")]
1221 let mut tc = TypeChoice {
1222 comments_before_type,
1223 comments_after_type: None,
1224 type1: self.parse_type1(None)?,
1225 };
1226
1227 #[cfg(not(feature = "ast-comments"))]
1228 let tc = TypeChoice {
1229 type1: self.parse_type1(None)?,
1230 };
1231
1232 #[cfg(feature = "ast-comments")]
1233 {
1234 tc.comments_after_type = self.collect_comments()?;
1235 }
1236 #[cfg(not(feature = "ast-comments"))]
1237 self.advance_newline()?;
1238
1239 t.type_choices.push(tc);
1240 }
1241
1242 #[cfg(feature = "ast-span")]
1243 {
1244 t.span.1 = self.parser_position.range.1;
1245 }
1246
1247 Ok(t)
1248 }
1249
1250 #[allow(missing_docs)]
1253 pub fn parse_type1(&mut self, parenthesized_type: Option<Type2<'a>>) -> Result<Type1<'a>> {
1254 #[cfg(feature = "ast-span")]
1255 let mut begin_type1_line = self.lexer_position.line;
1256 #[cfg(feature = "ast-span")]
1257 let mut begin_type1_range = self.lexer_position.range.0;
1258
1259 let t2_1 = if let Some(Type2::ParenthesizedType {
1260 #[cfg(feature = "ast-comments")]
1261 comments_before_type,
1262 pt,
1263 #[cfg(feature = "ast-comments")]
1264 comments_after_type,
1265 #[cfg(feature = "ast-span")]
1266 span,
1267 }) = parenthesized_type
1268 {
1269 #[cfg(feature = "ast-span")]
1270 {
1271 begin_type1_line = span.2;
1272 begin_type1_range = span.0;
1273 }
1274
1275 Type2::ParenthesizedType {
1276 #[cfg(feature = "ast-comments")]
1277 comments_before_type,
1278 pt,
1279 #[cfg(feature = "ast-comments")]
1280 comments_after_type,
1281 #[cfg(feature = "ast-span")]
1282 span,
1283 }
1284 } else {
1285 self.parse_type2()?
1286 };
1287
1288 #[cfg(feature = "ast-span")]
1289 let mut span = (
1290 begin_type1_range,
1291 self.lexer_position.range.1,
1292 begin_type1_line,
1293 );
1294
1295 #[cfg(feature = "ast-comments")]
1296 let comments_after_type = self.collect_comments()?;
1297 #[cfg(not(feature = "ast-comments"))]
1298 self.advance_newline()?;
1299
1300 let op = match &self.cur_token {
1301 Token::RANGEOP(i) => {
1302 #[cfg(feature = "ast-span")]
1303 {
1304 span.0 = self.lexer_position.range.0;
1305 }
1306
1307 Some(RangeCtlOp::RangeOp {
1308 is_inclusive: *i,
1309 #[cfg(feature = "ast-span")]
1310 span,
1311 })
1312 }
1313 Token::ControlOperator(ctrl) => {
1314 #[cfg(feature = "ast-span")]
1315 {
1316 span.0 = self.lexer_position.range.0;
1317 }
1318
1319 Some(RangeCtlOp::CtlOp {
1320 ctrl: *ctrl,
1321 #[cfg(feature = "ast-span")]
1322 span,
1323 })
1324 }
1325 _ => None,
1326 };
1327
1328 #[cfg(feature = "ast-span")]
1329 {
1330 span = (
1331 begin_type1_range,
1332 self.parser_position.range.1,
1333 begin_type1_line,
1334 );
1335 }
1336
1337 match op {
1338 Some(operator) => {
1339 self.next_token()?;
1340
1341 #[cfg(feature = "ast-comments")]
1342 let comments_after_operator = self.collect_comments()?;
1343 #[cfg(not(feature = "ast-comments"))]
1344 self.advance_newline()?;
1345
1346 let t2 = self.parse_type2()?;
1347
1348 #[cfg(feature = "ast-span")]
1349 {
1350 span.1 = self.parser_position.range.1;
1351 }
1352
1353 Ok(Type1 {
1354 type2: t2_1,
1355 operator: Some(Operator {
1356 #[cfg(feature = "ast-comments")]
1357 comments_before_operator: comments_after_type,
1358 operator,
1359 #[cfg(feature = "ast-comments")]
1360 comments_after_operator,
1361 type2: t2,
1362 }),
1363 #[cfg(feature = "ast-comments")]
1364 comments_after_type: None,
1365 #[cfg(feature = "ast-span")]
1366 span,
1367 })
1368 }
1369 None => Ok(Type1 {
1370 type2: t2_1,
1371 operator: None,
1372 #[cfg(feature = "ast-comments")]
1373 comments_after_type,
1374 #[cfg(feature = "ast-span")]
1375 span,
1376 }),
1377 }
1378 }
1379
1380 #[allow(missing_docs)]
1381 pub fn parse_type2(&mut self) -> Result<Type2<'a>> {
1382 let t2 = match &self.cur_token {
1383 Token::VALUE(value) => {
1385 #[cfg(feature = "ast-span")]
1386 {
1387 self.parser_position.range = self.lexer_position.range;
1388 self.parser_position.line = self.lexer_position.line;
1389 }
1390
1391 #[cfg(feature = "ast-span")]
1392 let span = (
1393 self.parser_position.range.0,
1394 self.parser_position.range.1,
1395 self.parser_position.line,
1396 );
1397
1398 match value {
1399 token::Value::TEXT(t) => Ok(Type2::TextValue {
1400 value: t.clone(),
1401 #[cfg(feature = "ast-span")]
1402 span,
1403 }),
1404 token::Value::INT(i) => Ok(Type2::IntValue {
1405 value: *i,
1406 #[cfg(feature = "ast-span")]
1407 span,
1408 }),
1409 token::Value::UINT(ui) => Ok(Type2::UintValue {
1410 value: *ui,
1411 #[cfg(feature = "ast-span")]
1412 span,
1413 }),
1414 token::Value::FLOAT(f) => Ok(Type2::FloatValue {
1415 value: *f,
1416 #[cfg(feature = "ast-span")]
1417 span,
1418 }),
1419 token::Value::BYTE(token::ByteValue::UTF8(Cow::Borrowed(utf8))) => {
1420 Ok(Type2::UTF8ByteString {
1421 value: Cow::Borrowed(utf8),
1422 #[cfg(feature = "ast-span")]
1423 span,
1424 })
1425 }
1426 token::Value::BYTE(token::ByteValue::UTF8(Cow::Owned(utf8))) => {
1427 Ok(Type2::UTF8ByteString {
1428 value: Cow::Owned(utf8.to_owned()),
1429 #[cfg(feature = "ast-span")]
1430 span,
1431 })
1432 }
1433 token::Value::BYTE(token::ByteValue::B16(Cow::Borrowed(b16))) => {
1434 Ok(Type2::B16ByteString {
1435 value: Cow::Borrowed(b16),
1436 #[cfg(feature = "ast-span")]
1437 span,
1438 })
1439 }
1440 token::Value::BYTE(token::ByteValue::B16(Cow::Owned(b16))) => Ok(Type2::B16ByteString {
1441 value: Cow::Owned(b16.to_owned()),
1442 #[cfg(feature = "ast-span")]
1443 span,
1444 }),
1445 token::Value::BYTE(token::ByteValue::B64(Cow::Borrowed(b64))) => {
1446 Ok(Type2::B64ByteString {
1447 value: Cow::Borrowed(b64),
1448 #[cfg(feature = "ast-span")]
1449 span,
1450 })
1451 }
1452 token::Value::BYTE(token::ByteValue::B64(Cow::Owned(b64))) => Ok(Type2::B64ByteString {
1453 value: Cow::Owned(b64.to_owned()),
1454 #[cfg(feature = "ast-span")]
1455 span,
1456 }),
1457 }
1458 }
1459
1460 Token::IDENT(ident, socket) => {
1462 #[cfg(feature = "ast-span")]
1463 let begin_type2_range = self.lexer_position.range.0;
1464 #[cfg(feature = "ast-span")]
1465 let begin_type2_line = self.lexer_position.line;
1466
1467 if self.peek_token_is(&Token::LANGLEBRACKET) {
1469 let ident = self.identifier_from_ident_token(ident, *socket);
1470 let ga = self.parse_genericargs()?;
1471
1472 #[cfg(feature = "ast-span")]
1473 let end_type2_range = self.parser_position.range.1;
1474
1475 if ident.socket.is_none() {
1476 let mut is_generic_param = false;
1477 if let Some(idents) = &self.current_rule_generic_param_idents {
1478 is_generic_param = idents.contains(&ident.ident);
1479 }
1480
1481 #[cfg(feature = "ast-span")]
1482 if !is_generic_param && !self.typenames.contains(ident.ident) {
1483 self.unknown_rule_idents.push((ident.ident, ident.span));
1484 }
1485
1486 #[cfg(not(feature = "ast-span"))]
1487 if !is_generic_param && !self.typenames.contains(ident.ident) {
1488 self.unknown_rule_idents.push(ident.ident);
1489 }
1490 }
1491
1492 return Ok(Type2::Typename {
1493 ident,
1494 generic_args: Some(ga),
1495 #[cfg(feature = "ast-span")]
1496 span: (begin_type2_range, end_type2_range, begin_type2_line),
1497 });
1498 }
1499
1500 #[cfg(feature = "ast-span")]
1501 {
1502 self.parser_position.range = self.lexer_position.range;
1503 self.parser_position.line = self.lexer_position.line;
1504 }
1505
1506 let ident = self.identifier_from_ident_token(ident, *socket);
1507
1508 if ident.socket.is_none() {
1509 let mut is_generic_param = false;
1510 if let Some(idents) = &self.current_rule_generic_param_idents {
1511 is_generic_param = idents.contains(&ident.ident);
1512 }
1513
1514 #[cfg(feature = "ast-span")]
1515 if !is_generic_param && !self.typenames.contains(ident.ident) {
1516 self.unknown_rule_idents.push((ident.ident, ident.span));
1517 }
1518
1519 #[cfg(not(feature = "ast-span"))]
1520 if !is_generic_param && !self.typenames.contains(ident.ident) {
1521 self.unknown_rule_idents.push(ident.ident);
1522 }
1523 }
1524
1525 Ok(Type2::Typename {
1526 ident,
1527 generic_args: None,
1528 #[cfg(feature = "ast-span")]
1529 span: (
1530 self.parser_position.range.0,
1531 self.parser_position.range.1,
1532 self.parser_position.line,
1533 ),
1534 })
1535 }
1536
1537 Token::LPAREN => {
1539 #[cfg(feature = "ast-span")]
1540 let begin_type2_range = self.lexer_position.range.0;
1541 #[cfg(feature = "ast-span")]
1542 let begin_type2_line = self.lexer_position.line;
1543
1544 self.next_token()?;
1545
1546 #[cfg(feature = "ast-comments")]
1547 let comments_before_type = self.collect_comments()?;
1548 #[cfg(not(feature = "ast-comments"))]
1549 self.advance_newline()?;
1550
1551 let pt = self.parse_type(None)?;
1552
1553 #[cfg(feature = "ast-span")]
1554 {
1555 self.parser_position.range.0 = begin_type2_range;
1556 self.parser_position.range.1 = self.lexer_position.range.1;
1557 self.parser_position.line = begin_type2_line;
1558 }
1559
1560 #[cfg(feature = "ast-comments")]
1561 let comments_after_type = self.collect_comments()?;
1562 #[cfg(not(feature = "ast-comments"))]
1563 self.advance_newline()?;
1564
1565 Ok(Type2::ParenthesizedType {
1566 #[cfg(feature = "ast-comments")]
1567 comments_before_type,
1568 #[cfg(feature = "ast-comments")]
1569 comments_after_type,
1570 pt,
1571 #[cfg(feature = "ast-span")]
1572 span: (
1573 self.parser_position.range.0,
1574 self.parser_position.range.1,
1575 self.parser_position.line,
1576 ),
1577 })
1578 }
1579
1580 Token::LBRACE => {
1582 #[cfg(feature = "ast-span")]
1583 let begin_type2_range = self.lexer_position.range.0;
1584 #[cfg(feature = "ast-span")]
1585 let begin_type2_line = self.lexer_position.line;
1586
1587 #[cfg(feature = "ast-comments")]
1588 let mut group = self.parse_group()?;
1589 #[cfg(not(feature = "ast-comments"))]
1590 let group = self.parse_group()?;
1591
1592 #[cfg(feature = "ast-comments")]
1595 let comments_before_group = if let Some(GroupChoice {
1596 comments_before_grpchoice,
1597 ..
1598 }) = group.group_choices.first_mut()
1599 {
1600 comments_before_grpchoice
1601 .as_mut()
1602 .and_then(|comments| {
1603 if comments.0.len() > 1 {
1604 Some(comments.0.remove(0))
1605 } else {
1606 None
1607 }
1608 })
1609 .map(|comment| Comments(vec![comment]))
1610 } else {
1611 None
1612 };
1613
1614 #[cfg(feature = "ast-span")]
1615 let span = (
1616 begin_type2_range,
1617 self.lexer_position.range.1,
1618 begin_type2_line,
1619 );
1620
1621 #[cfg(feature = "ast-comments")]
1622 let comments_after_group = self.collect_comments()?;
1623 #[cfg(not(feature = "ast-comments"))]
1624 self.advance_newline()?;
1625
1626 Ok(Type2::Map {
1627 #[cfg(feature = "ast-comments")]
1628 comments_before_group,
1629 group,
1630 #[cfg(feature = "ast-span")]
1631 span,
1632 #[cfg(feature = "ast-comments")]
1633 comments_after_group,
1634 })
1635 }
1636
1637 Token::LBRACKET => {
1639 #[cfg(feature = "ast-span")]
1640 let begin_type2_range = self.lexer_position.range.0;
1641 #[cfg(feature = "ast-span")]
1642 let begin_type2_line = self.lexer_position.line;
1643
1644 #[cfg(feature = "ast-comments")]
1645 let mut group = self.parse_group()?;
1646 #[cfg(not(feature = "ast-comments"))]
1647 let group = self.parse_group()?;
1648
1649 #[cfg(feature = "ast-comments")]
1652 let comments_before_group = if let Some(GroupChoice {
1653 comments_before_grpchoice,
1654 ..
1655 }) = group.group_choices.first_mut()
1656 {
1657 comments_before_grpchoice
1658 .as_mut()
1659 .and_then(|comments| {
1660 if comments.0.len() > 1 {
1661 Some(comments.0.remove(0))
1662 } else {
1663 None
1664 }
1665 })
1666 .map(|comment| Comments(vec![comment]))
1667 } else {
1668 None
1669 };
1670
1671 #[cfg(feature = "ast-span")]
1672 let span = (
1673 begin_type2_range,
1674 self.lexer_position.range.1,
1675 begin_type2_line,
1676 );
1677
1678 #[cfg(feature = "ast-comments")]
1679 let comments_after_group = self.collect_comments()?;
1680 #[cfg(not(feature = "ast-comments"))]
1681 self.advance_newline()?;
1682
1683 Ok(Type2::Array {
1684 #[cfg(feature = "ast-comments")]
1685 comments_before_group,
1686 group,
1687 #[cfg(feature = "ast-comments")]
1688 comments_after_group,
1689 #[cfg(feature = "ast-span")]
1690 span,
1691 })
1692 }
1693
1694 Token::UNWRAP => {
1696 self.next_token()?;
1697
1698 #[cfg(feature = "ast-comments")]
1699 let comments = self.collect_comments()?;
1700 #[cfg(not(feature = "ast-comments"))]
1701 self.advance_newline()?;
1702
1703 let ident = if let Some(ident) = self.cur_token.in_standard_prelude() {
1704 Some(self.identifier_from_ident_token(ident, None))
1705 } else if let Token::IDENT(ident, socket) = &self.cur_token {
1706 Some(self.identifier_from_ident_token(ident, *socket))
1707 } else {
1708 None
1709 };
1710
1711 if let Some(ident) = ident {
1712 if self.peek_token_is(&Token::LANGLEBRACKET) {
1713 self.next_token()?;
1714
1715 return Ok(Type2::Unwrap {
1716 #[cfg(feature = "ast-comments")]
1717 comments,
1718 ident,
1719 generic_args: Some(self.parse_genericargs()?),
1720 #[cfg(feature = "ast-span")]
1721 span: (0, 0, 0),
1722 });
1723 }
1724
1725 return Ok(Type2::Unwrap {
1726 #[cfg(feature = "ast-comments")]
1727 comments,
1728 ident,
1729 generic_args: None,
1730 #[cfg(feature = "ast-span")]
1731 span: (0, 0, 0),
1732 });
1733 }
1734
1735 self.errors.push(Error::PARSER {
1736 #[cfg(feature = "ast-span")]
1737 position: self.parser_position,
1738 msg: InvalidUnwrapSyntax.into(),
1739 });
1740
1741 Err(Error::INCREMENTAL)
1742 }
1743
1744 Token::GTOCHOICE => {
1747 #[cfg(feature = "ast-span")]
1748 let begin_type2_range = self.lexer_position.range.0;
1749 #[cfg(feature = "ast-span")]
1750 let begin_type2_line = self.lexer_position.line;
1751
1752 self.next_token()?;
1753
1754 #[cfg(feature = "ast-comments")]
1755 let comments = self.collect_comments()?;
1756 #[cfg(not(feature = "ast-comments"))]
1757 self.advance_newline()?;
1758
1759 match &self.cur_token {
1760 Token::LPAREN => {
1761 self.next_token()?;
1762
1763 #[cfg(feature = "ast-comments")]
1764 let comments_before_group = self.collect_comments()?;
1765 #[cfg(not(feature = "ast-comments"))]
1766 self.advance_newline()?;
1767
1768 let group = self.parse_group()?;
1769
1770 #[cfg(feature = "ast-comments")]
1771 let comments_after_group = self.collect_comments()?;
1772 #[cfg(not(feature = "ast-comments"))]
1773 self.advance_newline()?;
1774
1775 Ok(Type2::ChoiceFromInlineGroup {
1776 #[cfg(feature = "ast-comments")]
1777 comments,
1778 #[cfg(feature = "ast-comments")]
1779 comments_before_group,
1780 group,
1781 #[cfg(feature = "ast-comments")]
1782 comments_after_group,
1783 #[cfg(feature = "ast-span")]
1784 span: (
1785 begin_type2_range,
1786 self.parser_position.range.1,
1787 begin_type2_line,
1788 ),
1789 })
1790 }
1791 Token::IDENT(ident, socket) => {
1792 let ident = self.identifier_from_ident_token(ident, *socket);
1793 if self.peek_token_is(&Token::LANGLEBRACKET) {
1794 self.next_token()?;
1795
1796 let generic_args = Some(self.parse_genericargs()?);
1797
1798 return Ok(Type2::ChoiceFromGroup {
1799 #[cfg(feature = "ast-comments")]
1800 comments,
1801 ident,
1802 generic_args,
1803 #[cfg(feature = "ast-span")]
1804 span: (
1805 begin_type2_range,
1806 self.parser_position.range.1,
1807 begin_type2_line,
1808 ),
1809 });
1810 }
1811
1812 #[cfg(feature = "ast-span")]
1813 {
1814 self.parser_position.range.1 = self.lexer_position.range.1;
1815 }
1816
1817 Ok(Type2::ChoiceFromGroup {
1818 #[cfg(feature = "ast-comments")]
1819 comments,
1820 ident,
1821 generic_args: None,
1822 #[cfg(feature = "ast-span")]
1823 span: (
1824 begin_type2_range,
1825 self.parser_position.range.1,
1826 begin_type2_line,
1827 ),
1828 })
1829 }
1830 _ => {
1831 self.errors.push(Error::PARSER {
1832 #[cfg(feature = "ast-span")]
1833 position: self.parser_position,
1834 msg: InvalidGroupToChoiceEnumSyntax.into(),
1835 });
1836 Err(Error::INCREMENTAL)
1837 }
1838 }
1839 }
1840
1841 Token::TAG(mt, constraint) => {
1850 #[cfg(feature = "ast-span")]
1851 let begin_type2_range = self.lexer_position.range.0;
1852 #[cfg(feature = "ast-span")]
1853 let begin_type2_line = self.lexer_position.line;
1854
1855 let mt_val = *mt;
1857 let constraint_val = *constraint;
1858
1859 match (mt_val, constraint_val) {
1860 (Some(6), tag) => {
1862 self.next_token()?;
1863 if !self.cur_token_is(Token::LPAREN) {
1864 self.errors.push(Error::PARSER {
1865 #[cfg(feature = "ast-span")]
1866 position: self.parser_position,
1867 msg: InvalidTagSyntax.into(),
1868 });
1869
1870 return Err(Error::INCREMENTAL);
1871 }
1872
1873 self.next_token()?;
1874
1875 #[cfg(feature = "ast-comments")]
1876 let comments_before_type = self.collect_comments()?;
1877 #[cfg(not(feature = "ast-comments"))]
1878 self.advance_newline()?;
1879
1880 let t = self.parse_type(None)?;
1881
1882 #[cfg(feature = "ast-comments")]
1883 let comments_after_type = self.collect_comments()?;
1884 #[cfg(not(feature = "ast-comments"))]
1885 self.advance_newline()?;
1886
1887 if !self.cur_token_is(Token::RPAREN) {
1888 self.errors.push(Error::PARSER {
1889 #[cfg(feature = "ast-span")]
1890 position: self.parser_position,
1891 msg: InvalidTagSyntax.into(),
1892 });
1893
1894 return Err(Error::INCREMENTAL);
1895 }
1896
1897 Ok(Type2::TaggedData {
1898 tag,
1899 #[cfg(feature = "ast-comments")]
1900 comments_before_type,
1901 t,
1902 #[cfg(feature = "ast-comments")]
1903 comments_after_type,
1904 #[cfg(feature = "ast-span")]
1905 span: (
1906 begin_type2_range,
1907 self.parser_position.range.1,
1908 begin_type2_line,
1909 ),
1910 })
1911 }
1912 (Some(mt), constraint) => Ok(Type2::DataMajorType {
1914 mt,
1915 constraint,
1916 #[cfg(feature = "ast-span")]
1917 span: (
1918 begin_type2_range,
1919 self.lexer_position.range.1,
1920 begin_type2_line,
1921 ),
1922 }),
1923 #[cfg(feature = "ast-span")]
1924 _ => Ok(Type2::Any {
1925 span: (
1926 begin_type2_range,
1927 self.lexer_position.range.1,
1928 begin_type2_line,
1929 ),
1930 }),
1931 #[cfg(not(feature = "ast-span"))]
1932 _ => Ok(Type2::Any {}),
1933 }
1934 }
1935 _ => {
1936 #[cfg(feature = "ast-comments")]
1937 self.collect_comments()?;
1938 #[cfg(not(feature = "ast-comments"))]
1939 self.advance_newline()?;
1940
1941 match self.cur_token.in_standard_prelude() {
1942 Some(s) => {
1943 let ident = self.identifier_from_ident_token(s, None);
1944 #[cfg(feature = "ast-span")]
1945 {
1946 self.parser_position.range = self.lexer_position.range;
1947 self.parser_position.line = self.lexer_position.line;
1948 }
1949
1950 Ok(Type2::Typename {
1951 ident,
1952 generic_args: None,
1953 #[cfg(feature = "ast-span")]
1954 span: (
1955 self.parser_position.range.0,
1956 self.parser_position.range.1,
1957 self.parser_position.line,
1958 ),
1959 })
1960 }
1961 None => {
1962 #[cfg(feature = "ast-span")]
1963 {
1964 self.parser_position.line = self.lexer_position.line;
1965 self.parser_position.range = self.lexer_position.range;
1966 }
1967
1968 if let Token::COLON | Token::ARROWMAP = &self.cur_token {
1969 self.errors.push(Error::PARSER {
1970 #[cfg(feature = "ast-span")]
1971 position: self.parser_position,
1972 msg: MissingGroupEntryMemberKey.into(),
1973 });
1974
1975 return Err(Error::INCREMENTAL);
1976 }
1977
1978 if let Token::RBRACE | Token::RBRACKET | Token::RPAREN = &self.cur_token {
1979 self.errors.push(Error::PARSER {
1980 #[cfg(feature = "ast-span")]
1981 position: self.parser_position,
1982 msg: MissingGroupEntry.into(),
1983 });
1984
1985 return Err(Error::INCREMENTAL);
1986 }
1987
1988 self.errors.push(Error::PARSER {
1989 #[cfg(feature = "ast-span")]
1990 position: self.parser_position,
1991 msg: InvalidGroupEntrySyntax.into(),
1992 });
1993
1994 Err(Error::INCREMENTAL)
1995 }
1996 }
1997 }
1998 };
1999
2000 #[cfg(feature = "ast-span")]
2001 {
2002 self.parser_position.range.1 = self.lexer_position.range.1;
2003 }
2004
2005 self.next_token()?;
2006
2007 t2
2008 }
2009
2010 #[allow(missing_docs)]
2011 pub fn parse_group(&mut self) -> Result<Group<'a>> {
2012 #[cfg(feature = "ast-span")]
2013 let begin_group_range =
2014 if let Token::LBRACE | Token::LPAREN | Token::LBRACKET | Token::GCHOICE = &self.cur_token {
2015 self.peek_lexer_position.range.0
2016 } else {
2017 self.lexer_position.range.0
2018 };
2019
2020 let closing_delimiter = token::closing_delimiter(&self.cur_token);
2021
2022 let mut group = Group {
2023 group_choices: Vec::new(),
2024 #[cfg(feature = "ast-span")]
2025 span: (begin_group_range, 0, self.lexer_position.line),
2026 };
2027
2028 group.group_choices.push(self.parse_grpchoice()?);
2029
2030 while let Token::GCHOICE = &self.cur_token {
2031 group.group_choices.push(self.parse_grpchoice()?);
2032 }
2033
2034 #[cfg(feature = "ast-span")]
2035 {
2036 group.span.1 = self.parser_position.range.1;
2037 }
2038
2039 if let Some(cd) = closing_delimiter.as_ref() {
2040 if cd != &self.cur_token {
2041 self.errors.push(Error::PARSER {
2042 #[cfg(feature = "ast-span")]
2043 position: self.lexer_position,
2044 msg: MissingClosingDelimiter.into(),
2045 });
2046
2047 return Err(Error::INCREMENTAL);
2048 }
2049 }
2050
2051 Ok(group)
2052 }
2053
2054 #[allow(missing_docs)]
2055 pub fn parse_grpchoice(&mut self) -> Result<GroupChoice<'a>> {
2056 let mut grpchoice = GroupChoice {
2057 group_entries: Vec::new(),
2058 #[cfg(feature = "ast-comments")]
2059 comments_before_grpchoice: None,
2060 #[cfg(feature = "ast-span")]
2061 span: (self.lexer_position.range.0, 0, self.lexer_position.line),
2062 };
2063
2064 let mut in_array_context = false;
2066
2067 if let Token::GCHOICE = &self.cur_token {
2068 self.next_token()?;
2069
2070 #[cfg(feature = "ast-comments")]
2071 {
2072 grpchoice.comments_before_grpchoice = self.collect_comments()?;
2073 }
2074 #[cfg(not(feature = "ast-comments"))]
2075 self.advance_newline()?;
2076
2077 #[cfg(feature = "ast-span")]
2078 {
2079 grpchoice.span.0 = self.lexer_position.range.0;
2080 }
2081 } else if let Token::LBRACKET = &self.cur_token {
2082 in_array_context = true;
2084 self.next_token()?;
2085
2086 #[cfg(feature = "ast-span")]
2087 {
2088 grpchoice.span.0 = self.lexer_position.range.0;
2089 }
2090
2091 #[cfg(feature = "ast-comments")]
2092 {
2093 grpchoice.comments_before_grpchoice = self.collect_comments()?;
2094 }
2095 #[cfg(not(feature = "ast-comments"))]
2096 self.advance_newline()?;
2097 } else if let Token::LBRACE = &self.cur_token {
2098 self.next_token()?;
2100
2101 #[cfg(feature = "ast-span")]
2102 {
2103 grpchoice.span.0 = self.lexer_position.range.0;
2104 }
2105
2106 #[cfg(feature = "ast-comments")]
2107 {
2108 grpchoice.comments_before_grpchoice = self.collect_comments()?;
2109 }
2110 #[cfg(not(feature = "ast-comments"))]
2111 self.advance_newline()?;
2112 };
2113
2114 while !self.cur_token_is(Token::RBRACE)
2118 && !self.cur_token_is(Token::RPAREN)
2119 && !self.cur_token_is(Token::RBRACKET)
2120 && !self.cur_token_is(Token::EOF)
2121 {
2122 let ge = if in_array_context {
2123 self.parse_grpent_array_context(false)?
2125 } else {
2126 self.parse_grpent(false)?
2128 };
2129
2130 if let Token::GCHOICE = &self.cur_token {
2131 grpchoice.group_entries.push((
2132 ge,
2133 OptionalComma {
2134 optional_comma: false,
2135 #[cfg(feature = "ast-comments")]
2136 trailing_comments: None,
2137 _a: PhantomData,
2138 },
2139 ));
2140
2141 #[cfg(feature = "ast-span")]
2142 {
2143 grpchoice.span.1 = self.parser_position.range.1;
2144 }
2145
2146 return Ok(grpchoice);
2147 }
2148
2149 if !self.cur_token_is(Token::RPAREN)
2152 && !self.cur_token_is(Token::RBRACE)
2153 && !self.cur_token_is(Token::RBRACKET)
2154 && !self.cur_token_is(Token::LPAREN)
2155 && !self.cur_token_is(Token::LBRACE)
2156 && !self.cur_token_is(Token::LBRACKET)
2157 && !self.cur_token_is(Token::COMMA)
2158 && !self.cur_token_is(Token::OPTIONAL)
2159 && !self.cur_token_is(Token::ONEORMORE)
2160 && !self.cur_token_is(Token::ASTERISK)
2161 && !self.peek_token_is(&Token::COLON)
2162 && !self.peek_token_is(&Token::ARROWMAP)
2163 && !self.cur_token_is(Token::EOF)
2164 && !matches!(self.cur_token, Token::IDENT(..))
2165 {
2166 #[cfg(feature = "ast-span")]
2167 {
2168 self.parser_position.range.1 = self.lexer_position.range.1;
2169 }
2170 self.next_token()?;
2171 }
2172
2173 let mut optional_comma = false;
2174
2175 if let Token::COMMA = &self.cur_token {
2176 optional_comma = true;
2177
2178 #[cfg(feature = "ast-span")]
2179 {
2180 self.parser_position.range.1 = self.lexer_position.range.1;
2181 }
2182 self.next_token()?;
2183 }
2184
2185 #[cfg(feature = "ast-comments")]
2186 let trailing_comments = self.collect_comments()?;
2187 #[cfg(not(feature = "ast-comments"))]
2188 self.advance_newline()?;
2189
2190 grpchoice.group_entries.push((
2191 ge,
2192 OptionalComma {
2193 optional_comma,
2194 #[cfg(feature = "ast-comments")]
2195 trailing_comments,
2196 _a: PhantomData,
2197 },
2198 ));
2199 }
2200
2201 #[cfg(feature = "ast-span")]
2202 {
2203 grpchoice.span.1 = self.parser_position.range.1;
2204 }
2205
2206 Ok(grpchoice)
2207 }
2208
2209 #[allow(missing_docs)]
2210 pub fn parse_grpent(&mut self, from_rule: bool) -> Result<GroupEntry<'a>> {
2211 self.parse_grpent_internal(from_rule, false)
2212 }
2213
2214 fn parse_grpent_array_context(&mut self, from_rule: bool) -> Result<GroupEntry<'a>> {
2215 self.parse_grpent_internal(from_rule, true)
2216 }
2217
2218 fn parse_grpent_internal(
2219 &mut self,
2220 from_rule: bool,
2221 in_array_context: bool,
2222 ) -> Result<GroupEntry<'a>> {
2223 #[cfg(feature = "ast-span")]
2224 let begin_grpent_range = self.lexer_position.range.0;
2225 #[cfg(feature = "ast-span")]
2226 let begin_grpent_line = self.lexer_position.line;
2227
2228 let occur = self.parse_occur(true)?;
2229
2230 let member_key = if from_rule {
2232 None
2233 } else {
2234 self.parse_memberkey(true)?
2235 };
2236
2237 if self.cur_token_is(Token::LPAREN) && member_key.is_none() {
2238 self.next_token()?;
2239
2240 #[cfg(feature = "ast-comments")]
2241 let comments_before_group = self.collect_comments()?;
2242 #[cfg(not(feature = "ast-comments"))]
2243 self.advance_newline()?;
2244
2245 let group = self.parse_group()?;
2246
2247 #[cfg(feature = "ast-span")]
2248 let mut span = (
2249 begin_grpent_range,
2250 self.parser_position.range.1,
2251 begin_grpent_line,
2252 );
2253
2254 #[cfg(feature = "ast-span")]
2255 {
2256 self.parser_position.range.1 = self.lexer_position.range.1;
2257 }
2258
2259 #[cfg(feature = "ast-comments")]
2260 let comments_after_group = self.collect_comments()?;
2261 #[cfg(not(feature = "ast-comments"))]
2262 self.advance_newline()?;
2263
2264 if !self.cur_token_is(Token::RPAREN) {
2265 self.errors.push(Error::PARSER {
2266 #[cfg(feature = "ast-span")]
2267 position: self.lexer_position,
2268 msg: MissingClosingParend.into(),
2269 });
2270 return Err(Error::INCREMENTAL);
2271 }
2272
2273 #[cfg(feature = "ast-span")]
2274 {
2275 span.1 = self.parser_position.range.1;
2276 }
2277
2278 self.next_token()?;
2279
2280 return Ok(GroupEntry::InlineGroup {
2281 occur,
2282 group,
2283 #[cfg(feature = "ast-comments")]
2284 comments_before_group,
2285 #[cfg(feature = "ast-comments")]
2286 comments_after_group,
2287 #[cfg(feature = "ast-span")]
2288 span,
2289 });
2290 }
2291
2292 #[cfg(feature = "ast-span")]
2293 let mut span = (
2294 begin_grpent_range,
2295 self.parser_position.range.1,
2296 begin_grpent_line,
2297 );
2298
2299 match member_key {
2300 Some(MemberKey::NonMemberKey {
2301 #[cfg(feature = "ast-comments")]
2302 non_member_key: NonMemberKey::Type(mut entry_type),
2303 #[cfg(not(feature = "ast-comments"))]
2304 non_member_key: NonMemberKey::Type(entry_type),
2305 #[cfg(feature = "ast-comments")]
2306 comments_before_type_or_group,
2307 #[cfg(feature = "ast-comments")]
2308 comments_after_type_or_group,
2309 }) => {
2310 #[cfg(feature = "ast-span")]
2311 if let Token::COMMA = &self.cur_token {
2312 span.1 = self.lexer_position.range.1;
2313 }
2314
2315 #[cfg(feature = "ast-comments")]
2316 let trailing_comments = entry_type.take_comments_after_type();
2317
2318 #[cfg(feature = "ast-span")]
2319 if let Some((name, generic_args, _)) = entry_type.groupname_entry() {
2320 if self.groupnames.contains(name.ident) || matches!(name.socket, Some(SocketPlug::GROUP))
2321 {
2322 if name.socket.is_none() {
2323 self.unknown_rule_idents = self
2324 .unknown_rule_idents
2325 .clone()
2326 .into_iter()
2327 .filter(|(ident, _)| ident != &name.ident)
2328 .collect();
2329 }
2330 return Ok(GroupEntry::TypeGroupname {
2331 ge: TypeGroupnameEntry {
2332 occur,
2333 name,
2334 generic_args,
2335 },
2336 #[cfg(feature = "ast-comments")]
2337 leading_comments: comments_before_type_or_group,
2338 #[cfg(feature = "ast-comments")]
2339 trailing_comments,
2340 span,
2341 });
2342 }
2343 }
2344
2345 #[cfg(not(feature = "ast-span"))]
2346 if let Some((name, generic_args)) = entry_type.groupname_entry() {
2347 if self.groupnames.contains(name.ident) || matches!(name.socket, Some(SocketPlug::GROUP))
2348 {
2349 if name.socket.is_none() {
2350 self.unknown_rule_idents = self
2351 .unknown_rule_idents
2352 .clone()
2353 .into_iter()
2354 .filter(|ident| ident != &name.ident)
2355 .collect();
2356 }
2357 return Ok(GroupEntry::TypeGroupname {
2358 ge: TypeGroupnameEntry {
2359 occur,
2360 name,
2361 generic_args,
2362 },
2363 #[cfg(feature = "ast-comments")]
2364 leading_comments: comments_before_type_or_group,
2365 #[cfg(feature = "ast-comments")]
2366 trailing_comments,
2367 });
2368 }
2369 }
2370
2371 if let Token::LPAREN | Token::LBRACE | Token::LBRACKET = self.cur_token {
2375 self.next_token()?;
2376 }
2377
2378 #[cfg(feature = "ast-comments")]
2379 let trailing_comments = if let Some(comments) = entry_type.split_comments_after_type() {
2380 Some(comments)
2381 } else {
2382 comments_after_type_or_group
2383 };
2384
2385 Ok(GroupEntry::ValueMemberKey {
2386 ge: Box::from(ValueMemberKeyEntry {
2387 occur,
2388 member_key: None,
2389 entry_type,
2390 }),
2391 #[cfg(feature = "ast-comments")]
2392 leading_comments: comments_before_type_or_group,
2393 #[cfg(feature = "ast-comments")]
2394 trailing_comments,
2395 #[cfg(feature = "ast-span")]
2396 span,
2397 })
2398 }
2399 Some(MemberKey::NonMemberKey {
2400 non_member_key: NonMemberKey::Group(group),
2401 #[cfg(feature = "ast-comments")]
2402 comments_before_type_or_group,
2403 #[cfg(feature = "ast-comments")]
2404 comments_after_type_or_group,
2405 }) => {
2406 #[cfg(feature = "ast-span")]
2407 if let Token::COMMA = &self.cur_token {
2408 span.1 = self.lexer_position.range.1;
2409 }
2410
2411 Ok(GroupEntry::InlineGroup {
2412 occur,
2413 group,
2414 #[cfg(feature = "ast-span")]
2415 span,
2416 #[cfg(feature = "ast-comments")]
2417 comments_before_group: comments_before_type_or_group,
2418 #[cfg(feature = "ast-comments")]
2419 comments_after_group: comments_after_type_or_group,
2420 })
2421 }
2422 member_key @ Some(_) => {
2423 #[cfg(feature = "ast-comments")]
2424 let mut entry_type = self.parse_type(None)?;
2425 #[cfg(not(feature = "ast-comments"))]
2426 let entry_type = self.parse_type(None)?;
2427
2428 #[cfg(feature = "ast-comments")]
2429 let trailing_comments = entry_type.split_comments_after_type();
2430
2431 #[cfg(feature = "ast-span")]
2432 {
2433 span.1 = self.parser_position.range.1;
2434 }
2435
2436 #[cfg(feature = "ast-span")]
2437 if let Token::COMMA = &self.cur_token {
2438 span.1 = self.lexer_position.range.1;
2439 }
2440
2441 Ok(GroupEntry::ValueMemberKey {
2442 ge: Box::from(ValueMemberKeyEntry {
2443 occur,
2444 member_key,
2445 entry_type,
2446 }),
2447 #[cfg(feature = "ast-comments")]
2448 leading_comments: None,
2449 #[cfg(feature = "ast-comments")]
2450 trailing_comments,
2451 #[cfg(feature = "ast-span")]
2452 span,
2453 })
2454 }
2455 None => {
2456 #[cfg(feature = "ast-comments")]
2457 let mut entry_type = self.parse_type(None)?;
2458 #[cfg(not(feature = "ast-comments"))]
2459 let entry_type = self.parse_type(None)?;
2460
2461 #[cfg(feature = "ast-span")]
2462 {
2463 span.1 = self.parser_position.range.1;
2464 }
2465
2466 #[cfg(feature = "ast-comments")]
2467 let trailing_comments = if let Some(comments) = entry_type.take_comments_after_type() {
2468 Some(comments)
2469 } else {
2470 self.collect_comments()?
2471 };
2472 #[cfg(not(feature = "ast-comments"))]
2473 self.advance_newline()?;
2474
2475 #[cfg(feature = "ast-span")]
2476 if let Token::COMMA = &self.cur_token {
2477 span.1 = self.lexer_position.range.1;
2478 }
2479
2480 #[cfg(feature = "ast-span")]
2481 if let Some((name, generic_args, _)) = entry_type.groupname_entry() {
2482 if self.groupnames.contains(name.ident) || matches!(name.socket, Some(SocketPlug::GROUP))
2484 {
2485 if generic_args.is_some() && self.peek_token_is(&Token::LANGLEBRACKET) {
2486 while !self.peek_token_is(&Token::RANGLEBRACKET) {
2487 self.next_token()?;
2488 }
2489
2490 self.next_token()?;
2491 }
2492
2493 if name.socket.is_none() {
2494 self.unknown_rule_idents = self
2495 .unknown_rule_idents
2496 .clone()
2497 .into_iter()
2498 .filter(|(ident, _)| ident != &name.ident)
2499 .collect();
2500 }
2501 return Ok(GroupEntry::TypeGroupname {
2502 ge: TypeGroupnameEntry {
2503 occur,
2504 name,
2505 generic_args,
2506 },
2507 #[cfg(feature = "ast-comments")]
2508 leading_comments: None,
2509 #[cfg(feature = "ast-comments")]
2510 trailing_comments,
2511 span,
2512 });
2513 }
2514 }
2515
2516 #[cfg(not(feature = "ast-span"))]
2517 if let Some((name, generic_args)) = entry_type.groupname_entry() {
2518 if self.groupnames.contains(name.ident) || matches!(name.socket, Some(SocketPlug::GROUP))
2519 {
2520 if generic_args.is_some() && self.peek_token_is(&Token::LANGLEBRACKET) {
2521 while !self.peek_token_is(&Token::RANGLEBRACKET) {
2522 self.next_token()?;
2523 }
2524
2525 self.next_token()?;
2526 }
2527
2528 if name.socket.is_none() {
2529 self.unknown_rule_idents = self
2530 .unknown_rule_idents
2531 .clone()
2532 .into_iter()
2533 .filter(|ident| ident != &name.ident)
2534 .collect();
2535 }
2536 return Ok(GroupEntry::TypeGroupname {
2537 ge: TypeGroupnameEntry {
2538 occur,
2539 name,
2540 generic_args,
2541 },
2542 #[cfg(feature = "ast-comments")]
2543 leading_comments: None,
2544 #[cfg(feature = "ast-comments")]
2545 trailing_comments,
2546 });
2547 }
2548 }
2549
2550 #[cfg(feature = "ast-span")]
2557 if !from_rule && !in_array_context && member_key.is_none() {
2558 if let Some((name, generic_args, _)) = entry_type.groupname_entry() {
2559 return Ok(GroupEntry::TypeGroupname {
2560 ge: TypeGroupnameEntry {
2561 occur,
2562 name,
2563 generic_args,
2564 },
2565 #[cfg(feature = "ast-comments")]
2566 leading_comments: None,
2567 #[cfg(feature = "ast-comments")]
2568 trailing_comments,
2569 span,
2570 });
2571 }
2572 }
2573
2574 #[cfg(not(feature = "ast-span"))]
2575 if !from_rule && !in_array_context && member_key.is_none() {
2576 if let Some((name, generic_args)) = entry_type.groupname_entry() {
2577 return Ok(GroupEntry::TypeGroupname {
2578 ge: TypeGroupnameEntry {
2579 occur,
2580 name,
2581 generic_args,
2582 },
2583 #[cfg(feature = "ast-comments")]
2584 leading_comments: None,
2585 #[cfg(feature = "ast-comments")]
2586 trailing_comments,
2587 });
2588 }
2589 }
2590
2591 Ok(GroupEntry::ValueMemberKey {
2592 ge: Box::from(ValueMemberKeyEntry {
2593 occur,
2594 member_key: None,
2595 entry_type,
2596 }),
2597 #[cfg(feature = "ast-comments")]
2598 leading_comments: None,
2599 #[cfg(feature = "ast-comments")]
2600 trailing_comments,
2601 #[cfg(feature = "ast-span")]
2602 span,
2603 })
2604 }
2605 }
2606 }
2607
2608 fn parse_memberkey_from_ident(
2612 &mut self,
2613 is_optional: bool,
2614 ident: &'a str,
2615 socket: Option<token::SocketPlug>,
2616 #[cfg(feature = "ast-span")] begin_memberkey_range: usize,
2617 #[cfg(feature = "ast-span")] begin_memberkey_line: usize,
2618 ) -> Result<Option<MemberKey<'a>>> {
2619 if !self.peek_token_is(&Token::COLON)
2620 && !self.peek_token_is(&Token::ARROWMAP)
2621 && !self.peek_token_is(&Token::CUT)
2622 && is_optional
2623 {
2624 return Ok(None);
2625 }
2626
2627 #[cfg(feature = "ast-span")]
2628 {
2629 self.parser_position.range.1 = self.peek_lexer_position.range.1;
2630 }
2631
2632 #[cfg(feature = "ast-span")]
2633 let end_t1_range = self.lexer_position.range.1;
2634
2635 #[cfg(feature = "ast-span")]
2636 let mut ident = self.identifier_from_ident_token(ident, socket);
2637 #[cfg(not(feature = "ast-span"))]
2638 let ident = self.identifier_from_ident_token(ident, socket);
2639 #[cfg(feature = "ast-span")]
2640 {
2641 ident.span = (begin_memberkey_range, end_t1_range, begin_memberkey_line);
2642 }
2643
2644 self.next_token()?;
2645
2646 #[cfg(feature = "ast-comments")]
2647 let comments_before_cut = self.collect_comments()?;
2648 #[cfg(not(feature = "ast-comments"))]
2649 self.advance_newline()?;
2650
2651 let mk = if let Token::CUT = &self.cur_token {
2652 self.next_token()?;
2653
2654 #[cfg(feature = "ast-comments")]
2655 let comments_after_cut = self.collect_comments()?;
2656 #[cfg(not(feature = "ast-comments"))]
2657 self.advance_newline()?;
2658
2659 if !self.cur_token_is(Token::ARROWMAP) {
2660 self.errors.push(Error::PARSER {
2661 #[cfg(feature = "ast-span")]
2662 position: self.lexer_position,
2663 msg: InvalidMemberKeyArrowMapSyntax.into(),
2664 });
2665 return Err(Error::INCREMENTAL);
2666 }
2667
2668 #[cfg(feature = "ast-span")]
2669 let end_memberkey_range = self.lexer_position.range.1;
2670
2671 #[cfg(feature = "ast-comments")]
2672 let comments_after_arrowmap = if let Token::COMMENT(_) = self.peek_token {
2673 self.next_token()?;
2674
2675 self.collect_comments()?
2676 } else {
2677 None
2678 };
2679
2680 #[cfg(not(feature = "ast-comments"))]
2681 self.advance_newline()?;
2682
2683 let t1 = MemberKey::Type1 {
2684 t1: Box::from(Type1 {
2685 type2: Type2::Typename {
2686 ident,
2687 generic_args: None,
2688 #[cfg(feature = "ast-span")]
2689 span: (begin_memberkey_range, end_t1_range, begin_memberkey_line),
2690 },
2691 operator: None,
2692 #[cfg(feature = "ast-comments")]
2693 comments_after_type: None,
2694 #[cfg(feature = "ast-span")]
2695 span: (begin_memberkey_range, end_t1_range, begin_memberkey_line),
2696 }),
2697 #[cfg(feature = "ast-comments")]
2698 comments_before_cut,
2699 is_cut: true,
2700 #[cfg(feature = "ast-comments")]
2701 comments_after_cut,
2702 #[cfg(feature = "ast-comments")]
2703 comments_after_arrowmap,
2704 #[cfg(feature = "ast-span")]
2705 span: (
2706 begin_memberkey_range,
2707 end_memberkey_range,
2708 begin_memberkey_line,
2709 ),
2710 };
2711
2712 self.next_token()?;
2713
2714 Some(t1)
2715 } else if let Token::ARROWMAP = &self.cur_token {
2716 #[cfg(feature = "ast-span")]
2717 let end_memberkey_range = self.lexer_position.range.1;
2718
2719 #[cfg(feature = "ast-comments")]
2720 let comments_after_arrowmap = if let Token::COMMENT(_) = &self.peek_token {
2721 self.next_token()?;
2722
2723 self.collect_comments()?
2724 } else {
2725 None
2726 };
2727
2728 #[cfg(not(feature = "ast-comments"))]
2729 self.advance_newline()?;
2730
2731 let t1 = MemberKey::Type1 {
2732 t1: Box::from(Type1 {
2733 type2: Type2::Typename {
2734 ident,
2735 generic_args: None,
2736 #[cfg(feature = "ast-span")]
2737 span: (begin_memberkey_range, end_t1_range, begin_memberkey_line),
2738 },
2739 operator: None,
2740 #[cfg(feature = "ast-comments")]
2741 comments_after_type: None,
2742 #[cfg(feature = "ast-span")]
2743 span: (begin_memberkey_range, end_t1_range, begin_memberkey_line),
2744 }),
2745 #[cfg(feature = "ast-comments")]
2746 comments_before_cut,
2747 is_cut: false,
2748 #[cfg(feature = "ast-comments")]
2749 comments_after_cut: None,
2750 #[cfg(feature = "ast-comments")]
2751 comments_after_arrowmap,
2752 #[cfg(feature = "ast-span")]
2753 span: (
2754 begin_memberkey_range,
2755 end_memberkey_range,
2756 begin_memberkey_line,
2757 ),
2758 };
2759
2760 self.next_token()?;
2761
2762 #[cfg(feature = "ast-comments")]
2763 let _ = self.collect_comments()?;
2764 #[cfg(not(feature = "ast-comments"))]
2765 self.advance_newline()?;
2766
2767 Some(t1)
2768 } else {
2769 if let Token::COLON = &self.cur_token {
2770 self.next_token()?;
2771 }
2772
2773 #[cfg(feature = "ast-comments")]
2774 let comments_after_colon = self.collect_comments()?;
2775 #[cfg(not(feature = "ast-comments"))]
2776 self.advance_newline()?;
2777
2778 Some(MemberKey::Bareword {
2779 ident,
2780 #[cfg(feature = "ast-comments")]
2781 comments: comments_before_cut,
2782 #[cfg(feature = "ast-comments")]
2783 comments_after_colon,
2784 #[cfg(feature = "ast-span")]
2785 span: (
2786 begin_memberkey_range,
2787 self.parser_position.range.1,
2788 begin_memberkey_line,
2789 ),
2790 })
2791 };
2792
2793 Ok(mk)
2794 }
2795
2796 #[allow(missing_docs)]
2797 pub fn parse_memberkey(&mut self, is_optional: bool) -> Result<Option<MemberKey<'a>>> {
2798 #[cfg(feature = "ast-span")]
2799 let begin_memberkey_range = self.lexer_position.range.0;
2800 #[cfg(feature = "ast-span")]
2801 let begin_memberkey_line = self.lexer_position.line;
2802
2803 if let Some(t) = self.cur_token.in_standard_prelude() {
2804 return self.parse_memberkey_from_ident(
2805 is_optional,
2806 t,
2807 None,
2808 #[cfg(feature = "ast-span")]
2809 begin_memberkey_range,
2810 #[cfg(feature = "ast-span")]
2811 begin_memberkey_line,
2812 );
2813 }
2814
2815 match &self.cur_token {
2816 Token::IDENT(ident, socket) => {
2817 let ident = *ident;
2818 let socket = *socket;
2819
2820 self.parse_memberkey_from_ident(
2821 is_optional,
2822 ident,
2823 socket,
2824 #[cfg(feature = "ast-span")]
2825 begin_memberkey_range,
2826 #[cfg(feature = "ast-span")]
2827 begin_memberkey_line,
2828 )
2829 }
2830 Token::VALUE(value) => {
2831 if !self.peek_token_is(&Token::COLON)
2832 && !self.peek_token_is(&Token::ARROWMAP)
2833 && !self.peek_token_is(&Token::CUT)
2834 && is_optional
2835 {
2836 return Ok(None);
2837 }
2838
2839 #[cfg(feature = "ast-span")]
2840 {
2841 self.parser_position.range.1 = self.peek_lexer_position.range.1;
2842 }
2843
2844 let value = value.clone();
2845
2846 let t1 = self.parse_type1(None)?;
2847
2848 #[cfg(feature = "ast-comments")]
2849 let comments_before_cut = self.collect_comments()?;
2850 #[cfg(not(feature = "ast-comments"))]
2851 self.advance_newline()?;
2852
2853 let mk = if let Token::CUT = &self.cur_token {
2854 self.next_token()?;
2855
2856 #[cfg(feature = "ast-comments")]
2857 let comments_after_cut = self.collect_comments()?;
2858 #[cfg(not(feature = "ast-comments"))]
2859 self.advance_newline()?;
2860
2861 if !self.cur_token_is(Token::ARROWMAP) {
2862 self.errors.push(Error::PARSER {
2863 #[cfg(feature = "ast-span")]
2864 position: self.lexer_position,
2865 msg: InvalidMemberKeyArrowMapSyntax.into(),
2866 });
2867 return Err(Error::INCREMENTAL);
2868 }
2869
2870 #[cfg(feature = "ast-span")]
2871 let end_memberkey_range = self.lexer_position.range.1;
2872
2873 self.next_token()?;
2874
2875 #[cfg(feature = "ast-comments")]
2876 let memberkey_comments = self.collect_comments()?;
2877 #[cfg(not(feature = "ast-comments"))]
2878 self.advance_newline()?;
2879
2880 Some(MemberKey::Type1 {
2881 t1: Box::from(t1),
2882 #[cfg(feature = "ast-comments")]
2883 comments_before_cut,
2884 is_cut: true,
2885 #[cfg(feature = "ast-comments")]
2886 comments_after_cut,
2887 #[cfg(feature = "ast-comments")]
2888 comments_after_arrowmap: memberkey_comments,
2889 #[cfg(feature = "ast-span")]
2890 span: (
2891 begin_memberkey_range,
2892 end_memberkey_range,
2893 begin_memberkey_line,
2894 ),
2895 })
2896 } else {
2897 #[cfg(feature = "ast-comments")]
2898 let comments = self.collect_comments()?;
2899 #[cfg(not(feature = "ast-comments"))]
2900 self.advance_newline()?;
2901
2902 if !self.cur_token_is(Token::ARROWMAP) && !self.cur_token_is(Token::COLON) {
2903 self.errors.push(Error::PARSER {
2904 #[cfg(feature = "ast-span")]
2905 position: self.lexer_position,
2906 msg: InvalidMemberKeySyntax.into(),
2907 });
2908 return Err(Error::INCREMENTAL);
2909 }
2910
2911 #[cfg(feature = "ast-span")]
2912 {
2913 self.parser_position.range.1 = self.lexer_position.range.1;
2914 }
2915
2916 self.next_token()?;
2917
2918 #[cfg(feature = "ast-comments")]
2919 let memberkey_comments = self.collect_comments()?;
2920 #[cfg(not(feature = "ast-comments"))]
2921 self.advance_newline()?;
2922
2923 Some(MemberKey::Value {
2924 value,
2925 #[cfg(feature = "ast-comments")]
2926 comments,
2927 #[cfg(feature = "ast-comments")]
2928 comments_after_colon: memberkey_comments,
2929 #[cfg(feature = "ast-span")]
2930 span: (
2931 begin_memberkey_range,
2932 self.parser_position.range.1,
2933 begin_memberkey_line,
2934 ),
2935 })
2936 };
2937
2938 if let Token::COLON = &self.cur_token {
2939 self.next_token()?;
2940 }
2941
2942 Ok(mk)
2943 }
2944 Token::LPAREN => {
2947 #[cfg(feature = "ast-span")]
2948 let begin_memberkey_range = self.lexer_position.range.0;
2949 #[cfg(feature = "ast-span")]
2950 let begin_memberkey_line = self.lexer_position.line;
2951
2952 let mut nested_parend_count = 0;
2953
2954 self.next_token()?;
2955
2956 #[cfg(feature = "ast-comments")]
2957 let comments_before_type_or_group = self.collect_comments()?;
2958 #[cfg(not(feature = "ast-comments"))]
2959 self.advance_newline()?;
2960
2961 let mut tokens: Vec<lexer::Item> = Vec::new();
2962
2963 #[cfg(feature = "ast-comments")]
2964 let mut comments_after_type_or_group = None;
2965
2966 let mut has_group_entries = false;
2967 let mut closing_parend = false;
2968 #[cfg(feature = "ast-span")]
2969 let mut closing_parend_index = 0;
2970 while !closing_parend {
2971 if let Token::ARROWMAP
2972 | Token::COLON
2973 | Token::OPTIONAL
2974 | Token::ASTERISK
2975 | Token::GCHOICE = &self.cur_token
2976 {
2977 has_group_entries = true;
2978 }
2979
2980 if let Token::LPAREN = &self.cur_token {
2982 nested_parend_count += 1;
2983 }
2984
2985 if let Token::RPAREN = &self.cur_token {
2986 match nested_parend_count.cmp(&0) {
2987 Ordering::Greater => nested_parend_count -= 1,
2988 Ordering::Equal | Ordering::Less => {
2989 closing_parend = true;
2990 #[cfg(feature = "ast-span")]
2991 {
2992 closing_parend_index = self.lexer_position.range.1;
2993 }
2994 }
2995 }
2996 }
2997
2998 tokens.push(Ok((self.lexer_position, self.cur_token.clone())));
2999
3000 #[cfg(feature = "ast-span")]
3001 {
3002 self.parser_position.range.1 = self.lexer_position.range.1;
3003 }
3004
3005 self.next_token()?;
3006
3007 #[cfg(feature = "ast-comments")]
3008 {
3009 comments_after_type_or_group = self.collect_comments()?;
3010 }
3011 #[cfg(not(feature = "ast-comments"))]
3012 self.advance_newline()?;
3013
3014 if let Token::EOF = &self.cur_token {
3015 self.errors.push(Error::PARSER {
3016 #[cfg(feature = "ast-span")]
3017 position: self.lexer_position,
3018 msg: MissingClosingParend.into(),
3019 });
3020
3021 return Err(Error::INCREMENTAL);
3022 }
3023 }
3024
3025 let mut parser = Parser::new(self.str_input, Box::new(tokens.into_iter()))?;
3027 parser.groupnames = self.groupnames.clone();
3028 parser.typenames = self.typenames.clone();
3029
3030 if has_group_entries {
3032 let group = match parser.parse_group() {
3033 Ok(g) => g,
3034 Err(Error::INCREMENTAL) => {
3035 for e in parser.errors.into_iter() {
3036 self.errors.push(e);
3037 }
3038
3039 return Err(Error::INCREMENTAL);
3040 }
3041 Err(e) => return Err(e),
3042 };
3043 self
3044 .unknown_rule_idents
3045 .append(&mut parser.unknown_rule_idents);
3046
3047 return Ok(Some(MemberKey::NonMemberKey {
3048 non_member_key: NonMemberKey::Group(group),
3049 #[cfg(feature = "ast-comments")]
3050 comments_before_type_or_group,
3051 #[cfg(feature = "ast-comments")]
3052 comments_after_type_or_group,
3053 }));
3054 }
3055
3056 let t = match parser.parse_type(None) {
3058 Ok(t) => t,
3059 Err(Error::INCREMENTAL) => {
3060 for e in parser.errors.into_iter() {
3061 self.errors.push(e);
3062 }
3063
3064 return Err(Error::INCREMENTAL);
3065 }
3066 Err(e) => return Err(e),
3067 };
3068 self
3069 .unknown_rule_idents
3070 .append(&mut parser.unknown_rule_idents);
3071
3072 #[cfg(feature = "ast-comments")]
3073 let comments_before_cut = self.collect_comments()?;
3074 #[cfg(not(feature = "ast-comments"))]
3075 self.advance_newline()?;
3076
3077 if let Token::CUT = &self.cur_token {
3078 self.next_token()?;
3079
3080 #[cfg(feature = "ast-comments")]
3081 let comments_after_cut = self.collect_comments()?;
3082 #[cfg(not(feature = "ast-comments"))]
3083 self.advance_newline()?;
3084
3085 if !self.cur_token_is(Token::ARROWMAP) {
3086 self.errors.push(Error::PARSER {
3087 #[cfg(feature = "ast-span")]
3088 position: self.lexer_position,
3089 msg: InvalidMemberKeyArrowMapSyntax.into(),
3090 });
3091 return Err(Error::INCREMENTAL);
3092 }
3093
3094 #[cfg(feature = "ast-span")]
3095 let end_memberkey_range = self.lexer_position.range.1;
3096
3097 let t1 = Some(MemberKey::Type1 {
3098 t1: Box::from(Type1 {
3099 type2: Type2::ParenthesizedType {
3100 pt: t,
3101 #[cfg(feature = "ast-comments")]
3102 comments_before_type: comments_before_type_or_group,
3103 #[cfg(feature = "ast-comments")]
3104 comments_after_type: comments_after_type_or_group,
3105 #[cfg(feature = "ast-span")]
3106 span: (
3107 begin_memberkey_range,
3108 closing_parend_index,
3109 begin_memberkey_line,
3110 ),
3111 },
3112 #[cfg(feature = "ast-comments")]
3113 comments_after_type: comments_before_cut.clone(),
3114 operator: None,
3115 #[cfg(feature = "ast-span")]
3116 span: (
3117 begin_memberkey_range,
3118 closing_parend_index,
3119 begin_memberkey_line,
3120 ),
3121 }),
3122 #[cfg(feature = "ast-comments")]
3123 comments_before_cut,
3124 is_cut: true,
3125 #[cfg(feature = "ast-comments")]
3126 comments_after_cut,
3127 #[cfg(feature = "ast-comments")]
3128 comments_after_arrowmap: None,
3129 #[cfg(feature = "ast-span")]
3130 span: (
3131 begin_memberkey_range,
3132 end_memberkey_range,
3133 begin_memberkey_line,
3134 ),
3135 });
3136
3137 return Ok(t1);
3138 }
3139
3140 let t1 = if let Token::ARROWMAP = &self.cur_token {
3141 self.next_token()?;
3142
3143 #[cfg(feature = "ast-span")]
3144 {
3145 self.parser_position.range.1 = self.lexer_position.range.1;
3146 }
3147
3148 #[cfg(feature = "ast-comments")]
3149 let memberkey_comments = self.collect_comments()?;
3150 #[cfg(not(feature = "ast-comments"))]
3151 self.advance_newline()?;
3152
3153 Some(MemberKey::Type1 {
3154 t1: Box::from(Type1 {
3155 type2: Type2::ParenthesizedType {
3156 pt: t,
3157 #[cfg(feature = "ast-comments")]
3158 comments_before_type: comments_before_type_or_group,
3159 #[cfg(feature = "ast-comments")]
3160 comments_after_type: comments_after_type_or_group,
3161 #[cfg(feature = "ast-span")]
3162 span: (
3163 begin_memberkey_range,
3164 closing_parend_index,
3165 begin_memberkey_line,
3166 ),
3167 },
3168 #[cfg(feature = "ast-comments")]
3169 comments_after_type: comments_before_cut.clone(),
3170 operator: None,
3171 #[cfg(feature = "ast-span")]
3172 span: (
3173 begin_memberkey_range,
3174 closing_parend_index,
3175 begin_memberkey_line,
3176 ),
3177 }),
3178 #[cfg(feature = "ast-comments")]
3179 comments_before_cut,
3180 is_cut: false,
3181 #[cfg(feature = "ast-comments")]
3182 comments_after_cut: None,
3183 #[cfg(feature = "ast-comments")]
3184 comments_after_arrowmap: memberkey_comments,
3185 #[cfg(feature = "ast-span")]
3186 span: (
3187 begin_memberkey_range,
3188 self.lexer_position.range.0,
3189 begin_memberkey_line,
3190 ),
3191 })
3192 } else {
3193 Some(MemberKey::NonMemberKey {
3194 non_member_key: NonMemberKey::Type(Type {
3195 type_choices: t.type_choices,
3196 #[cfg(feature = "ast-span")]
3197 span: (
3198 begin_memberkey_range,
3199 self.parser_position.range.1,
3200 begin_memberkey_line,
3201 ),
3202 }),
3203 #[cfg(feature = "ast-comments")]
3204 comments_before_type_or_group,
3205 #[cfg(feature = "ast-comments")]
3206 comments_after_type_or_group,
3207 })
3208 };
3209
3210 Ok(t1)
3211 }
3212 _ => {
3213 let t1 = self.parse_type1(None)?;
3214
3215 #[cfg(feature = "ast-comments")]
3216 let comments_before_cut = self.collect_comments()?;
3217 #[cfg(not(feature = "ast-comments"))]
3218 self.advance_newline()?;
3219
3220 if let Token::CUT = &self.cur_token {
3221 self.next_token()?;
3222
3223 #[cfg(feature = "ast-comments")]
3224 let comments_after_cut = self.collect_comments()?;
3225 #[cfg(not(feature = "ast-comments"))]
3226 self.advance_newline()?;
3227
3228 if !self.cur_token_is(Token::ARROWMAP) {
3229 self.errors.push(Error::PARSER {
3230 #[cfg(feature = "ast-span")]
3231 position: self.lexer_position,
3232 msg: InvalidMemberKeyArrowMapSyntax.into(),
3233 });
3234 return Err(Error::INCREMENTAL);
3235 }
3236
3237 #[cfg(feature = "ast-span")]
3238 let end_memberkey_range = self.lexer_position.range.1;
3239
3240 self.next_token()?;
3241
3242 #[cfg(feature = "ast-comments")]
3243 let memberkey_comments = self.collect_comments()?;
3244 #[cfg(not(feature = "ast-comments"))]
3245 self.advance_newline()?;
3246
3247 return Ok(Some(MemberKey::Type1 {
3248 t1: Box::from(t1),
3249 #[cfg(feature = "ast-comments")]
3250 comments_before_cut,
3251 is_cut: true,
3252 #[cfg(feature = "ast-comments")]
3253 comments_after_cut,
3254 #[cfg(feature = "ast-comments")]
3255 comments_after_arrowmap: memberkey_comments,
3256 #[cfg(feature = "ast-span")]
3257 span: (
3258 begin_memberkey_range,
3259 end_memberkey_range,
3260 begin_memberkey_line,
3261 ),
3262 }));
3263 }
3264
3265 let t1 = if let Token::ARROWMAP = &self.cur_token {
3266 self.next_token()?;
3267
3268 #[cfg(feature = "ast-span")]
3269 {
3270 self.parser_position.range.1 = self.lexer_position.range.1;
3271 }
3272
3273 #[cfg(feature = "ast-comments")]
3274 let memberkey_comments = self.collect_comments()?;
3275 #[cfg(not(feature = "ast-comments"))]
3276 self.advance_newline()?;
3277
3278 Some(MemberKey::Type1 {
3279 t1: Box::from(t1),
3280 #[cfg(feature = "ast-comments")]
3281 comments_before_cut,
3282 is_cut: false,
3283 #[cfg(feature = "ast-comments")]
3284 comments_after_cut: None,
3285 #[cfg(feature = "ast-comments")]
3286 comments_after_arrowmap: memberkey_comments,
3287 #[cfg(feature = "ast-span")]
3288 span: (
3289 begin_memberkey_range,
3290 self.parser_position.range.1,
3291 begin_memberkey_line,
3292 ),
3293 })
3294 } else {
3295 Some(MemberKey::NonMemberKey {
3296 non_member_key: NonMemberKey::Type(Type {
3297 type_choices: vec![TypeChoice {
3298 #[cfg(feature = "ast-comments")]
3299 comments_before_type: None,
3300 #[cfg(feature = "ast-comments")]
3301 comments_after_type: None,
3302 type1: t1,
3303 }],
3304 #[cfg(feature = "ast-span")]
3305 span: (
3306 begin_memberkey_range,
3307 self.parser_position.range.1,
3308 begin_memberkey_line,
3309 ),
3310 }),
3311 #[cfg(feature = "ast-comments")]
3312 comments_before_type_or_group: None,
3313 #[cfg(feature = "ast-comments")]
3314 comments_after_type_or_group: comments_before_cut,
3315 })
3316 };
3317
3318 Ok(t1)
3319 }
3320 }
3321 }
3322
3323 #[allow(missing_docs)]
3324 pub fn parse_occur(&mut self, is_optional: bool) -> Result<Option<Occurrence<'a>>> {
3325 #[cfg(feature = "ast-span")]
3326 let begin_occur_range = self.lexer_position.range.0;
3327 #[cfg(feature = "ast-span")]
3328 let begin_occur_line = self.lexer_position.line;
3329 #[cfg(feature = "ast-span")]
3330 {
3331 self.parser_position.line = self.lexer_position.line;
3332 }
3333
3334 match &self.cur_token {
3335 Token::OPTIONAL => {
3336 #[cfg(feature = "ast-span")]
3337 {
3338 self.parser_position.range = self.lexer_position.range;
3339 }
3340
3341 self.next_token()?;
3342
3343 #[cfg(feature = "ast-comments")]
3344 let comments = self.collect_comments()?;
3345 #[cfg(not(feature = "ast-comments"))]
3346 self.advance_newline()?;
3347
3348 Ok(Some(Occurrence {
3349 #[cfg(feature = "ast-span")]
3350 occur: Occur::Optional {
3351 span: (
3352 self.parser_position.range.0,
3353 self.parser_position.range.1,
3354 self.parser_position.line,
3355 ),
3356 },
3357 #[cfg(not(feature = "ast-span"))]
3358 occur: Occur::Optional {},
3359 #[cfg(feature = "ast-comments")]
3360 comments,
3361 _a: PhantomData,
3362 }))
3363 }
3364 Token::ONEORMORE => {
3365 #[cfg(feature = "ast-span")]
3366 {
3367 self.parser_position.range = self.lexer_position.range;
3368 }
3369
3370 self.next_token()?;
3371
3372 #[cfg(feature = "ast-comments")]
3373 let comments = self.collect_comments()?;
3374 #[cfg(not(feature = "ast-comments"))]
3375 self.advance_newline()?;
3376
3377 Ok(Some(Occurrence {
3378 #[cfg(feature = "ast-span")]
3379 occur: Occur::OneOrMore {
3380 span: (
3381 self.parser_position.range.0,
3382 self.parser_position.range.1,
3383 self.parser_position.line,
3384 ),
3385 },
3386 #[cfg(not(feature = "ast-span"))]
3387 occur: Occur::OneOrMore {},
3388 #[cfg(feature = "ast-comments")]
3389 comments,
3390 _a: PhantomData,
3391 }))
3392 }
3393 Token::ASTERISK => {
3394 let occur = if let Token::VALUE(token::Value::UINT(u)) = &self.peek_token {
3395 #[cfg(feature = "ast-span")]
3396 {
3397 self.parser_position.range.0 = self.lexer_position.range.0;
3398 self.parser_position.range.1 = self.peek_lexer_position.range.1;
3399 }
3400
3401 Occur::Exact {
3402 lower: None,
3403 upper: Some(*u),
3404 #[cfg(feature = "ast-span")]
3405 span: (
3406 self.parser_position.range.0,
3407 self.parser_position.range.1,
3408 self.parser_position.line,
3409 ),
3410 }
3411 } else {
3412 #[cfg(feature = "ast-span")]
3413 {
3414 self.parser_position.range = self.lexer_position.range;
3415 Occur::ZeroOrMore {
3416 span: (
3417 self.parser_position.range.0,
3418 self.parser_position.range.1,
3419 self.parser_position.line,
3420 ),
3421 }
3422 }
3423
3424 #[cfg(not(feature = "ast-span"))]
3425 Occur::ZeroOrMore {}
3426 };
3427
3428 self.next_token()?;
3429
3430 if let Token::VALUE(token::Value::UINT(_)) = &self.cur_token {
3431 self.next_token()?;
3432 }
3433
3434 #[cfg(feature = "ast-comments")]
3435 let comments = self.collect_comments()?;
3436 #[cfg(not(feature = "ast-comments"))]
3437 self.advance_newline()?;
3438
3439 Ok(Some(Occurrence {
3440 occur,
3441 #[cfg(feature = "ast-comments")]
3442 comments,
3443 _a: PhantomData,
3444 }))
3445 }
3446 Token::VALUE(_) => {
3447 let lower = if let Token::VALUE(token::Value::UINT(li)) = &self.cur_token {
3448 Some(*li)
3449 } else {
3450 None
3451 };
3452
3453 if !self.peek_token_is(&Token::ASTERISK) {
3454 if is_optional {
3455 return Ok(None);
3456 }
3457
3458 self.errors.push(Error::PARSER {
3459 #[cfg(feature = "ast-span")]
3460 position: self.lexer_position,
3461 msg: InvalidOccurrenceSyntax.into(),
3462 });
3463
3464 return Err(Error::INCREMENTAL);
3465 }
3466
3467 self.next_token()?;
3468
3469 #[cfg(feature = "ast-span")]
3470 {
3471 self.parser_position.range.1 = self.lexer_position.range.1;
3472 }
3473
3474 self.next_token()?;
3475
3476 let upper = if let Token::VALUE(token::Value::UINT(ui)) = &self.cur_token {
3477 let ui = *ui;
3478
3479 #[cfg(feature = "ast-span")]
3480 {
3481 self.parser_position.range.1 = self.lexer_position.range.1;
3482 }
3483
3484 self.next_token()?;
3485
3486 Some(ui)
3487 } else {
3488 None
3489 };
3490
3491 #[cfg(feature = "ast-comments")]
3492 let comments = self.collect_comments()?;
3493 #[cfg(not(feature = "ast-comments"))]
3494 self.advance_newline()?;
3495
3496 Ok(Some(Occurrence {
3497 occur: Occur::Exact {
3498 lower,
3499 upper,
3500 #[cfg(feature = "ast-span")]
3501 span: (
3502 begin_occur_range,
3503 self.parser_position.range.1,
3504 begin_occur_line,
3505 ),
3506 },
3507 #[cfg(feature = "ast-comments")]
3508 comments,
3509 _a: PhantomData,
3510 }))
3511 }
3512 _ => Ok(None),
3513 }
3514 }
3515
3516 fn cur_token_is(&self, t: Token) -> bool {
3517 mem::discriminant(&self.cur_token) == mem::discriminant(&t)
3518 }
3519
3520 fn peek_token_is(&self, t: &Token) -> bool {
3521 mem::discriminant(&self.peek_token) == mem::discriminant(t)
3522 }
3523
3524 fn expect_peek(&mut self, t: &Token) -> Result<bool> {
3525 if self.peek_token_is(t) {
3526 return self.next_token().map(|_| true);
3527 }
3528
3529 Ok(false)
3530 }
3531
3532 fn identifier_from_ident_token(
3534 &self,
3535 ident: &'a str,
3536 socket: Option<token::SocketPlug>,
3537 ) -> Identifier<'a> {
3538 Identifier {
3539 ident,
3540 socket,
3541 #[cfg(feature = "ast-span")]
3542 span: (
3543 self.lexer_position.range.0,
3544 self.lexer_position.range.1,
3545 self.lexer_position.line,
3546 ),
3547 }
3548 }
3549}
3550
3551#[cfg(not(target_arch = "wasm32"))]
3566#[cfg(feature = "std")]
3567pub fn cddl_from_str(input: &str, print_stderr: bool) -> std::result::Result<CDDL<'_>, String> {
3568 match Parser::new(input, Box::new(lexer::lexer_from_str(input).iter())).map_err(|e| e.to_string())
3569 {
3570 Ok(mut p) => match p.parse_cddl() {
3571 Ok(c) => Ok(c),
3572 Err(Error::INCREMENTAL) => {
3573 let e = if print_stderr {
3574 p.report_errors(true)
3575 } else {
3576 p.report_errors(false)
3577 };
3578
3579 if let Ok(Some(e)) = e {
3580 return Err(e);
3581 }
3582
3583 Err(Error::INCREMENTAL.to_string())
3584 }
3585 Err(e) => Err(e.to_string()),
3586 },
3587 Err(e) => Err(e),
3588 }
3589}
3590
3591#[cfg(feature = "std")]
3593#[cfg(not(target_arch = "wasm32"))]
3594pub fn root_type_name_from_cddl_str(input: &str) -> std::result::Result<String, String> {
3595 let cddl = cddl_from_str(input, false)?;
3596
3597 for r in cddl.rules.iter() {
3598 if let Rule::Type { rule, .. } = r {
3600 if rule.generic_params.is_none() {
3601 return Ok(rule.name.to_string());
3602 }
3603 }
3604 }
3605
3606 Err("cddl spec contains no root type".to_string())
3607}
3608
3609impl CDDL<'_> {
3610 #[cfg(not(target_arch = "wasm32"))]
3612 #[cfg(feature = "std")]
3613 pub fn from_slice(input: &[u8]) -> std::result::Result<CDDL<'_>, String> {
3614 let str_input = std::str::from_utf8(input).map_err(|e| e.to_string())?;
3615
3616 match Parser::new(str_input, Box::new(lexer::Lexer::from_slice(input).iter()))
3617 .map_err(|e| e.to_string())
3618 {
3619 Ok(mut p) => match p.parse_cddl() {
3620 Ok(c) => Ok(c),
3621 Err(Error::INCREMENTAL) => {
3622 if let Ok(Some(e)) = p.report_errors(false) {
3623 return Err(e);
3624 }
3625
3626 Err(Error::INCREMENTAL.to_string())
3627 }
3628 Err(e) => Err(e.to_string()),
3629 },
3630 Err(e) => Err(e),
3631 }
3632 }
3633
3634 #[cfg(not(target_arch = "wasm32"))]
3636 #[cfg(not(feature = "std"))]
3637 pub fn from_slice(input: &[u8]) -> std::result::Result<CDDL<'_>, String> {
3638 let str_input = std::str::from_utf8(input).map_err(|e| e.to_string())?;
3639
3640 match Parser::new(str_input, Box::new(lexer::Lexer::from_slice(input).iter()))
3641 .map_err(|e| e.to_string())
3642 {
3643 Ok(mut p) => match p.parse_cddl() {
3644 Ok(c) => Ok(c),
3645 Err(Error::INCREMENTAL) => {
3646 if let Some(e) = p.report_errors() {
3647 return Err(e);
3648 }
3649
3650 Err(Error::INCREMENTAL.to_string())
3651 }
3652 Err(e) => Err(e.to_string()),
3653 },
3654 Err(e) => Err(e),
3655 }
3656 }
3657}
3658
3659#[cfg(not(target_arch = "wasm32"))]
3677#[cfg(not(feature = "std"))]
3678pub fn cddl_from_str(input: &str) -> std::result::Result<CDDL<'_>, String> {
3679 match Parser::new(input, Box::new(lexer::lexer_from_str(input).iter())).map_err(|e| e.to_string())
3680 {
3681 Ok(mut p) => match p.parse_cddl() {
3682 Ok(c) => Ok(c),
3683 Err(Error::INCREMENTAL) => {
3684 if let Some(e) = p.report_errors() {
3685 return Err(e);
3686 }
3687
3688 Err(Error::INCREMENTAL.to_string())
3689 }
3690 Err(e) => Err(e.to_string()),
3691 },
3692 Err(e) => Err(e),
3693 }
3694}
3695
3696#[cfg(target_arch = "wasm32")]
3715#[wasm_bindgen]
3716pub fn cddl_from_str(input: &str) -> result::Result<JsValue, JsValue> {
3717 #[derive(Serialize)]
3718 struct ParserError {
3719 position: Position,
3720 msg: ErrorMsg,
3721 }
3722
3723 match Parser::new(input, Box::new(lexer::Lexer::new(input).iter())) {
3724 Ok(mut p) => match p.parse_cddl() {
3725 Ok(c) => serde_wasm_bindgen::to_value(&c).map_err(|e| JsValue::from(e.to_string())),
3726 Err(Error::INCREMENTAL) => {
3727 if !p.errors.is_empty() {
3728 return Err(
3729 serde_wasm_bindgen::to_value(
3730 &p.errors
3731 .iter()
3732 .filter_map(|e| {
3733 if let Error::PARSER { position, msg } = e {
3734 Some(ParserError {
3735 position: *position,
3736 msg: msg.clone(),
3737 })
3738 } else {
3739 None
3740 }
3741 })
3742 .collect::<Vec<ParserError>>(),
3743 )
3744 .map_err(|e| JsValue::from(e.to_string()))?,
3745 );
3746 }
3747
3748 Err(JsValue::from(Error::INCREMENTAL.to_string()))
3749 }
3750 Err(e) => Err(JsValue::from(e.to_string())),
3751 },
3752 Err(e) => Err(JsValue::from(e.to_string())),
3753 }
3754}
3755
3756#[cfg(feature = "lsp")]
3757#[cfg(target_arch = "wasm32")]
3758#[wasm_bindgen]
3759pub fn format_cddl_from_str(input: &str) -> result::Result<String, JsValue> {
3761 #[derive(Serialize)]
3762 struct ParserError {
3763 position: Position,
3764 msg: ErrorMsg,
3765 }
3766
3767 match Parser::new(input, Box::new(lexer::Lexer::new(input).iter())) {
3768 Ok(mut p) => match p.parse_cddl() {
3769 Ok(c) => Ok(c.to_string()),
3770 Err(Error::INCREMENTAL) => {
3771 if !p.errors.is_empty() {
3772 return Err(
3773 serde_wasm_bindgen::to_value(
3774 &p.errors
3775 .iter()
3776 .filter_map(|e| {
3777 if let Error::PARSER { position, msg } = e {
3778 Some(ParserError {
3779 position: *position,
3780 msg: msg.clone(),
3781 })
3782 } else {
3783 None
3784 }
3785 })
3786 .collect::<Vec<ParserError>>(),
3787 )
3788 .map_err(|e| JsValue::from(e.to_string()))?,
3789 );
3790 }
3791
3792 Err(JsValue::from(Error::INCREMENTAL.to_string()))
3793 }
3794 Err(e) => Err(JsValue::from(e.to_string())),
3795 },
3796 Err(e) => Err(JsValue::from(e.to_string())),
3797 }
3798}
3799
3800#[cfg(test)]
3801mod tests {
3802 use super::*;
3803 use crate::lexer;
3804
3805 #[test]
3806 fn test_multiple_rules_with_reference_to_parenthesized_type() {
3807 let input = r#"basic = (d: #6.23(uint), e: bytes)
3808 outer = [a: uint, b: basic, c: "some text"]"#;
3809
3810 let mut parser = Parser::new(input, Box::new(lexer::lexer_from_str(input).iter())).unwrap();
3812 let result = parser.parse_cddl();
3813
3814 assert!(result.is_ok(), "Parser errors: {:?}", parser.errors);
3816
3817 let cddl = result.unwrap();
3819 assert_eq!(cddl.rules.len(), 2);
3820
3821 let rule_names: Vec<_> = cddl.rules.iter().map(|r| r.name()).collect();
3823 assert!(rule_names.contains(&"basic".to_string()));
3824 assert!(rule_names.contains(&"outer".to_string()));
3825 }
3826}