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