1use std::{borrow::Cow, fmt::Display, num::NonZeroU32, sync::LazyLock};
2
3use chumsky::{
4 IterParser, Parser,
5 error::Rich,
6 extra,
7 input::{Input, MappedInput},
8 inspector::Inspector,
9 prelude::{choice, just, recursive},
10 select,
11};
12use device_driver_common::{
13 interner::{Istr, StrExt},
14 span::{Span, SpanExt, Spanned},
15 specifiers::{Access, AddressMode, BaseType, ByteOrder, Integer},
16};
17use device_driver_diagnostics::{Diagnostics, errors::ParsingError};
18use device_driver_lexer::{
19 Token, TokenModifier, TokenType,
20 semantic_token_object::{SemanticToken, SemanticTokenObject},
21};
22
23use crate::parse_num::{ParseIntRadix, ParseIntRadixError, ParseIntRadixErrorKind, parse_num};
24
25#[cfg(feature = "gen-docs")]
26pub mod gen_docs;
27mod parse_num;
28
29#[derive(Default)]
30pub struct AstArena {
31 nodes: Vec<Node>,
32}
33
34impl AstArena {
35 pub fn alloc_node(&mut self, node: Node) -> NodeId {
36 let id = NodeId(self.nodes.len());
37 self.nodes.push(node);
38 id
39 }
40}
41
42impl<'src, I: Input<'src>> Inspector<'src, I> for AstArena {
43 type Checkpoint = AstArenaCheckpoint;
44
45 fn on_token(&mut self, _token: &I::Token) {}
46
47 fn on_save<'parse>(
48 &self,
49 _cursor: &chumsky::input::Cursor<'src, 'parse, I>,
50 ) -> Self::Checkpoint {
51 AstArenaCheckpoint {
52 node_count: self.nodes.len(),
53 }
54 }
55
56 fn on_rewind<'parse>(
57 &mut self,
58 marker: &chumsky::input::Checkpoint<'src, 'parse, I, Self::Checkpoint>,
59 ) {
60 self.nodes.truncate(marker.inspector().node_count);
62 }
63}
64
65#[derive(Debug, Clone, Copy)]
66pub struct AstArenaCheckpoint {
67 node_count: usize,
68}
69
70pub fn parse(tokens: &[Spanned<Token>], diagnostics: &mut Diagnostics) -> Ast {
71 let mut state = AstArena { nodes: Vec::new() };
72
73 let (ast, parse_errs) = node()
74 .map_with(|ast, e| (ast, e.span()))
75 .parse_with_state(
76 tokens.map(
77 tokens
78 .last()
79 .map(|t| Span::from(t.span.end..t.span.end))
80 .unwrap_or_default(),
81 |token| (&token.value, &token.span),
82 ),
83 &mut state,
84 )
85 .into_output_errors();
86
87 for error in parse_errs {
88 diagnostics.add(ParsingError {
89 reason: error.to_string(),
90 span: *error.span(),
91 });
92 }
93
94 Ast::new(
95 ast.map(|(ast, _)| ast),
96 state,
97 ast.as_ref().map(|(_, span)| *span).unwrap_or_default(),
98 )
99}
100
101#[derive(Debug)]
103pub struct Ast {
104 pub root_node: Option<NodeId>,
105 nodes: Vec<Node>,
106 pub span: Span,
107}
108
109impl Ast {
110 pub fn new(root_node: Option<NodeId>, arena: AstArena, span: Span) -> Self {
111 Self {
112 root_node,
113 nodes: arena.nodes,
114 span,
115 }
116 }
117
118 pub fn node(&self, id: NodeId) -> &Node {
119 &self.nodes[id.0]
120 }
121
122 pub fn node_mut(&mut self, id: NodeId) -> &mut Node {
123 &mut self.nodes[id.0]
124 }
125
126 pub fn nodes(&self) -> &[Node] {
127 &self.nodes
128 }
129
130 pub fn nodes_mut(&mut self) -> &mut [Node] {
131 &mut self.nodes
132 }
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq)]
136pub struct NodeId(usize);
137
138#[derive(Debug, Clone)]
139pub struct Node {
140 pub doc_comments: Vec<Spanned<Istr>>,
141 pub node_type: Ident,
142 pub name: Ident,
143 pub repeat: Option<Spanned<Repeat>>,
144 pub type_specifier: Option<Spanned<TypeSpecifier>>,
145 pub short_properties: Vec<Spanned<Expression>>,
146 pub properties: Vec<Spanned<Property>>,
147 pub sub_nodes: Vec<NodeId>,
148 pub body_span: Option<Span>,
149 pub span: Span,
152}
153
154impl Node {
155 pub fn non_docs_span(&self) -> Span {
157 self.span.start_from(self.node_type.span)
158 }
159
160 pub fn to_string_formatted(&self, ast: &Ast) -> String {
161 let mut buf = String::new();
162 self.fmt_formatted(&mut buf, ast, 0).unwrap();
163 buf
164 }
165
166 pub fn fmt_formatted(
167 &self,
168 f: &mut impl std::fmt::Write,
169 ast: &Ast,
170 indentation_level: usize,
171 ) -> std::fmt::Result {
172 let indentation = format!("{:width$}", "", width = indentation_level * 4);
173
174 for doc_comment in &self.doc_comments {
175 writeln!(
176 f,
177 "{indentation}///{}{doc_comment}",
178 if doc_comment.starts_with(" ") {
179 ""
180 } else {
181 " "
182 }
183 )?;
184 }
185 write!(f, "{indentation}{} {}", self.node_type.val, self.name.val)?;
186
187 if let Some(repeat) = self.repeat {
188 write!(f, "[{} stride {}]", repeat.source, repeat.stride)?;
189 }
190
191 for expression in self.short_properties.iter() {
192 write!(f, " {}", expression.print_formatted(ast))?;
193 }
194
195 if let Some(type_specifier) = self.type_specifier.as_ref() {
196 write!(f, " -> {}", type_specifier.base_type)?;
197
198 if let Some(conversion) = type_specifier.conversion.as_ref() {
199 write!(f, " as")?;
200 if type_specifier.use_try {
201 write!(f, " try")?;
202 }
203
204 match conversion {
205 TypeConversion::Reference(ident) => write!(f, " {}", ident.val)?,
206 TypeConversion::Subnode(node) => {
207 let node = ast.node(*node);
208 if node.doc_comments.is_empty() {
209 for (i, line) in node.to_string_formatted(ast).lines().enumerate() {
210 if i == 0 {
211 write!(f, " {line}")?;
212 } else {
213 write!(f, "\n{indentation}{line}")?;
214 }
215 }
216 } else {
217 node.fmt_formatted(f, ast, indentation_level + 1)?;
218 }
219 }
220 }
221 }
222 }
223
224 if !self.sub_nodes.is_empty() || !self.properties.is_empty() {
225 writeln!(f, " {{")?;
226
227 for property in self.properties.iter() {
228 for doc_comment in property.doc_comments.iter() {
229 writeln!(
230 f,
231 "{indentation} ///{}{}",
232 if doc_comment.starts_with(" ") {
233 ""
234 } else {
235 " "
236 },
237 doc_comment
238 )?;
239 }
240
241 write!(f, "{indentation} {}:", property.name.val)?;
242
243 let expression = property.expression.print_formatted(ast);
244
245 if expression.starts_with("///") {
246 for line in expression.lines() {
247 write!(f, "\n{indentation} {line}")?;
248 }
249 } else {
250 for (i, line) in expression.lines().enumerate() {
251 if i == 0 {
252 write!(f, " {line}")?;
253 } else {
254 write!(f, "\n{indentation} {line}")?;
255 }
256 }
257 }
258
259 writeln!(f, ",")?;
260 }
261
262 if !self.properties.is_empty() && !self.sub_nodes.is_empty() {
263 writeln!(f, "{indentation}",)?;
264 }
265
266 for node in self.sub_nodes.iter() {
267 let node = ast.node(*node);
268 node.fmt_formatted(f, ast, indentation_level + 1)?;
269 writeln!(f, ",")?;
270 }
271
272 write!(f, "{indentation}}}")?;
273 }
274
275 Ok(())
276 }
277}
278
279impl SemanticTokenObject for Node {
280 type Context = Ast;
281
282 fn to_tokens_in(&self, ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
283 tokens.extend(self.doc_comments.iter().map(|doc_comment| {
284 Token::DocCommentLine(doc_comment.as_str())
285 .with_semantics(TokenType::Comment, &[TokenModifier::Documentation])
286 }));
287 tokens.push(
288 Token::Ident(self.node_type.val.as_str()).with_semantics(TokenType::Keyword, &[]),
289 );
290 tokens.push(Token::Ident(self.name.val.as_str()).with_semantics(
291 TokenType::Type,
292 &[TokenModifier::Declaration, TokenModifier::Definition],
293 ));
294
295 if let Some(repeat) = self.repeat.as_ref() {
296 repeat.to_tokens_in(&(), tokens);
297 }
298
299 for short_property in self.short_properties.iter() {
300 short_property.to_tokens_in(ctx, tokens);
301 }
302
303 if let Some(type_specifier) = self.type_specifier.as_ref() {
304 type_specifier.to_tokens_in(ctx, tokens);
305 }
306
307 if self.properties.len() + self.sub_nodes.len() > 0 {
308 tokens.push(Token::CurlyOpen.without_semantics());
309
310 for property in self.properties.iter() {
311 property.to_tokens_in(ctx, tokens);
312 tokens.push(Token::Comma.without_semantics());
313 }
314
315 for sub_node in self.sub_nodes.iter() {
316 ctx.node(*sub_node).to_tokens_in(ctx, tokens);
317 tokens.push(Token::Comma.without_semantics());
318 }
319
320 tokens.push(Token::CurlyClose.without_semantics());
321 }
322 }
323}
324
325#[derive(Debug, Clone)]
326pub struct TypeSpecifier {
327 pub base_type: Spanned<BaseType>,
328 pub use_try: bool,
329 pub conversion: Option<TypeConversion>,
330}
331
332impl SemanticTokenObject for TypeSpecifier {
333 type Context = Ast;
334
335 fn to_tokens_in(&self, ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
336 tokens.push(Token::Arrow.without_semantics());
337 self.base_type.to_tokens_in(&(), tokens);
338 if let Some(conversion) = self.conversion.as_ref() {
339 tokens.push(Token::As.with_semantics(TokenType::Keyword, &[TokenModifier::Expression]));
340 if self.use_try {
341 tokens.push(
342 Token::Try.with_semantics(TokenType::Keyword, &[TokenModifier::Expression]),
343 );
344 }
345 conversion.to_tokens_in(ctx, tokens);
346 }
347 }
348}
349
350#[derive(Debug, Clone)]
351pub enum TypeConversion {
352 Reference(Ident),
353 Subnode(NodeId),
354}
355
356impl TypeConversion {
357 pub fn as_subnode(&self) -> Option<NodeId> {
358 if let Self::Subnode(v) = self {
359 Some(*v)
360 } else {
361 None
362 }
363 }
364}
365
366impl SemanticTokenObject for TypeConversion {
367 type Context = Ast;
368
369 fn to_tokens_in(&self, ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
370 match self {
371 TypeConversion::Reference(ident) => {
372 tokens.push(Token::Ident(ident.val.as_str()).with_semantics(TokenType::Type, &[]))
373 }
374 TypeConversion::Subnode(node) => ctx.node(*node).to_tokens_in(ctx, tokens),
375 }
376 }
377}
378
379#[derive(Debug, Clone)]
380pub struct Property {
381 pub doc_comments: Vec<Spanned<Istr>>,
382 pub name: Ident,
383 pub expression: Spanned<Expression>,
384}
385
386impl SemanticTokenObject for Property {
387 type Context = Ast;
388
389 fn to_tokens_in(&self, ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
390 tokens.extend(self.doc_comments.iter().map(|istr| {
391 Token::DocCommentLine(istr.as_str())
392 .with_semantics(TokenType::Comment, &[TokenModifier::Documentation])
393 }));
394 tokens.push(Token::Ident(self.name.val.as_str()).with_semantics(TokenType::Property, &[]));
395
396 tokens.push(Token::Colon.without_semantics());
397 self.expression.to_tokens_in(ctx, tokens);
398 }
399}
400
401#[derive(Debug, Clone)]
402pub enum Expression {
403 AddressRange { end: i128, start: i128 },
404 ByteArray(Vec<u8>),
405 BaseType(BaseType),
406 Integer(Integer),
407 Allow,
408 Number(i128),
409 DefaultNumber(Option<i128>),
410 CatchAllNumber(Option<i128>),
411 String(Istr),
412 Access(Access),
413 ByteOrder(ByteOrder),
414 TypeReference(Ident),
415 SubNode(NodeId),
416 Auto,
417 AddressMode(AddressMode),
418}
419
420impl Expression {
421 pub fn as_range(&self) -> Option<(i128, i128)> {
422 if let Self::AddressRange { end, start } = self {
423 Some((*end, *start))
424 } else {
425 None
426 }
427 }
428
429 pub fn as_byte_order(&self) -> Option<ByteOrder> {
430 if let Self::ByteOrder(v) = self {
431 Some(*v)
432 } else {
433 None
434 }
435 }
436
437 pub fn as_access(&self) -> Option<Access> {
438 if let Self::Access(v) = self {
439 Some(*v)
440 } else {
441 None
442 }
443 }
444
445 pub fn as_integer(&self) -> Option<Integer> {
446 if let Self::Integer(v) = self {
447 Some(*v)
448 } else {
449 None
450 }
451 }
452
453 pub fn as_unsigned_integer(&self) -> Option<Integer> {
454 if let Self::Integer(v) = self {
455 Some(*v)
456 } else {
457 None
458 }
459 }
460
461 pub fn as_number(&self) -> Option<i128> {
462 if let Self::Number(v) = self {
463 Some(*v)
464 } else {
465 None
466 }
467 }
468
469 pub fn as_string(&self) -> Option<Istr> {
470 if let Self::String(v) = self {
471 Some(*v)
472 } else {
473 None
474 }
475 }
476
477 pub fn as_address_mode(&self) -> Option<AddressMode> {
478 if let Self::AddressMode(v) = self {
479 Some(*v)
480 } else {
481 None
482 }
483 }
484
485 pub fn as_sub_node(&self) -> Option<NodeId> {
486 if let Self::SubNode(v) = self {
487 Some(*v)
488 } else {
489 None
490 }
491 }
492
493 pub fn print_formatted(&self, ast: &Ast) -> Cow<'static, str> {
494 match self {
495 Expression::AddressRange { end, start } => format!("{end}:{start}").into(),
496 Expression::ByteArray(items) => format!("{items:?}").into(),
497 Expression::BaseType(base_type) => base_type.to_string().into(),
498 Expression::Integer(integer) => integer.to_string().into(),
499 Expression::Allow => "allow".into(),
500 Expression::Number(num) => num.to_string().into(),
501 Expression::DefaultNumber(Some(num)) => format!("default {num}").into(),
502 Expression::DefaultNumber(None) => "default _".into(),
503 Expression::CatchAllNumber(Some(num)) => format!("catch-all {num}").into(),
504 Expression::CatchAllNumber(None) => "catch-all _".into(),
505 Expression::String(val) => format!("\"{val}\"").into(),
506 Expression::Access(val) => val.to_string().into(),
507 Expression::ByteOrder(val) => val.to_string().into(),
508 Expression::TypeReference(ident) => ident.val.to_string().into(),
509 Expression::SubNode(val) => ast.node(*val).to_string_formatted(ast).into(),
510 Expression::Auto => "_".into(),
511 Expression::AddressMode(val) => val.to_string().into(),
512 }
513 }
514}
515
516impl Display for Expression {
517 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
518 match self {
519 Expression::AddressRange { .. } => write!(f, "range"),
520 Expression::ByteArray(_) => write!(f, "[bytes]"),
521 Expression::BaseType(_) => write!(f, "base type"),
522 Expression::Integer(_) => write!(f, "integer type"),
523 Expression::Allow => write!(f, "allow"),
524 Expression::Number(_) => write!(f, "number"),
525 Expression::DefaultNumber(None) => write!(f, "default auto"),
526 Expression::CatchAllNumber(None) => write!(f, "catch-all auto"),
527 Expression::DefaultNumber(Some(_)) => write!(f, "default number"),
528 Expression::CatchAllNumber(Some(_)) => write!(f, "catch-all number"),
529 Expression::String(_) => write!(f, "string"),
530 Expression::Access(_) => write!(f, "access specifier"),
531 Expression::ByteOrder(_) => write!(f, "byte order"),
532 Expression::TypeReference(_) => write!(f, "type reference"),
533 Expression::SubNode(_) => write!(f, "sub node"),
534 Expression::Auto => write!(f, "auto"),
535 Expression::AddressMode(_) => write!(f, "address mode"),
536 }
537 }
538}
539
540impl SemanticTokenObject for Expression {
541 type Context = Ast;
542
543 fn to_tokens_in(&self, ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
544 match self {
545 Expression::AddressRange { end, start } => {
546 tokens.push(
547 Token::Num(end.to_string().intern().as_str())
548 .with_semantics(TokenType::Number, &[]),
549 );
550 tokens.push(Token::Colon.without_semantics());
551 tokens.push(
552 Token::Num(start.to_string().intern().as_str())
553 .with_semantics(TokenType::Number, &[]),
554 );
555 }
556 Expression::ByteArray(bytes) => {
557 tokens.push(Token::BracketOpen.without_semantics());
558 for (i, byte) in bytes.iter().enumerate() {
559 if i != 0 {
560 tokens.push(Token::Comma.without_semantics());
561 }
562 tokens.push(
563 Token::Num(byte.to_string().intern().as_str())
564 .with_semantics(TokenType::Number, &[]),
565 );
566 }
567 tokens.push(Token::BracketClose.without_semantics());
568 }
569 Expression::BaseType(base_type) => base_type.to_tokens_in(&(), tokens),
570 Expression::Integer(integer) => integer.to_tokens_in(&(), tokens),
571 Expression::Allow => tokens.push(Token::Allow.with_semantics(TokenType::Keyword, &[])),
572 Expression::Number(num) => tokens.push(
573 Token::Num(num.to_string().intern().as_str())
574 .with_semantics(TokenType::Number, &[]),
575 ),
576 Expression::DefaultNumber(num) => {
577 tokens.push(Token::Default.with_semantics(TokenType::Keyword, &[]));
578 match num {
579 Some(num) => {
580 tokens.push(
581 Token::Num(num.to_string().intern().as_str())
582 .with_semantics(TokenType::Number, &[]),
583 );
584 }
585 None => {
586 tokens.push(Token::Underscore.with_semantics(TokenType::Operator, &[]));
587 }
588 }
589 }
590 Expression::CatchAllNumber(num) => {
591 tokens.push(Token::CatchAll.with_semantics(TokenType::Keyword, &[]));
592 match num {
593 Some(num) => {
594 tokens.push(
595 Token::Num(num.to_string().intern().as_str())
596 .with_semantics(TokenType::Number, &[]),
597 );
598 }
599 None => {
600 tokens.push(Token::Underscore.with_semantics(TokenType::Operator, &[]));
601 }
602 }
603 }
604 Expression::String(istr) => {
605 tokens.push(Token::String(istr.as_str()).with_semantics(TokenType::String, &[]));
606 }
607 Expression::Access(access) => access.to_tokens_in(&(), tokens),
608 Expression::ByteOrder(byte_order) => byte_order.to_tokens_in(&(), tokens),
609 Expression::TypeReference(ident) => {
610 tokens.push(Token::Ident(ident.val.as_str()).with_semantics(TokenType::Type, &[]))
611 }
612 Expression::SubNode(node) => ctx.node(*node).to_tokens_in(ctx, tokens),
613 Expression::Auto => {
614 tokens.push(Token::Underscore.with_semantics(TokenType::Operator, &[]));
615 }
616 Expression::AddressMode(address_mode) => address_mode.to_tokens_in(&(), tokens),
617 }
618 }
619}
620
621#[derive(Debug, Clone, Copy, Default)]
622pub struct Repeat {
623 pub source: Spanned<RepeatSource>,
624 pub stride: Spanned<i32>,
625}
626
627impl SemanticTokenObject for Repeat {
628 type Context = ();
629
630 fn to_tokens_in(&self, ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
631 tokens.push(Token::BracketOpen.without_semantics());
632 self.source.to_tokens_in(ctx, tokens);
633 tokens.push(Token::Stride.with_semantics(TokenType::Keyword, &[TokenModifier::Expression]));
634 tokens.push(
635 Token::Num(self.stride.to_string().intern().as_str())
636 .with_semantics(TokenType::Number, &[]),
637 );
638 tokens.push(Token::BracketClose.without_semantics());
639 }
640}
641
642#[derive(Debug, Clone, Copy)]
643pub enum RepeatSource {
644 Count(NonZeroU32),
645 Enum(Ident),
646}
647
648impl Default for RepeatSource {
649 fn default() -> Self {
650 Self::Count(1.try_into().unwrap())
651 }
652}
653
654impl Display for RepeatSource {
655 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
656 match self {
657 RepeatSource::Count(non_zero) => write!(f, "{non_zero}"),
658 RepeatSource::Enum(ident) => write!(f, "{}", ident.val),
659 }
660 }
661}
662
663impl SemanticTokenObject for RepeatSource {
664 type Context = ();
665
666 fn to_tokens_in(&self, _ctx: &Self::Context, tokens: &mut Vec<SemanticToken<'_>>) {
667 match self {
668 RepeatSource::Count(non_zero) => tokens.push(
669 Token::Num(non_zero.get().to_string().intern().as_str())
670 .with_semantics(TokenType::Number, &[]),
671 ),
672 RepeatSource::Enum(ident) => {
673 tokens.push(Token::Ident(ident.val.as_str()).with_semantics(TokenType::Type, &[]))
674 }
675 }
676 }
677}
678
679#[derive(Debug, Clone, Copy)]
680pub struct Ident {
681 pub val: Istr,
682 pub span: Span,
683}
684
685impl Ident {
686 pub const fn new(val: Istr, span: Span) -> Self {
687 Self { val, span }
688 }
689
690 pub const fn new_no_span(val: Istr) -> Self {
691 Self {
692 val,
693 span: Span::empty(),
694 }
695 }
696
697 pub fn new_auto(span: Span) -> Self {
698 Self {
699 val: "_".intern(),
700 span,
701 }
702 }
703
704 pub fn is_auto(&self) -> bool {
706 static UNDERSCORE: LazyLock<Istr> = LazyLock::new(|| "_".intern());
707 self.val == *UNDERSCORE
708 }
709}
710
711fn try_num<'tokens, 'src: 'tokens, I: ParseIntRadix>(
712 num_str: &'src str,
713 span: Span,
714) -> Result<I, RichErr<'tokens, 'src>> {
715 match parse_num::<I>(num_str) {
716 Ok(num) => Ok(num),
717 Err(ParseIntRadixError {
718 source,
719 kind,
720 target_bits,
721 target_signed,
722 }) => match kind {
723 ParseIntRadixErrorKind::Overflow => Err(Rich::custom(
724 span,
725 format!(
726 "number `{source}` is parsed as a {}{target_bits}, but overflows.",
727 if target_signed { 'i' } else { 'u' }
728 ),
729 )),
730 ParseIntRadixErrorKind::Underflow => Err(Rich::custom(
731 span,
732 format!(
733 "number `{source}` is parsed as a {}{target_bits}, but underflows.",
734 if target_signed { 'i' } else { 'u' }
735 ),
736 )),
737 ParseIntRadixErrorKind::Empty => Err(Rich::custom(
738 span,
739 format!("could not parse `{source}` as a number because it contains no numbers"),
740 )),
741 ParseIntRadixErrorKind::Zero => {
742 Err(Rich::custom(span, "number can't be 0 in this position"))
743 }
744 },
745 }
746}
747
748pub type InputType<'tokens, 'src> =
749 MappedInput<'tokens, Token<'src>, Span, &'tokens [Spanned<Token<'src>>]>;
750pub type RichErr<'tokens, 'src> = Rich<'tokens, Token<'src>, Span>;
751pub type RichExtra<'tokens, 'src> = extra::Full<RichErr<'tokens, 'src>, AstArena, ()>;
752
753pub fn ident<'tokens, 'src: 'tokens>(
754 allow_auto: bool,
755) -> impl Parser<'tokens, InputType<'tokens, 'src>, Ident, RichExtra<'tokens, 'src>> + Clone {
756 select! {
757 Token::Ident(val) = e => Ident::new(val.intern(), e.span()),
758 Token::Underscore = e if allow_auto => Ident::new_auto(e.span()),
759 }
760 .labelled(format!(
761 "Ident{}",
762 if allow_auto { "|Underscore" } else { "" }
763 ))
764 .as_terminal()
765}
766
767pub fn doc_comment<'tokens, 'src: 'tokens>()
768-> impl Parser<'tokens, InputType<'tokens, 'src>, Spanned<Istr>, RichExtra<'tokens, 'src>> + Copy {
769 select! {
770 Token::DocCommentLine(val) => val
771 }
772 .map_with(|line, extra| line.intern().spanned(extra.span()))
773 .labelled("DocCommentLine")
774 .as_terminal()
775}
776
777pub fn num<'tokens, 'src: 'tokens, I: ParseIntRadix>()
778-> impl Parser<'tokens, InputType<'tokens, 'src>, I, RichExtra<'tokens, 'src>> + Clone {
779 select! {
780 Token::Num(num) => num
781 }
782 .try_map(try_num::<I>)
783 .labelled(format!(
784 "Num<{}>",
785 std::any::type_name::<I>().split("::").last().unwrap()
787 ))
788 .as_terminal()
789}
790
791pub fn range<'tokens, 'src: 'tokens>()
792-> impl Parser<'tokens, InputType<'tokens, 'src>, Expression, RichExtra<'tokens, 'src>> + Clone {
793 num::<i128>()
794 .then_ignore(just(Token::Colon))
795 .then(num::<i128>())
796 .map(|(end, start)| Expression::AddressRange { end, start })
797 .labelled("range")
798}
799
800pub fn base_type<'tokens, 'src: 'tokens>()
801-> impl Parser<'tokens, InputType<'tokens, 'src>, BaseType, RichExtra<'tokens, 'src>> + Copy {
802 select! { Token::BaseType(bt) => bt }
803 .labelled("BaseType")
804 .as_terminal()
805}
806
807pub fn integer<'tokens, 'src: 'tokens>()
808-> impl Parser<'tokens, InputType<'tokens, 'src>, Integer, RichExtra<'tokens, 'src>> + Copy {
809 select! { Token::Integer(i) => i }
810 .labelled("Integer")
811 .as_terminal()
812}
813
814pub fn byte_array<'tokens, 'src: 'tokens>()
815-> impl Parser<'tokens, InputType<'tokens, 'src>, Expression, RichExtra<'tokens, 'src>> + Clone {
816 num::<u8>()
817 .separated_by(just(Token::Comma))
818 .collect::<Vec<_>>()
819 .map(Expression::ByteArray)
820 .then_ignore(just(Token::Comma).or_not())
821 .delimited_by(just(Token::BracketOpen), just(Token::BracketClose))
822 .labelled("byte-array")
823}
824
825pub fn simple_expression<'tokens, 'src: 'tokens>()
827-> impl Parser<'tokens, InputType<'tokens, 'src>, Spanned<Expression>, RichExtra<'tokens, 'src>> + Clone
828{
829 choice((
830 range().labelled("range").as_non_terminal(),
831 base_type().map(Expression::BaseType),
832 integer().map(Expression::Integer),
833 num::<i128>().map(Expression::Number),
834 just(Token::Default)
835 .ignore_then(
836 num::<i128>()
837 .map(Some)
838 .or(just(Token::Underscore).map(|_| None)),
839 )
840 .map(Expression::DefaultNumber)
841 .labelled("default-number"),
842 just(Token::CatchAll)
843 .ignore_then(
844 num::<i128>()
845 .map(Some)
846 .or(just(Token::Underscore).map(|_| None)),
847 )
848 .map(Expression::CatchAllNumber)
849 .labelled("catch-all-number"),
850 byte_array().labelled("byte-array").as_non_terminal(),
851 just(Token::Allow).map(|_| Expression::Allow),
852 select! { Token::Access(val) => val }
853 .map(Expression::Access)
854 .labelled("Access")
855 .as_terminal(),
856 select! { Token::ByteOrder(val) => val }
857 .map(Expression::ByteOrder)
858 .labelled("ByteOrder")
859 .as_terminal(),
860 just(Token::Underscore).map(|_| Expression::Auto),
861 select! { Token::String(val) => val.intern() }
862 .map(Expression::String)
863 .labelled("String")
864 .as_terminal(),
865 select! { Token::AddressMode(val) => val }
866 .map(Expression::AddressMode)
867 .labelled("AddressMode")
868 .as_terminal(),
869 ))
870 .map_with(|expression, extra| expression.spanned(extra.span()))
871 .labelled("simple-expression")
872}
873
874pub fn repeat<'tokens, 'src: 'tokens>()
875-> impl Parser<'tokens, InputType<'tokens, 'src>, Spanned<Repeat>, RichExtra<'tokens, 'src>> + Clone
876{
877 choice((
878 num::<NonZeroU32>().map(RepeatSource::Count),
879 ident(false).map(RepeatSource::Enum),
880 ))
881 .map_with(|repeat_source, extra| repeat_source.with_span(extra.span()))
882 .then(
883 just(Token::Stride)
884 .ignore_then(num::<i32>().map_with(|num, extra| num.with_span(extra.span()))),
885 )
886 .delimited_by(just(Token::BracketOpen), just(Token::BracketClose))
887 .map_with(|(source, stride), extra| Repeat { source, stride }.spanned(extra.span()))
888 .labelled("repeat")
889}
890
891pub fn property<'tokens, 'src: 'tokens, 'node>(
892 node: impl Parser<'tokens, InputType<'tokens, 'src>, NodeId, RichExtra<'tokens, 'src>> + Clone,
893) -> impl Parser<'tokens, InputType<'tokens, 'src>, Spanned<Property>, RichExtra<'tokens, 'src>> + Clone
894{
895 doc_comment()
896 .repeated()
897 .collect()
898 .then(
899 ident(false)
900 .then(
901 just(Token::Colon).ignore_then(choice((
902 simple_expression()
903 .labelled("simple-expression")
904 .as_non_terminal(),
905 node.clone()
906 .map_with(|node, extra| Expression::SubNode(node).spanned(extra.span()))
907 .labelled("node")
908 .as_non_terminal(),
909 ident(false)
910 .map(Expression::TypeReference)
911 .map_with(|expression, extra| expression.spanned(extra.span())),
912 ))),
913 )
914 .map_with(|(name, expression), extra| {
915 Property {
916 doc_comments: Vec::new(),
917 name,
918 expression,
919 }
920 .spanned(extra.span())
921 }),
922 )
923 .map(|(docs, mut prop)| {
924 prop.doc_comments = docs;
925 prop
926 })
927 .labelled("property")
928}
929
930pub fn type_specifier<'tokens, 'src: 'tokens>(
931 node: impl Parser<'tokens, InputType<'tokens, 'src>, NodeId, RichExtra<'tokens, 'src>> + Clone,
932) -> impl Parser<'tokens, InputType<'tokens, 'src>, Spanned<TypeSpecifier>, RichExtra<'tokens, 'src>>
933+ Clone {
934 let type_conversion = just(Token::As).ignore_then(just(Token::Try).or_not()).then(
935 node.labelled("node")
936 .as_non_terminal()
937 .map(TypeConversion::Subnode)
938 .or(ident(false).map(TypeConversion::Reference)),
939 );
940 just(Token::Arrow)
941 .ignore_then(
942 choice((
943 base_type(),
944 integer().map(BaseType::FixedSize),
945 just(Token::Underscore).map(|_| BaseType::Unspecified),
946 ))
947 .map_with(|b, e| b.spanned(e.span())),
948 )
949 .then(type_conversion.or_not())
950 .map(|(base_type, conversion)| TypeSpecifier {
951 base_type,
952 use_try: conversion
953 .as_ref()
954 .map(|(try_token, _)| try_token.is_some())
955 .unwrap_or_default(),
956 conversion: conversion.map(|(_, conversion)| conversion),
957 })
958 .map_with(|ts, e| ts.spanned(e.span()))
959 .labelled("type-specifier")
960}
961
962pub fn node_body<'tokens, 'src: 'tokens>(
963 node: impl Parser<'tokens, InputType<'tokens, 'src>, NodeId, RichExtra<'tokens, 'src>> + Clone,
964) -> impl Parser<
965 'tokens,
966 InputType<'tokens, 'src>,
967 (Vec<Spanned<Property>>, Vec<NodeId>),
968 RichExtra<'tokens, 'src>,
969> + Clone {
970 let properties = property(node.clone())
971 .labelled("property")
972 .as_non_terminal()
973 .separated_by(just(Token::Comma))
974 .at_least(1)
975 .collect::<Vec<_>>();
976 let nodes = node
977 .labelled("node")
978 .as_non_terminal()
979 .separated_by(just(Token::Comma))
980 .at_least(1)
981 .collect::<Vec<_>>();
982
983 choice((
985 properties
987 .clone()
988 .then_ignore(just(Token::Comma))
989 .then(nodes.clone()),
990 properties
992 .clone()
993 .map(|properties| (properties, Vec::new())),
994 nodes.map(|nodes| (Vec::new(), nodes)),
996 ))
997 .then_ignore(just(Token::Comma).or_not())
998 .or_not()
999 .map(|body| body.unwrap_or_default())
1000 .delimited_by(just(Token::CurlyOpen), just(Token::CurlyClose))
1001 .labelled("node-body")
1002}
1003
1004pub fn node<'tokens, 'src: 'tokens>()
1005-> impl Parser<'tokens, InputType<'tokens, 'src>, NodeId, RichExtra<'tokens, 'src>> + Clone {
1006 recursive(|node| {
1007 let node = node.labelled("node").as_non_terminal();
1008
1009 doc_comment()
1010 .repeated()
1011 .collect()
1012 .then(ident(false).labelled("node-type"))
1013 .then(ident(true).labelled("node-name"))
1014 .then(repeat().labelled("repeat").as_non_terminal().or_not())
1015 .then(
1016 simple_expression()
1017 .labelled("simple-expression")
1018 .as_non_terminal()
1019 .repeated()
1020 .collect::<Vec<_>>(),
1021 )
1022 .then(
1023 type_specifier(node.clone())
1024 .labelled("type-specifier")
1025 .as_non_terminal()
1026 .or_not(),
1027 )
1028 .then(
1029 node_body(node.clone())
1030 .map_with(|body, extra| (body, extra.span()))
1031 .labelled("node-body")
1032 .as_non_terminal()
1033 .or_not(),
1034 )
1035 .map_with(
1036 |(
1037 (((((doc_comments, node_type), name), repeat), expressions), type_specifier),
1038 body,
1039 ),
1040 extra| {
1041 let ((properties, sub_nodes), body_span) = body.unwrap_or_default();
1042
1043 let span: Span = extra.span();
1044
1045 extra.state().alloc_node(Node {
1046 doc_comments,
1047 node_type,
1048 name,
1049 repeat,
1050 type_specifier,
1051 properties,
1052 short_properties: expressions,
1053 sub_nodes,
1054 body_span: if body_span.is_empty() {
1055 None
1056 } else {
1057 Some(body_span)
1058 },
1059 span,
1060 })
1061 },
1062 )
1063 .labelled("node")
1064 })
1065}