1pub mod error;
2mod expression;
3pub mod item_type;
4mod items;
5pub mod lexer;
6mod statements;
7
8use std::marker::PhantomData;
9
10use colored::*;
11use itertools::Itertools;
12use local_impl::local_impl;
13use logos::Lexer;
14use spade_diagnostics::diag_list::DiagList;
15use statements::{AssertParser, BindingParser, DeclParser, LabelParser, RegisterParser, SetParser};
16use tracing::{debug, event, Level};
17
18use spade_ast::{
19 ArgumentList, ArgumentPattern, Attribute, AttributeList, BitLiteral, Block, CallKind,
20 EnumVariant, Expression, IntLiteral, Item, ModuleBody, NamedArgument, NamedTurbofish,
21 ParameterList, Pattern, PipelineStageReference, Statement, TraitSpec, TurbofishInner,
22 TypeExpression, TypeParam, TypeSpec, Unit, UnitHead, UnitKind, WhereClause,
23};
24use spade_common::location_info::{lspan, AsLabel, FullSpan, HasCodespan, Loc, WithLocation};
25use spade_common::name::{Identifier, Path};
26use spade_common::num_ext::InfallibleToBigInt;
27use spade_diagnostics::{diag_bail, Diagnostic};
28use spade_macros::trace_parser;
29
30use crate::error::{
31 unexpected_token_message, CSErrorTransformations, CommaSeparatedResult, ExpectedArgumentList,
32 Result, SuggestBraceEnumVariant, TokenSeparatedError, UnexpectedToken,
33};
34use crate::item_type::UnitKindLocal;
35use crate::lexer::{LiteralKind, TokenKind};
36
37pub use logos;
38
39#[derive(Clone, Debug, PartialEq)]
41pub struct Token {
42 pub kind: TokenKind,
43 pub span: logos::Span,
44 pub file_id: usize,
45}
46
47impl Token {
48 pub fn new(kind: TokenKind, lexer: &Lexer<TokenKind>, file_id: usize) -> Self {
49 Self {
50 kind,
51 span: lexer.span(),
52 file_id,
53 }
54 }
55
56 pub fn loc(&self) -> Loc<()> {
57 Loc::new((), self.span.codespan(), self.file_id)
58 }
59}
60
61impl HasCodespan for Token {
62 fn codespan(&self) -> spade_codespan::Span {
63 self.span().codespan()
64 }
65}
66
67impl AsLabel for Token {
68 fn file_id(&self) -> usize {
69 self.file_id
70 }
71
72 fn span(&self) -> std::ops::Range<usize> {
73 self.span.clone()
74 }
75}
76
77impl From<Token> for FullSpan {
78 fn from(token: Token) -> FullSpan {
79 (token.codespan(), token.file_id)
80 }
81}
82
83#[derive(Clone)]
86pub struct Parser<'a> {
87 lex: Lexer<'a, TokenKind>,
88 peeked: Option<Token>,
89 last_token: Option<Token>,
91 pub parse_stack: Vec<ParseStackEntry>,
92 file_id: usize,
93 unit_context: Option<Loc<UnitKind>>,
94 pub diags: DiagList,
95 recovering_tokens: Vec<Vec<TokenKind>>,
96}
97
98impl<'a> Parser<'a> {
99 pub fn new(lex: Lexer<'a, TokenKind>, file_id: usize) -> Self {
100 Self {
101 lex,
102 peeked: None,
103 last_token: None,
104 parse_stack: vec![],
105 file_id,
106 unit_context: None,
107 diags: DiagList::new(),
108 recovering_tokens: vec![vec![TokenKind::Eof]],
109 }
110 }
111}
112
113#[macro_export]
116macro_rules! peek_for {
117 ($self:expr, $token:expr) => {
118 if let Some(t) = $self.peek_and_eat($token)? {
119 t
120 } else {
121 return Ok(None);
122 }
123 };
124}
125
126impl<'a> Parser<'a> {
128 #[trace_parser]
129 #[tracing::instrument(level = "trace", skip(self))]
130 pub fn identifier(&mut self) -> Result<Loc<Identifier>> {
131 let token = self.eat_cond(TokenKind::is_identifier, "Identifier")?;
132
133 if let TokenKind::Identifier(name) = token.kind {
134 Ok(Identifier(name).at(self.file_id, &token.span))
135 } else {
136 unreachable!("eat_cond should have checked this");
137 }
138 }
139
140 #[trace_parser]
141 pub fn path(&mut self) -> Result<Loc<Path>> {
142 let mut result = vec![];
143 loop {
144 result.push(self.identifier()?);
145
146 if self.peek_and_eat(&TokenKind::PathSeparator)?.is_none() {
147 break;
148 }
149 }
150 let start = result.first().unwrap().span;
153 let end = result.last().unwrap().span;
154 Ok(Path(result).between(self.file_id, &start, &end))
155 }
156
157 pub fn named_turbofish(&mut self) -> Result<Loc<NamedTurbofish>> {
158 let name = self.identifier()?;
160 if self.peek_and_eat(&TokenKind::Colon)?.is_some() {
161 let value = self.type_expression()?;
162
163 let span = name.span.merge(value.span);
164
165 Ok(NamedTurbofish::Full(name, value).at(self.file_id, &span))
166 } else {
167 Ok(NamedTurbofish::Short(name.clone()).at(self.file_id, &name))
168 }
169 }
170
171 #[trace_parser]
172 pub fn turbofish(&mut self) -> Result<Option<Loc<TurbofishInner>>> {
173 let start = peek_for!(self, &TokenKind::PathSeparator);
174
175 if self.peek_kind(&TokenKind::Lt)? {
176 let params = self.generic_spec_list()?.unwrap();
178
179 Ok(Some(params.map(|p| TurbofishInner::Positional(p))))
180 } else if self.peek_kind(&TokenKind::Dollar)? {
181 self.eat_unconditional()?;
182 let (params, loc) = self.surrounded(
183 &TokenKind::Lt,
184 |s| {
185 s.comma_separated(Self::named_turbofish, &TokenKind::Gt)
186 .extra_expected(vec!["identifier", "type spec"])
187 },
188 &TokenKind::Gt,
189 )?;
190
191 Ok(Some(TurbofishInner::Named(params).at_loc(&loc)))
192 } else {
193 let next = self.peek()?;
194 return Err(Diagnostic::error(next, "Expected $ or <")
195 .primary_label("Expected $ or <")
196 .secondary_label(
197 start,
198 ":: after an method is used to specify type parameters",
199 ));
200 }
201 }
202
203 #[trace_parser]
204 pub fn path_with_turbofish(
205 &mut self,
206 ) -> Result<Option<(Loc<Path>, Option<Loc<TurbofishInner>>)>> {
207 let mut result = vec![];
208 if !self.peek_cond(TokenKind::is_identifier, "Identifier")? {
209 return Ok(None);
210 }
211
212 loop {
213 result.push(self.identifier()?);
214
215 let path_start = result.first().unwrap().span;
218 let path_end = result.last().unwrap().span;
219
220 if self.peek_and_eat(&TokenKind::PathSeparator)?.is_none() {
221 break Ok(Some((
222 Path(result).between(self.file_id, &path_start, &path_end),
223 None,
224 )));
225 } else if self.peek_kind(&TokenKind::Lt)? {
226 let params = self.generic_spec_list()?.unwrap();
228
229 break Ok(Some((
230 Path(result).between(self.file_id, &path_start, &path_end),
231 Some(params.map(|p| TurbofishInner::Positional(p))),
232 )));
233 } else if self.peek_kind(&TokenKind::Dollar)? {
234 self.eat_unconditional()?;
235 let (params, loc) = self.surrounded(
236 &TokenKind::Lt,
237 |s| {
238 s.comma_separated(Self::named_turbofish, &TokenKind::Gt)
239 .extra_expected(vec!["identifier", "type spec"])
240 },
241 &TokenKind::Gt,
242 )?;
243
244 break Ok(Some((
245 Path(result).between(self.file_id, &path_start, &path_end),
246 Some(TurbofishInner::Named(params).at_loc(&loc)),
247 )));
248 }
249 }
250 }
251
252 #[trace_parser]
253 fn array_literal(&mut self) -> Result<Option<Loc<Expression>>> {
254 let start = peek_for!(self, &TokenKind::OpenBracket);
255
256 if let Some(end) = self.peek_and_eat(&TokenKind::CloseBracket)? {
258 return Ok(Some(Expression::ArrayLiteral(vec![]).between(
259 self.file_id,
260 &start,
261 &end,
262 )));
263 }
264
265 let first = self.expression()?;
267
268 let expr = if self.peek_and_eat(&TokenKind::Semi).unwrap().is_some() {
269 Expression::ArrayShorthandLiteral(Box::new(first), Box::new(self.expression()?))
271 } else {
272 let _ = self.peek_and_eat(&TokenKind::Comma)?;
274 let mut inner = self
276 .comma_separated(Self::expression, &TokenKind::CloseBracket)
277 .no_context()?;
278 inner.insert(0, first);
279 Expression::ArrayLiteral(inner)
280 };
281
282 let end = self.eat(&TokenKind::CloseBracket)?;
283
284 Ok(Some(expr.between(self.file_id, &start, &end)))
285 }
286
287 #[trace_parser]
288 fn tuple_literal(&mut self) -> Result<Option<Loc<Expression>>> {
289 let start = peek_for!(self, &TokenKind::OpenParen);
290 if self.peek_kind(&TokenKind::CloseParen)? {
291 return Ok(Some(Expression::TupleLiteral(vec![]).between(
292 self.file_id,
293 &start,
294 &self.eat_unconditional()?,
295 )));
296 }
297 if let Some(_) = self.peek_and_eat(&TokenKind::Comma)? {
298 let closer = self.eat(&TokenKind::CloseParen)?;
299 return Ok(Some(Expression::TupleLiteral(vec![]).between(
300 self.file_id,
301 &start,
302 &closer,
303 )));
304 }
305
306 let first = self.expression()?;
307 let first_sep = self.eat_unconditional()?;
308
309 match &first_sep.kind {
310 TokenKind::CloseParen => {
311 Ok(Some(first.inner.between(self.file_id, &start, &first_sep)))
312 }
313 TokenKind::Comma => {
314 let rest = self
315 .comma_separated(Self::expression, &TokenKind::CloseParen)
316 .no_context()?;
317
318 let end = self.eat(&TokenKind::CloseParen)?;
319
320 Ok(Some(
321 Expression::TupleLiteral(vec![first].into_iter().chain(rest).collect())
322 .between(self.file_id, &start, &end),
323 ))
324 }
325 _ => Err(UnexpectedToken {
326 got: first_sep,
327 expected: vec!["expression", ",", ")"],
328 }
329 .into()),
330 }
331 }
332
333 #[trace_parser]
334 #[tracing::instrument(skip(self))]
335 fn entity_instance(&mut self) -> Result<Option<Loc<Expression>>> {
336 let start = peek_for!(self, &TokenKind::Instance);
337 let start_loc = ().at(self.file_id, &start);
338
339 self.unit_context
341 .allows_inst(().at(self.file_id, &start.span()))?;
342
343 let pipeline_depth = if self.peek_kind(&TokenKind::OpenParen)? {
345 Some(self.surrounded(
346 &TokenKind::OpenParen,
347 |s| s.type_expression(),
348 &TokenKind::CloseParen,
349 )?)
350 } else {
351 None
352 };
353
354 let peeked = self.peek()?;
355 let (name, turbofish) = self.path_with_turbofish()?.ok_or_else(|| {
356 Diagnostic::from(UnexpectedToken {
357 got: peeked,
358 expected: vec!["identifier", "pipeline depth"],
359 })
360 })?;
361 let next_token = self.peek()?;
362
363 let args = self.argument_list()?.ok_or_else(|| {
364 ExpectedArgumentList {
365 next_token,
366 base_expr: ().between(self.file_id, &start, &name),
367 }
368 .with_suggestions()
369 })?;
370
371 if let Some((depth, end_paren)) = pipeline_depth {
372 Ok(Some(
373 Expression::Call {
374 kind: CallKind::Pipeline(
375 ().between(self.file_id, &start_loc, &end_paren),
376 depth,
377 ),
378 callee: name,
379 args: args.clone(),
380 turbofish,
381 }
382 .between(self.file_id, &start.span, &args),
383 ))
384 } else {
385 Ok(Some(
386 Expression::Call {
387 kind: CallKind::Entity(start_loc),
388 callee: name,
389 args: args.clone(),
390 turbofish,
391 }
392 .between(self.file_id, &start.span, &args),
393 ))
394 }
395 }
396
397 #[trace_parser]
399 #[tracing::instrument(skip(self))]
400 pub fn if_expression(&mut self, allow_stages: bool) -> Result<Option<Loc<Expression>>> {
401 let start = peek_for!(self, &TokenKind::If);
402
403 let cond = self.expression()?;
404
405 let on_true = if let Some(block) = self.block(allow_stages)? {
406 block.map(Box::new).map(Expression::Block)
407 } else {
408 let got = self.peek()?;
409 return Err(Diagnostic::error(
410 got.loc(),
411 format!("Unexpected `{}`, expected a block", got.kind.as_str()),
412 )
413 .primary_label("expected a block here"));
414 };
415
416 self.eat(&TokenKind::Else)?;
417 let on_false = if let Some(block) = self.block(allow_stages)? {
418 block.map(Box::new).map(Expression::Block)
419 } else if let Some(expr) = self.if_expression(allow_stages)? {
420 expr
421 } else {
422 let got = self.peek()?;
423 return Err(Diagnostic::error(
424 got.loc(),
425 format!(
426 "Unexpected `{}`, expected `if` or a block",
427 got.kind.as_str()
428 ),
429 )
430 .primary_label("expected a block here"));
431 };
432 let end_span = on_false.span;
433
434 Ok(Some(
435 Expression::If(Box::new(cond), Box::new(on_true), Box::new(on_false)).between(
436 self.file_id,
437 &start.span,
438 &end_span,
439 ),
440 ))
441 }
442
443 pub fn type_level_if(&mut self) -> Result<Option<Loc<Expression>>> {
445 let start = peek_for!(self, &TokenKind::Gen);
446
447 let Some(inner) = self.if_expression(true)? else {
448 return Err(
449 Diagnostic::error(self.peek()?, "gen must be followed by if")
450 .primary_label("Expected if")
451 .secondary_label(start, "Because of this gen"),
452 );
453 };
454 let end_span = inner.loc();
455 let Expression::If(cond, on_true, on_false) = inner.inner else {
456 diag_bail!(inner, "if_expression did not return an if")
457 };
458
459 let on_false = match &on_false.inner {
460 Expression::If(cond, on_true, on_false) => Box::new(
461 Expression::TypeLevelIf(cond.clone(), on_true.clone(), on_false.clone())
462 .at_loc(&on_false),
463 ),
464 _ => on_false,
465 };
466
467 Ok(Some(
468 Expression::TypeLevelIf(cond, on_true, on_false).between(
469 self.file_id,
470 &start.span,
471 &end_span,
472 ),
473 ))
474 }
475
476 #[trace_parser]
477 pub fn match_expression(&mut self) -> Result<Option<Loc<Expression>>> {
478 let start = peek_for!(self, &TokenKind::Match);
479
480 let expression = self.expression()?;
481
482 let (patterns, body_loc) = self.surrounded(
483 &TokenKind::OpenBrace,
484 |s| {
485 s.comma_separated(
486 |s| {
487 let pattern = s.pattern()?;
488 s.eat(&TokenKind::FatArrow)?;
489 let value = s.expression()?;
490
491 Ok((pattern, value))
492 },
493 &TokenKind::CloseBrace,
494 )
495 .no_context()
496 },
497 &TokenKind::CloseBrace,
498 )?;
499 let patterns = patterns.at_loc(&body_loc);
500
501 Ok(Some(
502 Expression::Match(Box::new(expression), patterns).between(
503 self.file_id,
504 &start.span,
505 &body_loc,
506 ),
507 ))
508 }
509
510 #[trace_parser]
511 #[tracing::instrument(skip(self))]
512 pub fn int_literal(&mut self) -> Result<Option<Loc<IntLiteral>>> {
513 let plusminus = match &self.peek()?.kind {
514 TokenKind::Plus | TokenKind::Minus => Some(self.eat_unconditional()?),
515 _ => None,
516 };
517 if self.peek_cond(TokenKind::is_integer, "integer")? {
518 let token = self.eat_unconditional()?;
519 match &token.kind {
520 TokenKind::Integer(val)
521 | TokenKind::HexInteger(val)
522 | TokenKind::BinInteger(val) => {
523 let (val_int, val_signed) = val;
524
525 let signed_val = || {
526 if plusminus.as_ref().map(|tok| &tok.kind) == Some(&TokenKind::Minus) {
527 -val_int.to_bigint()
528 } else {
529 val_int.to_bigint()
530 }
531 };
532
533 let inner = match val_signed {
534 LiteralKind::Signed(size) => IntLiteral::Signed {
535 val: signed_val(),
536 size: size.clone(),
537 },
538 LiteralKind::Unsized => IntLiteral::Unsized(signed_val()),
539 LiteralKind::Unsigned(size) => IntLiteral::Unsigned {
540 val: val_int.clone(),
541 size: size.clone(),
542 },
543 };
544 let loc = if let Some(pm) = plusminus {
545 ().between(self.file_id, &pm, &token)
546 } else {
547 token.loc()
548 };
549 Ok(Some(inner.at_loc(&loc)))
550 }
551 _ => unreachable!(),
552 }
553 } else if let Some(pm) = plusminus {
554 Err(Diagnostic::error(
555 pm.loc(),
556 format!("expected a number after '{}'", pm.kind.as_str()),
557 ))
558 } else {
559 Ok(None)
560 }
561 }
562
563 #[trace_parser]
564 fn bool_literal(&mut self) -> Result<Option<Loc<bool>>> {
565 if let Some(tok) = self.peek_and_eat(&TokenKind::True)? {
566 Ok(Some(true.at(self.file_id, &tok.span)))
567 } else if let Some(tok) = self.peek_and_eat(&TokenKind::False)? {
568 Ok(Some(false.at(self.file_id, &tok.span)))
569 } else {
570 Ok(None)
571 }
572 }
573
574 #[trace_parser]
575 fn bit_literal(&mut self) -> Result<Option<Loc<BitLiteral>>> {
576 if let Some(tok) = self.peek_and_eat(&TokenKind::Low)? {
577 Ok(Some(BitLiteral::Low.at(self.file_id, &tok.span)))
578 } else if let Some(tok) = self.peek_and_eat(&TokenKind::High)? {
579 Ok(Some(BitLiteral::High.at(self.file_id, &tok.span)))
580 } else if let Some(tok) = self.peek_and_eat(&TokenKind::HighImp)? {
581 Ok(Some(BitLiteral::HighImp.at(self.file_id, &tok.span)))
582 } else {
583 Ok(None)
584 }
585 }
586
587 #[trace_parser]
588 #[tracing::instrument(skip(self))]
589 pub fn block(&mut self, is_pipeline: bool) -> Result<Option<Loc<Block>>> {
590 let start = peek_for!(self, &TokenKind::OpenBrace);
591
592 let (statements, result) = self.statements(is_pipeline)?;
593
594 let end = self.eat(&TokenKind::CloseBrace)?;
595
596 Ok(Some(Block { statements, result }.between(
597 self.file_id,
598 &start.span,
599 &end.span,
600 )))
601 }
602
603 #[trace_parser]
604 pub fn pipeline_reference(&mut self) -> Result<Option<Loc<Expression>>> {
605 let start = peek_for!(self, &TokenKind::Stage);
606 let next = self.peek()?;
608
609 let parsed = self.first_successful(vec![
610 &|s: &mut Self| s.pipeline_stage_reference(&start),
611 &|s: &mut Self| s.pipeline_stage_status(&start),
612 ])?;
613 match parsed {
614 Some(e) => Ok(Some(e)),
615 None => Err(Diagnostic::from(UnexpectedToken {
616 got: next,
617 expected: vec![".", "("],
618 })),
619 }
620 }
621
622 #[trace_parser]
623 pub fn pipeline_stage_reference(
624 &mut self,
625 stage_keyword: &Token,
626 ) -> Result<Option<Loc<Expression>>> {
627 peek_for!(self, &TokenKind::OpenParen);
628
629 self.unit_context.allows_pipeline_ref(stage_keyword.loc())?;
630
631 let next = self.peek()?;
632 let reference = match next.kind {
633 TokenKind::Plus => {
634 let start = self.eat_unconditional()?;
635 let offset = self.expression()?;
636 let result = PipelineStageReference::Relative(
637 TypeExpression::ConstGeneric(Box::new(offset.clone())).between(
638 self.file_id,
639 &start,
640 &offset,
641 ),
642 );
643 result
644 }
645 TokenKind::Minus => {
646 let start = self.eat_unconditional()?;
647 let offset = self.expression()?;
648 let texpr = TypeExpression::ConstGeneric(Box::new(
649 Expression::UnaryOperator(
650 spade_ast::UnaryOperator::Sub.at(self.file_id, &next.span),
651 Box::new(offset.clone()),
652 )
653 .between(self.file_id, &start, &offset),
654 ))
655 .between(self.file_id, &start, &offset);
656 PipelineStageReference::Relative(texpr)
657 }
658 TokenKind::Identifier(_) => PipelineStageReference::Absolute(self.identifier()?),
659 _ => {
660 return Err(Diagnostic::from(UnexpectedToken {
661 got: next,
662 expected: vec!["+", "-", "identifier"],
663 }));
664 }
665 };
666
667 let close_paren = self.eat(&TokenKind::CloseParen)?;
668
669 self.eat(&TokenKind::Dot)?;
670
671 let ident = self.identifier()?;
672
673 Ok(Some(
674 Expression::PipelineReference {
675 stage_kw_and_reference_loc: ().between(
676 self.file_id,
677 &stage_keyword.span,
678 &close_paren.span,
679 ),
680 stage: reference,
681 name: ident.clone(),
682 }
683 .between(self.file_id, &stage_keyword.span, &ident),
684 ))
685 }
686
687 #[trace_parser]
688 pub fn pipeline_stage_status(
689 &mut self,
690 stage_keyword: &Token,
691 ) -> Result<Option<Loc<Expression>>> {
692 peek_for!(self, &TokenKind::Dot);
693
694 let ident = self.identifier()?;
695
696 match ident.inner.0.as_str() {
697 "valid" => Ok(Some(Expression::StageValid.between(
698 self.file_id,
699 stage_keyword,
700 &ident,
701 ))),
702 "ready" => Ok(Some(Expression::StageReady.between(
703 self.file_id,
704 stage_keyword,
705 &ident,
706 ))),
707 other => Err(Diagnostic::error(
708 &ident,
709 format!("Expected `ready` or `valid`, got `{other}`"),
710 )
711 .primary_label("Expected `ready` or `valid`")),
712 }
713 }
714
715 #[trace_parser]
716 fn argument_list(&mut self) -> Result<Option<Loc<ArgumentList>>> {
717 let is_named = self.peek_and_eat(&TokenKind::Dollar)?.is_some();
718 let opener = peek_for!(self, &TokenKind::OpenParen);
719
720 let argument_list = if is_named {
721 let args = self
722 .comma_separated(Self::named_argument, &TokenKind::CloseParen)
723 .extra_expected(vec![":"])
724 .map_err(|e| {
725 debug!("check named arguments =");
726 let Ok(tok) = self.peek() else {
727 return e;
728 };
729 debug!("{:?}", tok);
730 if tok.kind == TokenKind::Assignment {
731 e.span_suggest_replace(
732 "named arguments are specified with `:`",
733 tok.loc(),
736 ":",
737 )
738 } else {
739 e
740 }
741 })?
742 .into_iter()
743 .map(Loc::strip)
744 .collect();
745 ArgumentList::Named(args)
746 } else {
747 let args = self
748 .comma_separated(Self::expression, &TokenKind::CloseParen)
749 .no_context()?;
750
751 ArgumentList::Positional(args)
752 };
753 let end = self.eat(&TokenKind::CloseParen)?;
754 let span = lspan(opener.span).merge(lspan(end.span));
755 Ok(Some(argument_list.at(self.file_id, &span)))
756 }
757 #[trace_parser]
758 fn named_argument(&mut self) -> Result<Loc<NamedArgument>> {
759 let name = self.identifier()?;
761 if self.peek_and_eat(&TokenKind::Colon)?.is_some() {
762 let value = self.expression()?;
763
764 let span = name.span.merge(value.span);
765
766 Ok(NamedArgument::Full(name, value).at(self.file_id, &span))
767 } else {
768 Ok(NamedArgument::Short(name.clone()).at(self.file_id, &name))
769 }
770 }
771
772 #[trace_parser]
773 pub fn type_expression(&mut self) -> Result<Loc<TypeExpression>> {
774 if let Some(val) = self.int_literal()? {
775 Ok(TypeExpression::Integer(val.inner.clone().as_signed()).at_loc(&val))
776 } else if self.peek_kind(&TokenKind::OpenBrace)? {
777 let (expr, span) = self.surrounded(
778 &TokenKind::OpenBrace,
779 |s| s.expression(),
780 &TokenKind::CloseBrace,
781 )?;
782 Ok(TypeExpression::ConstGeneric(Box::new(expr)).at(self.file_id, &span))
783 } else {
784 let inner = self.type_spec()?;
785
786 Ok(TypeExpression::TypeSpec(Box::new(inner.clone())).at_loc(&inner))
787 }
788 }
789
790 #[trace_parser]
792 pub fn type_spec(&mut self) -> Result<Loc<TypeSpec>> {
793 if let Some(inv) = self.peek_and_eat(&TokenKind::Inv)? {
794 let rest = self.type_expression()?;
795 Ok(TypeSpec::Inverted(Box::new(rest.clone())).between(self.file_id, &inv, &rest))
796 } else if let Some(tilde) = self.peek_and_eat(&TokenKind::Tilde)? {
797 return Err(Diagnostic::error(
798 tilde.clone(),
799 "The syntax for inverted ports has changed from ~ to inv",
800 )
801 .primary_label("~ cannot be used in a type")
802 .span_suggest("Consider using inv", tilde, "inv "));
803 } else if let Some(wire_sign) = self.peek_and_eat(&TokenKind::Ampersand)? {
804 if let Some(mut_) = self.peek_and_eat(&TokenKind::Mut)? {
805 return Err(Diagnostic::error(
806 &().at(self.file_id, &mut_),
807 "The syntax of &mut has changed to inv &",
808 )
809 .primary_label("&mut is now written as inv &")
810 .span_suggest_replace(
811 "Consider using inv &",
812 ().between(self.file_id, &wire_sign, &mut_),
813 "inv &",
814 ));
815 }
816
817 let rest = self.type_expression()?;
818 Ok(TypeSpec::Wire(Box::new(rest.clone())).between(self.file_id, &wire_sign, &rest))
819 } else if let Some(tuple) = self.tuple_spec()? {
820 Ok(tuple)
821 } else if let Some(array) = self.array_spec()? {
822 Ok(array)
823 } else {
824 if !self.peek_cond(TokenKind::is_identifier, "Identifier")? {
825 return Err(Diagnostic::from(UnexpectedToken {
826 got: self.peek()?,
827 expected: vec!["type"],
828 }));
829 }
830 let (path, span) = self.path()?.separate();
832
833 if path.as_strs() == ["_"] {
834 return Ok(TypeSpec::Wildcard.at(self.file_id, &span));
835 }
836
837 let generics = if self.peek_kind(&TokenKind::Lt)? {
839 let generic_start = self.eat_unconditional()?;
840 let type_exprs = self
841 .comma_separated(Self::type_expression, &TokenKind::Gt)
842 .extra_expected(vec!["type expression"])?;
843 let generic_end = self.eat(&TokenKind::Gt)?;
844 Some(type_exprs.between(self.file_id, &generic_start.span, &generic_end.span))
845 } else {
846 None
847 };
848
849 let span_end = generics.as_ref().map(|g| g.span).unwrap_or(span);
850 Ok(TypeSpec::Named(path, generics).between(self.file_id, &span, &span_end))
851 }
852 }
853
854 #[trace_parser]
855 pub fn tuple_spec(&mut self) -> Result<Option<Loc<TypeSpec>>> {
856 let start = peek_for!(self, &TokenKind::OpenParen);
857 if let Some(_) = self.peek_and_eat(&TokenKind::Comma)? {
858 let closer = self.eat(&TokenKind::CloseParen)?;
859 return Ok(Some(TypeSpec::Tuple(vec![]).between(
860 self.file_id,
861 &start,
862 &closer,
863 )));
864 }
865
866 let inner = self
867 .comma_separated(Self::type_expression, &TokenKind::CloseParen)
868 .no_context()?;
869 let end = self.eat(&TokenKind::CloseParen)?;
870
871 let span = lspan(start.span).merge(lspan(end.span));
872
873 Ok(Some(TypeSpec::Tuple(inner).at(self.file_id, &span)))
874 }
875
876 #[trace_parser]
877 pub fn array_spec(&mut self) -> Result<Option<Loc<TypeSpec>>> {
878 let start = peek_for!(self, &TokenKind::OpenBracket);
879
880 let inner = self.type_expression()?;
881
882 if let Some(end) = self.peek_and_eat(&TokenKind::CloseBracket)? {
883 return Err(Diagnostic::error(
884 ().between_locs(&start.loc(), &end.loc()),
885 "missing array size",
886 )
887 .primary_label("missing size for this array type")
888 .note("array types need a specified size")
889 .span_suggest_insert_before("insert a size here", end, "; /* N */"));
890 }
891
892 self.eat(&TokenKind::Semi)?;
893
894 let size = self.type_expression()?;
895
896 let end = self.eat(&TokenKind::CloseBracket)?;
897
898 Ok(Some(
899 TypeSpec::Array {
900 inner: Box::new(inner),
901 size: Box::new(size),
902 }
903 .between(self.file_id, &start, &end),
904 ))
905 }
906
907 #[trace_parser]
912 pub fn name_and_type(&mut self) -> Result<(Loc<Identifier>, Loc<TypeSpec>)> {
913 let name = self.identifier()?;
914 self.eat(&TokenKind::Colon)?;
915 let t = self.type_spec()?;
916 Ok((name, t))
917 }
918
919 #[trace_parser]
920 pub fn pattern(&mut self) -> Result<Loc<Pattern>> {
921 let result = self.first_successful(vec![
922 &|s| {
923 let start = peek_for!(s, &TokenKind::OpenParen);
924 let inner = s
925 .comma_separated(Self::pattern, &TokenKind::CloseParen)
926 .no_context()?;
927 let end = s.eat(&TokenKind::CloseParen)?;
928
929 Ok(Some(Pattern::Tuple(inner).between(
930 s.file_id,
931 &start.span,
932 &end.span,
933 )))
934 },
935 &|s| {
936 let start = peek_for!(s, &TokenKind::OpenBracket);
937 let inner = s
938 .comma_separated(Self::pattern, &TokenKind::CloseBracket)
939 .no_context()?;
940 let end = s.eat(&TokenKind::CloseBracket)?;
941 Ok(Some(Pattern::Array(inner).between(
942 s.file_id,
943 &start.span,
944 &end.span,
945 )))
946 },
947 &|s| {
948 Ok(s.int_literal()?
949 .map(|val| val.map(Pattern::Integer)))
951 },
952 &|s| {
953 Ok(s.bool_literal()?
954 .map(|val| val.map(Pattern::Bool)))
956 },
957 &|s| {
958 let path = s.path()?;
959 let path_span = path.span;
960
961 if let Some(start_paren) = s.peek_and_eat(&TokenKind::OpenParen)? {
962 let inner = s
963 .comma_separated(Self::pattern, &TokenKind::CloseParen)
964 .no_context()?;
965 let end_paren = s.eat(&TokenKind::CloseParen)?;
966
967 Ok(Some(
968 Pattern::Type(
969 path,
970 ArgumentPattern::Positional(inner).between(
971 s.file_id,
972 &start_paren.span,
973 &end_paren.span,
974 ),
975 )
976 .between(s.file_id, &path_span, &end_paren.span),
977 ))
978 } else if let Some(start_brace) = s.peek_and_eat(&TokenKind::Dollar)? {
979 s.eat(&TokenKind::OpenParen)?;
980 let inner_parser = |s: &mut Self| {
981 let lhs = s.identifier()?;
982 let rhs = if s.peek_and_eat(&TokenKind::Colon)?.is_some() {
983 Some(s.pattern()?)
984 } else {
985 None
986 };
987
988 Ok((lhs, rhs))
989 };
990 let inner = s
991 .comma_separated(inner_parser, &TokenKind::CloseParen)
992 .extra_expected(vec![":"])?;
993 let end_brace = s.eat(&TokenKind::CloseParen)?;
994
995 Ok(Some(
996 Pattern::Type(
997 path,
998 ArgumentPattern::Named(inner).between(
999 s.file_id,
1000 &start_brace.span,
1001 &end_brace.span,
1002 ),
1003 )
1004 .between(s.file_id, &path_span, &end_brace.span),
1005 ))
1006 } else {
1007 Ok(Some(Pattern::Path(path.clone()).at(s.file_id, &path)))
1008 }
1009 },
1010 ])?;
1011
1012 if let Some(result) = result {
1013 Ok(result)
1014 } else {
1015 Err(Diagnostic::from(UnexpectedToken {
1016 got: self.eat_unconditional()?,
1017 expected: vec!["Pattern"],
1018 }))
1019 }
1020 }
1021
1022 #[trace_parser]
1023 pub fn statements(
1024 &mut self,
1025 allow_stages: bool,
1026 ) -> Result<(Vec<Loc<Statement>>, Option<Loc<Expression>>)> {
1027 fn semi_validator(next: Token) -> Result<TokenKind> {
1028 match next.kind {
1029 TokenKind::GreekQuestionMark => Err(Diagnostic::error(
1030 next.clone(),
1031 format!("Expected `;`, got a greek question mark (;)"),
1032 )
1033 .help("The greek question mark (;) looks similar to the normal `;` character")),
1034 other => Ok(other),
1035 }
1036 }
1037 let semi_continuation = |inner: Loc<Statement>, parser: &mut Parser| {
1038 let next = parser.peek()?;
1039 let span = next.loc();
1040 match semi_validator(next) {
1041 Ok(TokenKind::Semi) => {
1042 parser.eat_unconditional()?;
1043 Ok(inner)
1044 }
1045 Ok(other) => Err(Diagnostic::error(
1046 span,
1047 format!("Expected `;`, got `{}`", other.as_str()),
1048 )
1049 .primary_label("Expected `;`")
1050 .span_suggest_insert_after(
1051 "You probably forgot to end this statement with a `;`",
1052 inner,
1053 ";",
1054 )),
1055 Err(err) => Err(err),
1056 }
1057 };
1058
1059 let mut final_expr = None;
1060 let members = self.keyword_peeking_parser_or_else_seq(
1061 vec![
1062 Box::new(BindingParser {}.then(semi_continuation)),
1063 Box::new(RegisterParser {}.then(semi_continuation).then(
1064 move |statement, _parser| {
1065 if let Statement::PipelineRegMarker(_, _) = statement.inner {
1066 if !allow_stages {
1067 return Err(Diagnostic::error(
1068 statement.loc(),
1069 "stage outside pipeline",
1070 )
1071 .primary_label("stage is not allowed here")
1072 .note("stages are only allowed in the root block of a pipeline"));
1073 }
1074 }
1075 Ok(statement)
1076 },
1077 )),
1078 Box::new(DeclParser {}.then(semi_continuation)),
1079 Box::new(LabelParser {}),
1080 Box::new(AssertParser {}.then(semi_continuation)),
1081 Box::new(SetParser {}.then(semi_continuation)),
1082 ],
1083 true,
1084 vec![TokenKind::CloseBrace],
1085 |parser| {
1086 if parser.peek_kind(&TokenKind::CloseBrace)? {
1087 return Ok(None);
1088 }
1089 let (expr, loc) = parser.non_comptime_expression()?.separate_loc();
1090 if matches!(semi_validator(parser.peek()?)?, TokenKind::Semi) {
1091 parser.eat_unconditional()?;
1092 Ok(Some(Statement::Expression(expr).at_loc(&loc)))
1093 } else {
1094 final_expr = Some(expr);
1096 Ok(None)
1097 }
1098 },
1099 )?;
1100
1101 Ok((members, final_expr))
1102 }
1103
1104 #[trace_parser]
1105 pub fn self_arg(&mut self) -> Result<Option<Loc<()>>> {
1106 if self.peek_cond(
1107 |t| t == &TokenKind::Identifier("self".to_string()),
1108 "looking for self",
1109 )? {
1110 let tok = self.eat_unconditional()?;
1111 Ok(Some(().at(self.file_id, &tok.span)))
1112 } else {
1113 Ok(None)
1114 }
1115 }
1116
1117 #[trace_parser]
1118 pub fn parameter(&mut self) -> Result<(AttributeList, Loc<Identifier>, Loc<TypeSpec>)> {
1119 let attrs = self.attributes()?;
1120 let (name, ty) = self.name_and_type()?;
1121 Ok((attrs, name, ty))
1122 }
1123
1124 #[trace_parser]
1125 pub fn parameter_list(&mut self) -> Result<ParameterList> {
1126 let self_ = if self.peek_cond(
1127 |tok| tok == &TokenKind::Identifier(String::from("self")),
1128 "Expected argument",
1129 )? {
1130 let self_tok = self.eat_unconditional()?;
1131 self.peek_and_eat(&TokenKind::Comma)?;
1132 Some(().at(self.file_id, &self_tok))
1133 } else {
1134 None
1135 };
1136
1137 Ok(ParameterList {
1138 self_,
1139 args: self
1140 .comma_separated(Self::parameter, &TokenKind::CloseParen)
1141 .no_context()?,
1142 })
1143 }
1144
1145 #[tracing::instrument(skip(self))]
1146 pub fn type_parameter_list(&mut self) -> Result<ParameterList> {
1147 Ok(ParameterList::without_self(
1148 self.comma_separated(Self::name_and_type, &TokenKind::CloseBrace)
1149 .no_context()?,
1150 ))
1151 }
1152
1153 #[trace_parser]
1154 pub fn type_param(&mut self) -> Result<Loc<TypeParam>> {
1155 if let Some(_hash) = self.peek_and_eat(&TokenKind::Hash)? {
1157 let meta_type = self.identifier()?;
1158 let name = self.identifier()?;
1159
1160 let loc = ().between_locs(&meta_type, &name);
1161 Ok(TypeParam::TypeWithMeta {
1162 meta: meta_type,
1163 name,
1164 }
1165 .at_loc(&loc))
1166 } else {
1167 let (id, loc) = self.identifier()?.separate();
1168 let traits = if self.peek_and_eat(&TokenKind::Colon)?.is_some() {
1169 self.token_separated(
1170 Self::path_with_generic_spec,
1171 &TokenKind::Plus,
1172 vec![TokenKind::Comma, TokenKind::Gt],
1173 )
1174 .no_context()?
1175 .into_iter()
1176 .map(|(path, type_params)| {
1177 let loc = ().at_loc(&path);
1178 TraitSpec { path, type_params }.at_loc(&loc)
1179 })
1180 .collect()
1181 } else {
1182 vec![]
1183 };
1184 Ok(TypeParam::TypeName { name: id, traits }.at(self.file_id, &loc))
1185 }
1186 }
1187
1188 #[trace_parser]
1189 pub fn generics_list(&mut self) -> Result<Option<Loc<Vec<Loc<TypeParam>>>>> {
1190 if self.peek_kind(&TokenKind::Lt)? {
1191 let (params, loc) = self.surrounded(
1192 &TokenKind::Lt,
1193 |s| {
1194 s.comma_separated(Self::type_param, &TokenKind::Gt)
1195 .extra_expected(vec!["type parameter"])
1196 },
1197 &TokenKind::Gt,
1198 )?;
1199 Ok(Some(params.at_loc(&loc)))
1200 } else {
1201 Ok(None)
1202 }
1203 }
1204
1205 #[trace_parser]
1206 pub fn generic_spec_list(&mut self) -> Result<Option<Loc<Vec<Loc<TypeExpression>>>>> {
1207 if self.peek_kind(&TokenKind::Lt)? {
1208 let (params, loc) = self.surrounded(
1209 &TokenKind::Lt,
1210 |s| {
1211 s.comma_separated(Self::type_expression, &TokenKind::Gt)
1212 .extra_expected(vec!["type spec"])
1213 },
1214 &TokenKind::Gt,
1215 )?;
1216 Ok(Some(params.at_loc(&loc)))
1217 } else {
1218 Ok(None)
1219 }
1220 }
1221
1222 #[trace_parser]
1223 pub fn path_with_generic_spec(
1224 &mut self,
1225 ) -> Result<(Loc<Path>, Option<Loc<Vec<Loc<TypeExpression>>>>)> {
1226 Ok((self.path()?, self.generic_spec_list()?))
1227 }
1228
1229 fn disallow_attributes(&self, attributes: &AttributeList, item_start: &Token) -> Result<()> {
1230 if attributes.0.is_empty() {
1231 Ok(())
1232 } else {
1233 let mut diagnostic = Diagnostic::error(
1234 ().between_locs(attributes.0.first().unwrap(), attributes.0.last().unwrap()),
1235 "invalid attribute location",
1236 )
1237 .primary_label("attributes are not allowed here")
1238 .secondary_label(
1239 item_start.loc(),
1240 format!("...because this is a {}", item_start.kind.as_str()),
1241 )
1242 .note("attributes are only allowed on structs, enums, their variants, functions and pipelines");
1243 if matches!(item_start.kind, TokenKind::Mod) {
1244 diagnostic.add_help(
1245 "If you want to document this module, use inside comments (//!) instead.",
1246 );
1247 }
1248 Err(diagnostic)
1249 }
1250 }
1251
1252 pub fn unit_kind(&mut self, start_token: &Token) -> Result<Option<Loc<UnitKind>>> {
1253 match start_token.kind {
1254 TokenKind::Pipeline => {
1255 self.eat_unconditional()?;
1256 let (depth, depth_span) = self.surrounded(
1257 &TokenKind::OpenParen,
1258 |s| match s.type_expression() {
1259 Ok(t) => Ok(t),
1260 Err(diag) => Err(diag.secondary_label(
1261 ().at(s.file_id, start_token),
1262 "Pipelines require a pipeline depth",
1263 )),
1264 },
1265 &TokenKind::CloseParen,
1266 )?;
1267
1268 Ok(Some(UnitKind::Pipeline(depth).between(
1269 self.file_id,
1270 start_token,
1271 &depth_span,
1272 )))
1273 }
1274 TokenKind::Function => {
1275 self.eat_unconditional()?;
1276 Ok(Some(UnitKind::Function.at(self.file_id, start_token)))
1277 }
1278 TokenKind::Entity => {
1279 self.eat_unconditional()?;
1280 Ok(Some(UnitKind::Entity.at(self.file_id, start_token)))
1281 }
1282 _ => Ok(None),
1283 }
1284 }
1285
1286 #[trace_parser]
1287 #[tracing::instrument(skip(self))]
1288 pub fn unit_head(&mut self, attributes: &AttributeList) -> Result<Option<Loc<UnitHead>>> {
1289 let extern_token = self.peek_and_eat(&TokenKind::Extern)?;
1290 let start_token = self.peek()?;
1291 let Some(unit_kind) = self.unit_kind(&start_token)? else {
1292 return Ok(None);
1293 };
1294
1295 let name = self.identifier()?;
1296
1297 let type_params = self.generics_list()?;
1298
1299 let (inputs, inputs_loc) = self.surrounded(
1301 &TokenKind::OpenParen,
1302 Self::parameter_list,
1303 &TokenKind::CloseParen,
1304 )?;
1305 let inputs = inputs.at_loc(&inputs_loc);
1306
1307 let output_type = if let Some(arrow) = self.peek_and_eat(&TokenKind::SlimArrow)? {
1309 Some((arrow.loc(), self.type_spec()?))
1310 } else {
1311 None
1312 };
1313
1314 let where_clauses = self.where_clauses()?;
1315
1316 let end = output_type
1317 .as_ref()
1318 .map(|o| o.1.loc())
1319 .unwrap_or(inputs.loc());
1320
1321 Ok(Some(
1322 UnitHead {
1323 extern_token: extern_token.map(|token| token.loc()),
1324 attributes: attributes.clone(),
1325 unit_kind,
1326 name,
1327 inputs,
1328 output_type,
1329 type_params,
1330 where_clauses,
1331 }
1332 .between(self.file_id, &start_token, &end),
1333 ))
1334 }
1335
1336 fn where_clauses(&mut self) -> Result<Vec<WhereClause>> {
1337 if let Some(where_kw) = self.peek_and_eat(&TokenKind::Where)? {
1338 let clauses = self
1339 .token_separated(
1340 |s| {
1341 if s.peek_cond(|t| matches!(t, &TokenKind::Identifier(_)), "identifier")? {
1342 let name = s.path()?;
1343 let _colon = s.eat(&TokenKind::Colon)?;
1344
1345 if s.peek_cond(
1346 |tok| tok == &TokenKind::OpenBrace || tok == &TokenKind::Semi,
1347 "{",
1348 )? {
1349 let expression = s
1350 .surrounded(
1351 &TokenKind::OpenBrace,
1352 Self::expression,
1353 &TokenKind::CloseBrace,
1354 )?
1355 .0;
1356
1357 Ok(WhereClause::GenericInt {
1358 target: name,
1359 expression,
1360 })
1361 } else {
1362 let traits = s
1363 .token_separated(
1364 Self::path_with_generic_spec,
1365 &TokenKind::Plus,
1366 vec![
1367 TokenKind::Comma,
1368 TokenKind::OpenBrace,
1369 TokenKind::Semi,
1370 ],
1371 )
1372 .extra_expected(vec!["identifier"])?
1373 .into_iter()
1374 .map(|(path, type_params)| {
1375 let loc = ().at_loc(&path);
1376 TraitSpec { path, type_params }.at_loc(&loc)
1377 })
1378 .collect();
1379
1380 Ok(WhereClause::TraitBounds {
1381 target: name,
1382 traits,
1383 })
1384 }
1385 } else {
1386 Err(Diagnostic::bug(
1387 ().at(s.file_id, &where_kw),
1388 "Comma separated should not show this error",
1389 ))
1390 }
1391 },
1392 &TokenKind::Comma,
1393 vec![TokenKind::OpenBrace, TokenKind::Semi],
1394 )
1395 .extra_expected(vec!["identifier"])?;
1396
1397 Ok(clauses)
1398 } else {
1399 Ok(vec![])
1400 }
1401 }
1402
1403 #[trace_parser]
1404 pub fn impl_body(&mut self) -> Result<Vec<Loc<Unit>>> {
1405 let result = self.keyword_peeking_parser_seq(
1406 vec![Box::new(items::UnitParser {}.map(|u| {
1407 if u.head.unit_kind.is_pipeline() {
1408 return Err(Diagnostic::error(
1409 u.head.unit_kind.loc(),
1410 "Pipelines are currently not allowed in impl blocks",
1411 )
1412 .primary_label("Not allowed here")
1413 .note("This limitation is likely to be lifted in the future")
1414 .help("Consider defining a free-standing pipeline for now"));
1415 } else {
1416 Ok(u)
1417 }
1418 }))],
1419 true,
1420 vec![TokenKind::CloseBrace],
1421 )?;
1422
1423 Ok(result)
1424 }
1425
1426 #[trace_parser]
1427 #[tracing::instrument(level = "debug", skip(self))]
1428 pub fn enum_variant(&mut self) -> Result<EnumVariant> {
1429 let attributes = self.attributes()?;
1430
1431 let name = self.identifier()?;
1432
1433 let args = if let Some(start) = self.peek_and_eat(&TokenKind::OpenBrace)? {
1434 let result = self.type_parameter_list()?;
1435 let end = self.eat(&TokenKind::CloseBrace)?;
1436 Some(result.between(self.file_id, &start, &end))
1437 } else if self.peek_kind(&TokenKind::Comma)? || self.peek_kind(&TokenKind::CloseBrace)? {
1438 None
1439 } else {
1440 let token = self.peek()?;
1441 let message = unexpected_token_message(&token.kind, "`{`, `,` or `}`");
1442 let mut err = Diagnostic::error(token, message);
1444 self.maybe_suggest_brace_enum_variant(&mut err)?;
1445 return Err(err);
1446 };
1447
1448 Ok(EnumVariant {
1449 attributes,
1450 name,
1451 args,
1452 })
1453 }
1454
1455 fn maybe_suggest_brace_enum_variant(&mut self, err: &mut Diagnostic) -> Result<bool> {
1456 let open_paren = match self.peek_and_eat(&TokenKind::OpenParen)? {
1457 Some(open_paren) => open_paren.loc(),
1458 _ => return Ok(false),
1459 };
1460 let mut try_parameter_list = self.clone();
1461 if try_parameter_list.parameter_list().is_err() {
1462 return Ok(false);
1463 }
1464 let close_paren = match try_parameter_list.peek_and_eat(&TokenKind::CloseParen)? {
1465 Some(close_paren) => close_paren.loc(),
1466 _ => return Ok(false),
1467 };
1468 err.push_subdiagnostic(
1469 SuggestBraceEnumVariant {
1470 open_paren,
1471 close_paren,
1472 }
1473 .into(),
1474 );
1475 Ok(true)
1476 }
1477
1478 #[trace_parser]
1480 #[tracing::instrument(skip(self, value))]
1481 pub fn attribute_key_value<T>(
1482 &mut self,
1483 key: &str,
1484 value: impl Fn(&mut Self) -> Result<T>,
1485 ) -> Result<Option<(Loc<String>, T)>> {
1486 let next = self.peek()?;
1487 if next.kind == TokenKind::Identifier(key.to_string()) {
1488 self.eat_unconditional()?;
1489
1490 self.eat(&TokenKind::Assignment)?;
1491
1492 Ok(Some((
1493 key.to_string().at(self.file_id, &next),
1494 value(self)?,
1495 )))
1496 } else {
1497 Ok(None)
1498 }
1499 }
1500
1501 #[trace_parser]
1502 #[tracing::instrument(skip(self))]
1503 pub fn attribute_inner(&mut self) -> Result<Attribute> {
1504 let start = self.identifier()?;
1505
1506 macro_rules! bool_or_payload {
1507 ($name:ident bool) => {
1508 let mut $name = false;
1509 };
1510 ($name:ident $rest:tt) => {
1511 let mut $name = None;
1512 };
1513 }
1514 macro_rules! rhs_or_present {
1515 ($name:ident, $tok:expr, $s:ident, bool) => {
1516 $name = true
1517 };
1518 ($name:ident, $tok:expr, $s:ident, $subparser:tt) => {{
1519 if let Some(prev) = &$name {
1520 return Err(Diagnostic::error(
1521 $tok,
1522 format!("{} specified more than once", stringify!($name)),
1523 )
1524 .primary_label("Specified multiple times")
1525 .secondary_label(prev, "Previously specified here")
1526 .into());
1527 }
1528
1529 $s.peek_and_eat(&TokenKind::Assignment)?;
1530 $name = Some($subparser?)
1531 }};
1532 }
1533
1534 macro_rules! check_required {
1535 ($attr_token:expr, $name:ident) => {};
1536 ($attr_token:expr, $name:ident $required:ident) => {
1537 let $name = if let Some(inner) = $name {
1538 inner
1539 } else {
1540 return Err(Diagnostic::error(
1541 $attr_token,
1542 format!("Missing argument '{}'", stringify!($name)),
1543 )
1544 .primary_label(format!("Missing argument '{}'", stringify!($name)))
1545 .into());
1546 };
1547 };
1548 }
1549
1550 macro_rules! attribute_arg_parser {
1551 ($attr:expr, $self:expr, $s:ident, $result_struct:path{ $($name:ident $([$required:ident])?: $assignment:tt),* }) => {
1552 {
1553 $( bool_or_payload!($name $assignment) );*;
1554
1555 let params = vec![$(stringify!($name)),*];
1556
1557 $self.surrounded(
1558 &TokenKind::OpenParen, |$s| {
1559 loop {
1560 let next = $s.peek()?;
1561 match &next.kind {
1562 $(
1563 TokenKind::Identifier(ident) if ident == stringify!($name) => {
1564 $s.eat_unconditional()?;
1565 rhs_or_present!($name, next, $s, $assignment);
1566 }
1567 ),*
1568 TokenKind::Identifier(_) => {
1569 return Err(Diagnostic::error(next, format!("Invalid parameter for {}", $attr))
1570 .primary_label("Invalid parameter")
1571 .note(if params.is_empty() {
1572 format!(
1573 "{} does not take any parameters",
1574 $attr
1575 )
1576 } else if params.len() == 1 {
1577 format!(
1578 "{} only takes the parameter {}",
1579 $attr,
1580 params[0]
1581 )
1582 } else {
1583 format!(
1584 "{} only takes the parameters {} or {}",
1585 $attr,
1586 params.iter().take(params.len()-1).join(", "),
1587 params[params.len() - 1]
1588 )
1589 })
1590 .into()
1591 )
1592 }
1593 TokenKind::Comma => {
1594 $s.eat_unconditional()?;
1595 }
1596 TokenKind::CloseParen => {
1597 break
1598 },
1599 _ => {
1600 return Err(Diagnostic::from(UnexpectedToken {
1601 got: next,
1602 expected: vec!["identifier", ",", ")"],
1603 }).into())
1604 }
1605 }
1606 }
1607
1608 Ok(())
1609 },
1610 &TokenKind::CloseParen
1611 )?;
1612
1613 $(check_required!($attr, $name $($required)?);)*
1614
1615 $result_struct {
1616 $($name),*
1617 }
1618 }
1619 }
1620 }
1621
1622 match start.inner.0.as_str() {
1623 "no_mangle" => {
1624 if self.peek_kind(&TokenKind::OpenParen)? {
1625 let (all, _) = self.surrounded(
1626 &TokenKind::OpenParen,
1627 Self::identifier,
1628 &TokenKind::CloseParen,
1629 )?;
1630 if all.inner.0.as_str() != "all" {
1631 Err(Diagnostic::error(&all, "Invalid attribute syntax")
1632 .primary_label("Unexpected parameter to `#[no_mangle])")
1633 .span_suggest_replace("Did you mean `#[no_mangle(all)]`?", all, "all"))
1634 } else {
1635 Ok(Attribute::NoMangle { all: true })
1636 }
1637 } else {
1638 Ok(Attribute::NoMangle { all: false })
1639 }
1640 }
1641 "fsm" => {
1642 if self.peek_kind(&TokenKind::OpenParen)? {
1643 let (state, _) = self.surrounded(
1644 &TokenKind::OpenParen,
1645 Self::identifier,
1646 &TokenKind::CloseParen,
1647 )?;
1648 Ok(Attribute::Fsm { state: Some(state) })
1649 } else {
1650 Ok(Attribute::Fsm { state: None })
1651 }
1652 }
1653 "optimize" => {
1654 let (passes, _) = self.surrounded(
1655 &TokenKind::OpenParen,
1656 |s| {
1657 s.comma_separated(|s| s.identifier(), &TokenKind::CloseParen)
1658 .no_context()
1659 },
1660 &TokenKind::CloseParen,
1661 )?;
1662
1663 Ok(Attribute::Optimize {
1664 passes: passes
1665 .into_iter()
1666 .map(|loc| loc.map(|ident| ident.0))
1667 .collect(),
1668 })
1669 }
1670 "wal_trace" => {
1671 if self.peek_kind(&TokenKind::OpenParen)? {
1672 Ok(attribute_arg_parser!(
1673 start,
1674 self,
1675 s,
1676 Attribute::WalTrace {
1677 clk: { s.expression() },
1678 rst: { s.expression() }
1679 }
1680 ))
1681 } else {
1682 Ok(Attribute::WalTrace {
1683 clk: None,
1684 rst: None,
1685 })
1686 }
1687 }
1688 "wal_traceable" => Ok(attribute_arg_parser!(
1689 start,
1690 self,
1691 s,
1692 Attribute::WalTraceable {
1693 suffix: { s.identifier() },
1694 uses_clk: bool,
1695 uses_rst: bool
1696 }
1697 )),
1698 "wal_suffix" => Ok(attribute_arg_parser!(start, self, s, Attribute::WalSuffix {
1699 suffix [required]: {s.identifier()}
1700 })),
1701 other => Err(
1702 Diagnostic::error(&start, format!("Unknown attribute '{other}'"))
1703 .primary_label("Unrecognised attribute"),
1704 ),
1705 }
1706 }
1707
1708 #[trace_parser]
1709 pub fn attributes(&mut self) -> Result<AttributeList> {
1710 let mut result = AttributeList(vec![]);
1712 loop {
1713 if let Some(start) = self.peek_and_eat(&TokenKind::Hash)? {
1714 let (inner, loc) = self.surrounded(
1715 &TokenKind::OpenBracket,
1716 Self::attribute_inner,
1717 &TokenKind::CloseBracket,
1718 )?;
1719
1720 result.0.push(inner.between(self.file_id, &start, &loc));
1721 } else if self.peek_cond(
1722 |tk| matches!(tk, TokenKind::OutsideDocumentation(_)),
1723 "Outside doc-comment",
1724 )? {
1725 let token = self.eat_unconditional()?;
1726 let TokenKind::OutsideDocumentation(doc) = token.kind else {
1727 unreachable!("eat_cond should have checked this");
1728 };
1729 result
1730 .0
1731 .push(Attribute::Documentation { content: doc }.at(token.file_id, &token.span));
1732 } else {
1733 break;
1734 }
1735 }
1736 Ok(result)
1737 }
1738
1739 #[trace_parser]
1740 #[tracing::instrument(skip(self))]
1741 pub fn module_body(&mut self) -> Result<ModuleBody> {
1742 let mut documentation = vec![];
1743 while self.peek_cond(
1744 |tk| matches!(tk, TokenKind::InsideDocumentation(_)),
1745 "Inside doc-comment",
1746 )? {
1747 let token = self.eat_unconditional()?;
1748 let TokenKind::InsideDocumentation(doc) = token.kind else {
1749 unreachable!("eat_cond should have checked this");
1750 };
1751 documentation.push(doc);
1752 }
1753
1754 let members = self.keyword_peeking_parser_seq(
1755 vec![
1756 Box::new(items::UnitParser {}.map(|inner| Ok(Item::Unit(inner)))),
1757 Box::new(items::TraitDefParser {}.map(|inner| Ok(Item::TraitDef(inner)))),
1758 Box::new(items::ImplBlockParser {}.map(|inner| Ok(Item::ImplBlock(inner)))),
1759 Box::new(items::StructParser {}.map(|inner| Ok(Item::Type(inner)))),
1760 Box::new(items::EnumParser {}.map(|inner| Ok(Item::Type(inner)))),
1761 Box::new(items::ModuleParser {}),
1762 Box::new(items::UseParser {}.map(|inner| Ok(Item::Use(inner)))),
1763 ],
1764 true,
1765 vec![],
1766 )?;
1767 Ok(ModuleBody {
1768 members,
1769 documentation,
1770 })
1771 }
1772
1773 #[trace_parser]
1776 #[tracing::instrument(skip(self))]
1777 pub fn top_level_module_body(&mut self) -> Result<Loc<ModuleBody>> {
1778 let start_token = self.peek()?;
1779 let result = self.module_body()?;
1780 let end_token = self.peek()?;
1781
1782 if self.peek_kind(&TokenKind::Eof)? {
1783 Ok(result.between(self.file_id, &start_token, &end_token))
1784 } else {
1785 let got = self.peek()?;
1786 Err(Diagnostic::error(
1787 got.loc(),
1788 format!("expected item, got `{}`", got.kind.as_str()),
1789 )
1790 .primary_label("expected item"))
1791 }
1792 }
1793}
1794
1795impl<'a> Parser<'a> {
1797 #[tracing::instrument(skip_all, fields(parsers = parsers.len()))]
1798 fn first_successful<T>(
1799 &mut self,
1800 parsers: Vec<&dyn Fn(&mut Self) -> Result<Option<T>>>,
1801 ) -> Result<Option<T>> {
1802 for parser in parsers {
1803 match parser(self) {
1804 Ok(Some(val)) => {
1805 event!(Level::INFO, "Parser matched");
1806 return Ok(Some(val));
1807 }
1808 Ok(None) => continue,
1809 Err(e) => return Err(e),
1810 }
1811 }
1812 event!(Level::INFO, "No parser matched");
1813 Ok(None)
1814 }
1815
1816 #[tracing::instrument(level = "debug", skip(self, inner))]
1822 fn surrounded<T>(
1823 &mut self,
1824 start: &TokenKind,
1825 mut inner: impl FnMut(&mut Self) -> Result<T>,
1826 end_kind: &TokenKind,
1827 ) -> Result<(T, Loc<()>)> {
1828 let opener = self.eat(start)?;
1829 let result = inner(self)?;
1830 let end = if let Some(end) = self.peek_and_eat(end_kind)? {
1832 end
1833 } else {
1834 let got = self.eat_unconditional()?;
1835 return Err(Diagnostic::error(
1836 got.loc(),
1837 format!(
1838 "expected closing `{}`, got `{}`",
1839 end_kind.as_str(),
1840 got.kind.as_str()
1841 ),
1842 )
1843 .primary_label(format!("expected `{}`", end_kind.as_str()))
1844 .secondary_label(
1845 opener.loc(),
1846 format!("...to close this `{}`", start.as_str()),
1847 ));
1848 };
1849
1850 Ok((
1851 result,
1852 Loc::new((), lspan(opener.span).merge(lspan(end.span)), self.file_id),
1853 ))
1854 }
1855
1856 pub fn comma_separated<T>(
1857 &mut self,
1858 inner: impl Fn(&mut Self) -> Result<T>,
1859 end_marker: &TokenKind,
1863 ) -> CommaSeparatedResult<Vec<T>> {
1864 self.token_separated(inner, &TokenKind::Comma, vec![end_marker.clone()])
1865 }
1866
1867 #[tracing::instrument(level = "debug", skip(self, inner))]
1871 pub fn token_separated<T>(
1872 &mut self,
1873 inner: impl Fn(&mut Self) -> Result<T>,
1874 separator: &TokenKind,
1875 end_markers: Vec<TokenKind>,
1879 ) -> CommaSeparatedResult<Vec<T>> {
1880 self.parse_stack
1881 .push(ParseStackEntry::Enter("comma_separated".to_string()));
1882 let ret = || -> CommaSeparatedResult<Vec<T>> {
1883 let mut result = vec![];
1884 loop {
1885 if end_markers
1887 .iter()
1888 .map(|m| self.peek_kind(m))
1889 .collect::<Result<Vec<_>>>()?
1890 .into_iter()
1891 .any(|x| x)
1892 {
1893 break;
1894 }
1895 result.push(inner(self)?);
1896
1897 if end_markers
1900 .iter()
1901 .map(|m| self.peek_kind(m))
1902 .collect::<Result<Vec<_>>>()?
1903 .into_iter()
1904 .any(|x| x)
1905 {
1906 break;
1907 } else if self.peek_kind(separator)? {
1908 self.eat_unconditional()?;
1909 } else {
1910 return Err(TokenSeparatedError::UnexpectedToken {
1911 got: self.peek()?,
1912 separator: separator.clone(),
1913 end_tokens: end_markers,
1914 });
1915 }
1916 }
1917 Ok(result)
1918 }();
1919 if let Err(e) = &ret {
1920 self.parse_stack
1921 .push(ParseStackEntry::ExitWithDiagnostic(e.clone().no_context()));
1922 } else {
1923 self.parse_stack.push(ParseStackEntry::Exit);
1924 }
1925
1926 ret
1927 }
1928
1929 fn keyword_peeking_parser_seq<T>(
1930 &mut self,
1931 parsers: Vec<Box<dyn KeywordPeekingParser<T>>>,
1932 support_attributes: bool,
1933 additional_continuations: Vec<TokenKind>,
1934 ) -> Result<Vec<T>> {
1935 let mut result = vec![];
1936 let continuations = parsers
1937 .iter()
1938 .map(|p| p.leading_tokens())
1939 .flatten()
1940 .chain(additional_continuations.iter().cloned())
1941 .collect::<Vec<_>>();
1942 loop {
1943 let inner = self._keyword_peeking_parser_inner(
1944 parsers.as_slice(),
1945 support_attributes,
1946 continuations.as_slice(),
1947 );
1948
1949 match inner {
1950 RecoveryResult::Ok(Some(stmt)) => result.push(stmt),
1951 RecoveryResult::Ok(None) => break,
1952 RecoveryResult::Recovered => continue,
1953 }
1954 }
1955 Ok(result)
1956 }
1957
1958 fn keyword_peeking_parser_or_else_seq<T, F>(
1963 &mut self,
1964 parsers: Vec<Box<dyn KeywordPeekingParser<T>>>,
1965 support_attributes: bool,
1966 additional_continuations: Vec<TokenKind>,
1967 mut other: F,
1968 ) -> Result<Vec<T>>
1969 where
1970 F: FnMut(&mut Self) -> Result<Option<T>>,
1971 {
1972 let mut result = vec![];
1973 let continuations = parsers
1974 .iter()
1975 .map(|p| p.leading_tokens())
1976 .flatten()
1977 .chain(additional_continuations.iter().cloned())
1978 .collect::<Vec<_>>();
1979 loop {
1980 let inner = self._keyword_peeking_parser_inner(
1981 parsers.as_slice(),
1982 support_attributes,
1983 continuations.as_slice(),
1984 );
1985
1986 match inner {
1987 RecoveryResult::Ok(Some(stmt)) => result.push(stmt),
1988 RecoveryResult::Ok(None) => {
1989 if let Some(other_res) = (other)(self)? {
1990 result.push(other_res);
1991 } else {
1992 break;
1993 }
1994 }
1995 RecoveryResult::Recovered => continue,
1996 }
1997 }
1998 Ok(result)
1999 }
2000
2001 fn _keyword_peeking_parser_inner<T>(
2002 &mut self,
2003 parsers: &[Box<dyn KeywordPeekingParser<T>>],
2004 support_attributes: bool,
2005 continuations: &[TokenKind],
2006 ) -> RecoveryResult<Option<T>> {
2007 self.with_recovery(
2008 |s| {
2009 let attributes = if support_attributes {
2010 s.attributes()?
2011 } else {
2012 AttributeList::empty()
2013 };
2014
2015 let next = s.peek()?;
2016 let mut result = None;
2017 for parser in parsers {
2018 if parser.leading_tokens().contains(&next.kind) {
2019 result = Some(parser.parse(s, &attributes)?)
2020 }
2021 }
2022 Ok(result)
2023 },
2024 Vec::from(continuations),
2025 )
2026 }
2027
2028 pub fn with_recovery<T>(
2029 &mut self,
2030 inner: impl Fn(&mut Self) -> Result<T>,
2031 continuations: Vec<TokenKind>,
2032 ) -> RecoveryResult<T> {
2033 self.recovering_tokens.push(continuations);
2034 let result = match inner(self) {
2035 Ok(result) => RecoveryResult::Ok(result),
2036 Err(e) => {
2037 self.diags.errors.push(e);
2038
2039 while let Ok(tok) = self.peek() {
2042 if self
2043 .recovering_tokens
2044 .iter()
2045 .rev()
2046 .any(|list| list.iter().any(|t| t == &tok.kind))
2047 {
2048 break;
2049 }
2050 self.eat_unconditional().unwrap();
2052 }
2053
2054 RecoveryResult::Recovered
2055 }
2056 };
2057 self.recovering_tokens.pop();
2058 result
2059 }
2060}
2061
2062impl<'a> Parser<'a> {
2064 fn eat(&mut self, expected: &TokenKind) -> Result<Token> {
2065 self.parse_stack
2066 .push(ParseStackEntry::EatingExpected(expected.clone()));
2067 let next = self.eat_unconditional()?;
2069 if &next.kind == expected {
2070 Ok(next)
2071 } else if expected == &TokenKind::Gt && next.kind == TokenKind::RightShift {
2072 self.peeked = Some(Token {
2073 kind: TokenKind::Gt,
2074 span: next.span.end..next.span.end,
2075 file_id: next.file_id,
2076 });
2077 Ok(Token {
2078 kind: TokenKind::Gt,
2079 span: next.span.start..next.span.start,
2080 file_id: next.file_id,
2081 })
2082 } else if expected == &TokenKind::Gt && next.kind == TokenKind::ArithmeticRightShift {
2083 self.peeked = Some(Token {
2084 kind: TokenKind::RightShift,
2085 span: next.span.start + 1..next.span.end,
2086 file_id: next.file_id,
2087 });
2088 Ok(Token {
2089 kind: TokenKind::Gt,
2090 span: next.span.start..next.span.start,
2091 file_id: next.file_id,
2092 })
2093 } else {
2094 Err(Diagnostic::from(UnexpectedToken {
2095 got: next,
2096 expected: vec![expected.as_str()],
2097 }))
2098 }
2099 }
2100
2101 fn eat_cond(
2102 &mut self,
2103 condition: impl Fn(&TokenKind) -> bool,
2104 expected_description: &'static str,
2105 ) -> Result<Token> {
2106 let next = self.eat_unconditional()?;
2108
2109 if !condition(&next.kind) {
2111 Err(Diagnostic::from(UnexpectedToken {
2112 got: next,
2113 expected: vec![expected_description],
2114 }))
2115 } else {
2116 Ok(next)
2117 }
2118 }
2119
2120 fn eat_unconditional(&mut self) -> Result<Token> {
2121 let food = self
2122 .peeked
2123 .take()
2124 .map(Ok)
2125 .unwrap_or_else(|| self.next_token())?;
2126
2127 self.parse_stack.push(ParseStackEntry::Ate(food.clone()));
2128 self.last_token = Some(food.clone());
2129 Ok(food)
2130 }
2131
2132 fn peek_and_eat(&mut self, kind: &TokenKind) -> Result<Option<Token>> {
2138 if self.peek_kind(kind)? {
2141 Ok(Some(self.eat(kind)?))
2142 } else {
2143 Ok(None)
2144 }
2145 }
2146
2147 pub fn peek(&mut self) -> Result<Token> {
2148 if let Some(peeked) = self.peeked.clone() {
2149 Ok(peeked)
2150 } else {
2151 let result = match self.next_token() {
2152 Ok(token) => token,
2153 Err(e) => return Err(e),
2154 };
2155 self.peeked = Some(result.clone());
2156
2157 Ok(result)
2158 }
2159 }
2160
2161 fn peek_kind(&mut self, expected: &TokenKind) -> Result<bool> {
2162 let mut result = self.peek_cond_no_tracing(|kind| kind == expected)?;
2163 if expected == &TokenKind::Gt {
2164 result |= self.peek_cond_no_tracing(|kind| kind == &TokenKind::RightShift)?
2165 | self.peek_cond_no_tracing(|kind| kind == &TokenKind::ArithmeticRightShift)?
2166 }
2167 self.parse_stack
2168 .push(ParseStackEntry::PeekingFor(expected.clone(), result));
2169 Ok(result)
2170 }
2171
2172 fn peek_cond(&mut self, cond: impl Fn(&TokenKind) -> bool, msg: &str) -> Result<bool> {
2176 let result = self.peek_cond_no_tracing(cond)?;
2177 self.parse_stack.push(ParseStackEntry::PeekingWithCondition(
2178 msg.to_string(),
2179 result,
2180 ));
2181 Ok(result)
2182 }
2183
2184 fn peek_cond_no_tracing(&mut self, cond: impl Fn(&TokenKind) -> bool) -> Result<bool> {
2185 self.peek().map(|token| cond(&token.kind))
2186 }
2187
2188 fn next_token(&mut self) -> Result<Token> {
2189 let out = match self.lex.next() {
2190 Some(Ok(k)) => Ok(Token::new(k, &self.lex, self.file_id)),
2191 Some(Err(_)) => Err(Diagnostic::error(
2192 Loc::new((), lspan(self.lex.span()), self.file_id),
2193 "Lexer error, unexpected symbol",
2194 )),
2195 None => Ok(match &self.last_token {
2196 Some(last) => Token {
2197 kind: TokenKind::Eof,
2198 span: last.span.end..last.span.end,
2199 file_id: last.file_id,
2200 },
2201 None => Token {
2202 kind: TokenKind::Eof,
2203 span: logos::Span { start: 0, end: 0 },
2204 file_id: self.file_id,
2205 },
2206 }),
2207 }?;
2208
2209 match out.kind {
2210 TokenKind::BlockCommentStart => loop {
2211 let next = self.next_token()?;
2212 match next.kind {
2213 TokenKind::BlockCommentEnd => break self.next_token(),
2214 TokenKind::Eof => {
2215 break Err(Diagnostic::error(next, "Unterminated block comment")
2216 .primary_label("Expected */")
2217 .secondary_label(out, "to close this block comment"))
2218 }
2219 _ => {}
2220 }
2221 },
2222 _ => Ok(out),
2223 }
2224 }
2225}
2226
2227impl<'a> Parser<'a> {
2228 fn set_item_context(&mut self, context: Loc<UnitKind>) -> Result<()> {
2229 if let Some(prev) = &self.unit_context {
2230 Err(Diagnostic::bug(
2231 context.loc(),
2232 "overwriting previously uncleared item context",
2233 )
2234 .primary_label("new context set because of this")
2235 .secondary_label(prev.loc(), "previous context set here"))
2236 } else {
2237 self.unit_context = Some(context);
2238 Ok(())
2239 }
2240 }
2241
2242 fn clear_item_context(&mut self) {
2243 self.unit_context = None
2244 }
2245
2246 #[cfg(test)]
2247 fn set_parsing_entity(&mut self) {
2248 self.set_item_context(UnitKind::Entity.nowhere()).unwrap()
2249 }
2250}
2251
2252trait KeywordPeekingParser<T> {
2253 fn leading_tokens(&self) -> Vec<TokenKind>;
2254 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<T>;
2255}
2256
2257trait SizedKeywordPeekingParser<T>: Sized + KeywordPeekingParser<T> {
2258 fn map<F, O>(self, mapper: F) -> MappingParser<Self, F, T, O>
2259 where
2260 F: Fn(T) -> Result<O>,
2261 {
2262 MappingParser {
2263 inner: Box::new(self),
2264 mapper: Box::new(mapper),
2265 _phantoms: Default::default(),
2266 }
2267 }
2268
2269 fn then<F>(self, then: F) -> ThenParser<Self, F, T>
2270 where
2271 F: Fn(T, &mut Parser) -> Result<T>,
2272 {
2273 ThenParser {
2274 inner: Box::new(self),
2275 then: Box::new(then),
2276 _phantoms: Default::default(),
2277 }
2278 }
2279}
2280impl<TOuter, TInner> SizedKeywordPeekingParser<TInner> for TOuter where
2281 TOuter: KeywordPeekingParser<TInner> + Sized
2282{
2283}
2284
2285struct MappingParser<Inner, Mapper, I, T>
2286where
2287 Inner: SizedKeywordPeekingParser<I> + ?Sized,
2288 Mapper: Fn(I) -> Result<T>,
2289{
2290 inner: Box<Inner>,
2291 mapper: Box<Mapper>,
2292 _phantoms: (PhantomData<I>, PhantomData<T>),
2293}
2294
2295impl<Inner, Mapper, I, T> KeywordPeekingParser<T> for MappingParser<Inner, Mapper, I, T>
2296where
2297 Inner: SizedKeywordPeekingParser<I> + ?Sized,
2298 Mapper: Fn(I) -> Result<T>,
2299{
2300 fn leading_tokens(&self) -> Vec<TokenKind> {
2301 self.inner.leading_tokens()
2302 }
2303
2304 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<T> {
2305 (self.mapper)(self.inner.parse(parser, attributes)?)
2306 }
2307}
2308
2309struct ThenParser<Inner, After, T>
2315where
2316 Inner: SizedKeywordPeekingParser<T> + ?Sized,
2317 After: Fn(T, &mut Parser) -> Result<T>,
2318{
2319 inner: Box<Inner>,
2320 then: Box<After>,
2321 _phantoms: PhantomData<T>,
2322}
2323
2324impl<Inner, After, T> KeywordPeekingParser<T> for ThenParser<Inner, After, T>
2325where
2326 Inner: SizedKeywordPeekingParser<T> + ?Sized,
2327 After: Fn(T, &mut Parser) -> Result<T>,
2328{
2329 fn leading_tokens(&self) -> Vec<TokenKind> {
2330 self.inner.leading_tokens()
2331 }
2332
2333 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<T> {
2334 let inner = self.inner.parse(parser, attributes)?;
2335 (self.then)(inner, parser)
2336 }
2337}
2338
2339#[derive(Debug)]
2340pub enum RecoveryResult<T> {
2341 Ok(T),
2342 Recovered,
2343}
2344
2345#[local_impl]
2346impl<T> OptionExt for Option<T> {
2347 fn or_error(
2348 self,
2349 parser: &mut Parser,
2350 err: impl Fn(&mut Parser) -> Result<Diagnostic>,
2351 ) -> Result<T> {
2352 match self {
2353 Some(val) => Ok(val),
2354 None => Err(err(parser)?),
2355 }
2356 }
2357}
2358
2359#[derive(Clone)]
2360pub enum ParseStackEntry {
2361 Enter(String),
2362 Ate(Token),
2363 PeekingWithCondition(String, bool),
2364 PeekingFor(TokenKind, bool),
2365 EatingExpected(TokenKind),
2366 Exit,
2367 ExitWithDiagnostic(Diagnostic),
2368}
2369pub fn format_parse_stack(stack: &[ParseStackEntry]) -> String {
2370 let mut result = String::new();
2371 let mut indent_amount = 0;
2372
2373 for entry in stack {
2374 let mut next_indent_amount = indent_amount;
2375 let message = match entry {
2376 ParseStackEntry::Enter(function) => {
2377 next_indent_amount += 1;
2378 format!("{} `{}`", "trying".white(), function.blue())
2379 }
2380 ParseStackEntry::Ate(token) => format!(
2381 "{} '{}'",
2382 "Eating".bright_yellow(),
2383 token.kind.as_str().bright_purple()
2384 ),
2385 ParseStackEntry::PeekingFor(kind, success) => format!(
2386 "{} {} {}",
2387 "peeking for".white(),
2388 kind.as_str().bright_blue(),
2389 if *success {
2390 "✓".green()
2391 } else {
2392 "𐄂".red()
2393 }
2394 ),
2395 ParseStackEntry::PeekingWithCondition(needle, success) => format!(
2396 "{} {} {}",
2397 "peeking conditionally for ".white(),
2398 needle.bright_blue(),
2399 if *success {
2400 "✓".green()
2401 } else {
2402 "𐄂".red()
2403 }
2404 ),
2405 ParseStackEntry::EatingExpected(kind) => {
2406 format!(
2407 "{} {}",
2408 "eating expected".purple(),
2409 kind.as_str().bright_purple()
2410 )
2411 }
2412 ParseStackEntry::Exit => {
2413 next_indent_amount -= 1;
2414 String::new()
2415 }
2416 ParseStackEntry::ExitWithDiagnostic(_diag) => {
2417 next_indent_amount -= 1;
2418 "Giving up".bright_red().to_string()
2419 }
2420 };
2421 if let ParseStackEntry::Exit = entry {
2422 } else {
2423 for _ in 0..indent_amount {
2424 result += "| ";
2425 }
2426 result += &message;
2427 result += "\n"
2428 }
2429 indent_amount = next_indent_amount;
2430 }
2431 result
2432}
2433
2434#[cfg(test)]
2435mod tests {
2436 use spade_ast as ast;
2437 use spade_ast::testutil::{ast_ident, ast_path};
2438 use spade_ast::*;
2439 use spade_common::num_ext::InfallibleToBigInt;
2440
2441 use crate::lexer::TokenKind;
2442 use crate::*;
2443
2444 use logos::Logos;
2445
2446 use spade_common::location_info::WithLocation;
2447
2448 #[macro_export]
2449 macro_rules! check_parse {
2450 ($string:expr , $method:ident$(($($arg:expr),*))?, $expected:expr$(, $run_on_parser:expr)?) => {
2451 let mut parser = Parser::new(TokenKind::lexer($string), 0);
2452
2453 $($run_on_parser(&mut parser);)?
2454
2455 let result = parser.$method($($($arg),*)?);
2456 let expected: Result<_> = $expected;
2458
2459 if result != expected {
2460 println!("Parser state:\n{}", format_parse_stack(&parser.parse_stack));
2461 panic!(
2462 "\n\n {}: {:?}\n{}: {:?}",
2463 "Got".red(),
2464 result,
2465 "Expected".green(),
2466 expected
2467 );
2468 };
2469 };
2470 }
2471
2472 #[test]
2473 fn parsing_identifier_works() {
2474 check_parse!("abc123_", identifier, Ok(ast_ident("abc123_")));
2475 }
2476
2477 #[test]
2478 fn parsing_paths_works() {
2479 let expected = Path(vec![ast_ident("path"), ast_ident("to"), ast_ident("thing")]).nowhere();
2480 check_parse!("path::to::thing", path, Ok(expected));
2481 }
2482
2483 #[test]
2484 fn literals_are_expressions() {
2485 check_parse!(
2486 "123",
2487 expression,
2488 Ok(Expression::int_literal_signed(123).nowhere())
2489 );
2490 }
2491
2492 #[test]
2493 fn size_types_work() {
2494 let expected = TypeSpec::Named(
2495 ast_path("uint"),
2496 Some(vec![TypeExpression::Integer(10u32.to_bigint()).nowhere()].nowhere()),
2497 )
2498 .nowhere();
2499 check_parse!("uint<10>", type_spec, Ok(expected));
2500 }
2501
2502 #[test]
2503 fn nested_generics_work() {
2504 let code = "Option<int<5>>";
2505
2506 let expected = TypeSpec::Named(
2507 ast_path("Option"),
2508 Some(
2509 vec![TypeExpression::TypeSpec(Box::new(
2510 TypeSpec::Named(
2511 ast_path("int"),
2512 Some(vec![TypeExpression::Integer(5u32.to_bigint()).nowhere()].nowhere()),
2513 )
2514 .nowhere(),
2515 ))
2516 .nowhere()]
2517 .nowhere(),
2518 ),
2519 )
2520 .nowhere();
2521
2522 check_parse!(code, type_spec, Ok(expected));
2523 }
2524
2525 #[test]
2526 fn module_body_parsing_works() {
2527 let code = include_str!("../parser_test_code/multiple_entities.sp");
2528
2529 let e1 = Unit {
2530 head: UnitHead {
2531 extern_token: None,
2532 attributes: AttributeList::empty(),
2533 unit_kind: UnitKind::Entity.nowhere(),
2534 name: Identifier("e1".to_string()).nowhere(),
2535 inputs: aparams![],
2536 output_type: None,
2537 type_params: None,
2538 where_clauses: vec![],
2539 },
2540 body: Some(
2541 Expression::Block(Box::new(Block {
2542 statements: vec![],
2543 result: Some(Expression::int_literal_signed(0).nowhere()),
2544 }))
2545 .nowhere(),
2546 ),
2547 }
2548 .nowhere();
2549
2550 let e2 = Unit {
2551 head: UnitHead {
2552 extern_token: None,
2553 attributes: AttributeList::empty(),
2554 unit_kind: UnitKind::Entity.nowhere(),
2555 name: Identifier("e2".to_string()).nowhere(),
2556 inputs: aparams![],
2557 output_type: None,
2558 type_params: None,
2559 where_clauses: vec![],
2560 },
2561 body: Some(
2562 Expression::Block(Box::new(Block {
2563 statements: vec![],
2564 result: Some(Expression::int_literal_signed(1).nowhere()),
2565 }))
2566 .nowhere(),
2567 ),
2568 }
2569 .nowhere();
2570
2571 let expected = ModuleBody {
2572 members: vec![Item::Unit(e1), Item::Unit(e2)],
2573 documentation: vec![],
2574 };
2575
2576 check_parse!(code, module_body, Ok(expected));
2577 }
2578
2579 #[test]
2580 fn dec_int_literals_work() {
2581 let code = "1";
2582 let expected = IntLiteral::unsized_(1).nowhere();
2583
2584 check_parse!(code, int_literal, Ok(Some(expected)));
2585 }
2586 #[test]
2587 fn dec_negative_int_literals_work() {
2588 let code = "-1";
2589 let expected = IntLiteral::unsized_(-1).nowhere();
2590
2591 check_parse!(code, int_literal, Ok(Some(expected)));
2592 }
2593 #[test]
2594 fn hex_int_literals_work() {
2595 let code = "0xff";
2596 let expected = IntLiteral::unsized_(255).nowhere();
2597
2598 check_parse!(code, int_literal, Ok(Some(expected)));
2599 }
2600 #[test]
2601 fn bin_int_literals_work() {
2602 let code = "0b101";
2603 let expected = IntLiteral::unsized_(5).nowhere();
2604
2605 check_parse!(code, int_literal, Ok(Some(expected)));
2606 }
2607
2608 #[test]
2609 fn type_spec_with_multiple_generics_works() {
2610 let code = "A<X, Y>";
2611
2612 let expected = TypeSpec::Named(
2613 ast_path("A"),
2614 Some(
2615 vec![
2616 TypeExpression::TypeSpec(Box::new(
2617 TypeSpec::Named(ast_path("X"), None).nowhere(),
2618 ))
2619 .nowhere(),
2620 TypeExpression::TypeSpec(Box::new(
2621 TypeSpec::Named(ast_path("Y"), None).nowhere(),
2622 ))
2623 .nowhere(),
2624 ]
2625 .nowhere(),
2626 ),
2627 )
2628 .nowhere();
2629
2630 check_parse!(code, type_spec, Ok(expected));
2631 }
2632
2633 #[test]
2634 fn entity_instantiation() {
2635 let code = "inst some_entity(x, y, z)";
2636
2637 let expected = Expression::Call {
2638 kind: CallKind::Entity(().nowhere()),
2639 callee: ast_path("some_entity"),
2640 args: ArgumentList::Positional(vec![
2641 Expression::Identifier(ast_path("x")).nowhere(),
2642 Expression::Identifier(ast_path("y")).nowhere(),
2643 Expression::Identifier(ast_path("z")).nowhere(),
2644 ])
2645 .nowhere(),
2646 turbofish: None,
2647 }
2648 .nowhere();
2649
2650 check_parse!(code, expression, Ok(expected), Parser::set_parsing_entity);
2651 }
2652
2653 #[test]
2654 fn named_args_work() {
2655 let code = "x: a";
2656
2657 let expected = NamedArgument::Full(
2658 ast_ident("x"),
2659 Expression::Identifier(ast_path("a")).nowhere(),
2660 )
2661 .nowhere();
2662
2663 check_parse!(code, named_argument, Ok(expected));
2664 }
2665
2666 #[test]
2667 fn named_capture_shorthand_works() {
2668 let code = "x";
2669
2670 let expected = NamedArgument::Short(ast_ident("x")).nowhere();
2671
2672 check_parse!(code, named_argument, Ok(expected));
2673 }
2674
2675 #[test]
2676 fn tuple_patterns_work() {
2677 let code = "(x, y)";
2678
2679 let expected = Pattern::Tuple(vec![Pattern::name("x"), Pattern::name("y")]).nowhere();
2680
2681 check_parse!(code, pattern, Ok(expected));
2682 }
2683
2684 #[test]
2685 fn integer_patterns_work() {
2686 let code = "1";
2687
2688 let expected = Pattern::integer(1).nowhere();
2689
2690 check_parse!(code, pattern, Ok(expected));
2691 }
2692
2693 #[test]
2694 fn hex_integer_patterns_work() {
2695 let code = "0xff";
2696
2697 let expected = Pattern::integer(255).nowhere();
2698
2699 check_parse!(code, pattern, Ok(expected));
2700 }
2701
2702 #[test]
2703 fn bin_integer_patterns_work() {
2704 let code = "0b101";
2705
2706 let expected = Pattern::integer(5).nowhere();
2707
2708 check_parse!(code, pattern, Ok(expected));
2709 }
2710
2711 #[test]
2712 fn bool_patterns_work() {
2713 let code = "true";
2714
2715 let expected = Pattern::Bool(true).nowhere();
2716
2717 check_parse!(code, pattern, Ok(expected));
2718 }
2719
2720 #[test]
2721 fn positional_type_patterns_work() {
2722 let code = "SomeType(x, y)";
2723
2724 let expected = Pattern::Type(
2725 ast_path("SomeType"),
2726 ArgumentPattern::Positional(vec![Pattern::name("x"), Pattern::name("y")]).nowhere(),
2727 )
2728 .nowhere();
2729
2730 check_parse!(code, pattern, Ok(expected));
2731 }
2732
2733 #[test]
2734 fn named_type_patterns_work() {
2735 let code = "SomeType$(x: a, y)";
2736
2737 let expected = Pattern::Type(
2738 ast_path("SomeType"),
2739 ArgumentPattern::Named(vec![
2740 (ast_ident("x"), Some(Pattern::name("a"))),
2741 (ast_ident("y"), None),
2742 ])
2743 .nowhere(),
2744 )
2745 .nowhere();
2746
2747 check_parse!(code, pattern, Ok(expected));
2748 }
2749
2750 #[test]
2751 fn modules_can_be_empty() {
2752 let code = r#"mod X {}"#;
2753
2754 let expected = ModuleBody {
2755 members: vec![Item::Module(
2756 Module {
2757 name: ast_ident("X"),
2758 body: ModuleBody {
2759 members: vec![],
2760 documentation: vec![],
2761 }
2762 .nowhere(),
2763 }
2764 .nowhere(),
2765 )],
2766 documentation: vec![],
2767 };
2768
2769 check_parse!(code, module_body, Ok(expected));
2770 }
2771
2772 #[test]
2773 fn modules_containing_items_work() {
2774 let code = r#"mod X {mod Y {}}"#;
2775
2776 let expected = ModuleBody {
2777 members: vec![Item::Module(
2778 Module {
2779 name: ast_ident("X"),
2780 body: ModuleBody {
2781 members: vec![Item::Module(
2782 Module {
2783 name: ast_ident("Y"),
2784 body: ModuleBody {
2785 members: vec![],
2786 documentation: vec![],
2787 }
2788 .nowhere(),
2789 }
2790 .nowhere(),
2791 )],
2792 documentation: vec![],
2793 }
2794 .nowhere(),
2795 }
2796 .nowhere(),
2797 )],
2798 documentation: vec![],
2799 };
2800
2801 check_parse!(code, module_body, Ok(expected));
2802 }
2803}