1use crate::ast;
49use crate::lexer::token::*;
50use crate::parser::core::*;
51use crate::parser::TokenStream;
52use moore_common::errors::*;
53use moore_common::name::*;
54use moore_common::source::*;
55use std::fmt::Display;
56
57pub trait Parser: TokenStream<Token> {}
58impl<T> Parser for T where T: TokenStream<Token> {}
59
60#[derive(Debug)]
61pub struct Recovered;
62#[derive(Debug)]
63pub struct Reported;
64
65pub type RecoveredResult<T> = Result<T, Recovered>;
66pub type ReportedResult<T> = Result<T, Reported>;
67
68impl From<Recovered> for Reported {
69 fn from(_: Recovered) -> Reported {
70 Reported
71 }
72}
73
74macro_rules! unimp {
75 ($parser:expr, $name:expr) => {{
76 let q = $parser.peek(0).span;
77 $parser.emit(DiagBuilder2::error(format!("{} not yet implemented", $name)).span(q));
78 return Err(Reported);
79 }};
80}
81
82pub fn parse_design_file<P: Parser>(p: &mut P) -> Vec<ast::DesignUnit> {
88 let mut units = Vec::new();
89 while !p.is_fatal() && p.peek(0).value != Eof {
90 match parse_design_unit(p) {
91 Ok(unit) => units.push(unit),
92 Err(Recovered) => (),
93 }
94 }
95 units
96}
97
98pub fn parse_design_unit<P: Parser>(p: &mut P) -> RecoveredResult<ast::DesignUnit> {
112 let context = repeat(p, try_context_item)?;
113 let Spanned {
114 value: tkn,
115 span: sp,
116 } = p.peek(0);
117 match match tkn {
118 Keyword(Kw::Entity) => parse_entity_decl(p).map(|d| ast::DesignUnitData::EntityDecl(d)),
119 Keyword(Kw::Configuration) => parse_config_decl(p).map(|d| ast::DesignUnitData::CfgDecl(d)),
120 Keyword(Kw::Package) => {
121 if p.peek(1).value == Keyword(Kw::Body) {
122 parse_package_body(p).map(|d| ast::DesignUnitData::PkgBody(d))
123 } else {
124 parse_package_decl(p).map(|d| ast::DesignUnitData::PkgDecl(d))
125 }
126 }
127 Keyword(Kw::Context) => parse_context_decl(p).map(|d| ast::DesignUnitData::CtxDecl(d)),
128 Keyword(Kw::Architecture) => parse_arch_body(p).map(|d| ast::DesignUnitData::ArchBody(d)),
129 tkn => {
130 p.emit(
131 DiagBuilder2::error(format!(
132 "Expected a primary or secondary unit, instead found {}",
133 tkn
134 ))
135 .span(sp)
136 .add_note("`entity`, `configuration`, `package`, and `context` are primary units")
137 .add_note("`architecture` and `package body` are secondary units"),
138 );
139 Err(Reported)
140 }
141 } {
142 Ok(x) => Ok(ast::DesignUnit {
143 id: Default::default(),
144 ctx: context,
145 data: x,
146 }),
147 Err(Reported) => {
148 recover(p, &[Keyword(Kw::End)], true);
149 recover(p, &[Semicolon], true);
150 recover(
151 p,
152 &[
153 Keyword(Kw::Entity),
154 Keyword(Kw::Configuration),
155 Keyword(Kw::Package),
156 Keyword(Kw::Context),
157 Keyword(Kw::Architecture),
158 ],
159 false,
160 );
161 Err(Recovered)
162 }
163 }
164}
165
166pub fn try_context_item<P: Parser>(p: &mut P) -> RecoveredResult<Option<ast::CtxItem>> {
172 recovered(p, &[Semicolon], true, |p| {
173 let tkn = p.peek(0).value;
174 Ok(match tkn {
175 Keyword(Kw::Library) => Some(ast::CtxItem::LibClause(parse_library_clause(p)?)),
176 Keyword(Kw::Use) => Some(ast::CtxItem::UseClause(parse_use_clause(p)?)),
177 Keyword(Kw::Context) => {
178 if p.peek(2).value != Keyword(Kw::Is) {
179 Some(ast::CtxItem::CtxRef(parse_context_ref(p)?))
180 } else {
181 None
182 }
183 }
184 _ => None,
185 })
186 })
187}
188
189pub fn parse_library_clause<P: Parser>(p: &mut P) -> ReportedResult<Spanned<Vec<ast::Ident>>> {
195 let mut span = p.peek(0).span;
196 require(p, Keyword(Kw::Library))?;
197 let names = separated_nonempty(p, Comma, Semicolon, "library name", |p| {
198 parse_ident(p, "library name")
199 })?;
200 require(p, Semicolon)?;
201 span.expand(p.last_span());
202 Ok(Spanned::new(
203 names.into_iter().map(|n| ast::Ident::from(n)).collect(),
204 span,
205 ))
206}
207
208pub fn parse_use_clause<P: Parser>(p: &mut P) -> ReportedResult<Spanned<Vec<ast::CompoundName>>> {
214 let mut span = p.peek(0).span;
215 require(p, Keyword(Kw::Use))?;
216 let names = separated_nonempty(p, Comma, Semicolon, "selected name", parse_name)?;
217 require(p, Semicolon)?;
218 span.expand(p.last_span());
219 Ok(Spanned::new(names, span))
220}
221
222pub fn parse_context_ref<P: Parser>(p: &mut P) -> ReportedResult<Spanned<Vec<ast::CompoundName>>> {
223 let mut span = p.peek(0).span;
224 require(p, Keyword(Kw::Context))?;
225 let names = separated_nonempty(p, Comma, Semicolon, "selected name", parse_name)?;
226 require(p, Semicolon)?;
227 span.expand(p.last_span());
228 Ok(Spanned::new(names, span))
229}
230
231pub fn parse_name<P: Parser>(p: &mut P) -> ReportedResult<ast::CompoundName> {
233 let q = p.peek(0).span;
234 match try_name(p)? {
235 Some(n) => Ok(n),
236 None => {
237 p.emit(DiagBuilder2::error("Expected a name").span(q.begin()));
238 Err(Reported)
239 }
240 }
241}
242
243pub fn try_name<P: Parser>(p: &mut P) -> ReportedResult<Option<ast::CompoundName>> {
245 let primary = match try_primary_name(p) {
247 Some(pn) => pn,
248 None => return Ok(None),
249 };
250
251 let name = ast::CompoundName {
253 id: Default::default(),
254 span: primary.span,
255 primary: primary,
256 parts: Vec::new(),
257 };
258
259 parse_name_suffix(p, name).map(|x| Some(x))
261}
262
263pub fn try_primary_name<P: Parser>(p: &mut P) -> Option<ast::PrimaryName> {
269 let Spanned { value: tkn, span } = p.peek(0);
270 let kind = match tkn {
271 Ident(n) => ast::PrimaryNameKind::Ident(n),
272 Lit(Literal::Char(c)) => ast::PrimaryNameKind::Char(c),
273 Lit(Literal::String(s)) => ast::PrimaryNameKind::String(s),
274 _ => return None,
275 };
276 p.bump();
277 return Some(ast::PrimaryName {
278 id: Default::default(),
279 span: span,
280 kind: kind,
281 });
282}
283
284pub fn parse_name_suffix<P: Parser>(
294 p: &mut P,
295 mut name: ast::CompoundName,
296) -> ReportedResult<ast::CompoundName> {
297 if accept(p, Period) {
299 let suffix = {
301 if let Some(pn) = try_primary_name(p) {
302 ast::NamePart::Select(pn)
303 } else {
304 if accept(p, Keyword(Kw::All)) {
306 ast::NamePart::SelectAll(p.last_span())
307 } else {
308 let Spanned { value: wrong, span } = p.peek(0);
309 p.emit(
310 DiagBuilder2::error(
311 "Expected identifier, character literal, operator symbol, or `all` \
312 after `.`",
313 )
314 .span(span)
315 .add_note("see IEEE 1076-2008 section 8.3"),
316 );
317 return Err(Reported);
318 }
319 }
320 };
321
322 name.span.expand(p.last_span());
324 name.parts.push(suffix);
325 return parse_name_suffix(p, name);
326 }
327
328 if let Some(sig) = try_flanked(p, Brack, parse_signature)? {
330 name.span.expand(p.last_span());
331 name.parts.push(ast::NamePart::Signature(sig));
332 return parse_name_suffix(p, name);
333 }
334
335 if p.peek(0).value == Apostrophe && p.peek(1).value != OpenDelim(Paren) {
337 require(p, Apostrophe)?;
338
339 let attr = if accept(p, Keyword(Kw::Range)) {
345 Spanned::new(get_name_table().intern("range", false), p.last_span())
346 } else {
347 parse_ident(p, "attribute name")?
348 };
349
350 name.span.expand(p.last_span());
351 name.parts.push(ast::NamePart::Attribute(attr.into()));
352 return parse_name_suffix(p, name);
353 }
354
355 if let Some(al) = try_paren_expr(p)? {
357 name.span.expand(p.last_span());
358 name.parts.push(ast::NamePart::Call(al));
359 return parse_name_suffix(p, name);
360 }
361
362 if accept(p, Keyword(Kw::Range)) {
364 let expr = parse_expr_prec(p, ExprPrec::Range)?;
365 name.parts.push(ast::NamePart::Range(Box::new(expr)));
366 name.span.expand(p.last_span());
367 return parse_name_suffix(p, name);
368 }
369
370 Ok(name)
373}
374
375fn parse_optional_matching_ident<P, M1, M2, T>(p: &mut P, name: T, msg: M1, sec: M2)
378where
379 P: Parser,
380 M1: Display,
381 M2: Display,
382 T: Into<Option<Spanned<Name>>>,
383{
384 if let Some(n) = try_ident(p) {
385 if let Some(name) = name.into() {
386 if n.value != name.value {
387 p.emit(
388 DiagBuilder2::warning(format!(
389 "`{}` does not match {} name `{}`",
390 n.value, msg, name.value
391 ))
392 .span(n.span)
393 .add_note(format!("see IEEE 1076-2008 {}", sec)),
394 );
395 }
396 } else {
397 p.emit(
398 DiagBuilder2::warning(format!(
399 "Label `{}` is given at the end of {}, but not at the beginning",
400 n.value, msg
401 ))
402 .span(n.span)
403 .add_note(format!("see IEEE 1076-2008 {}", sec)),
404 );
405 }
406 }
407}
408
409pub fn parse_context_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::CtxDecl> {
418 let mut span = p.peek(0).span;
419 require(p, Keyword(Kw::Context))?;
420 let name = parse_ident(p, "context name")?;
421 require(p, Keyword(Kw::Is))?;
422 let items = repeat(p, try_context_item)?;
423 require(p, Keyword(Kw::End))?;
424 accept(p, Keyword(Kw::Context));
425 parse_optional_matching_ident(p, name, "context", "section 13.3");
426 require(p, Semicolon)?;
427 span.expand(p.last_span());
428 Ok(ast::CtxDecl {
429 id: Default::default(),
430 span: span,
431 name: name,
432 items: items,
433 })
434}
435
436pub fn parse_entity_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::EntityDecl> {
447 let mut span = p.peek(0).span;
448
449 require(p, Keyword(Kw::Entity))?;
451 let name = parse_ident(p, "entity name")?;
452 require(p, Keyword(Kw::Is))?;
453
454 let decl_items = repeat(p, try_decl_item)?;
456
457 let stmts = if accept(p, Keyword(Kw::Begin)) {
459 Some(repeat_until(p, Keyword(Kw::End), parse_stmt)?)
460 } else {
461 None
462 };
463
464 require(p, Keyword(Kw::End))?;
466 accept(p, Keyword(Kw::Entity));
467 parse_optional_matching_ident(p, name, "entity", "section 3.2.1");
468 require(p, Semicolon)?;
469 span.expand(p.last_span());
470 Ok(ast::EntityDecl {
471 id: Default::default(),
472 span: span,
473 name: name,
474 decls: decl_items,
475 stmts: stmts,
476 })
477}
478
479pub fn parse_config_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::CfgDecl> {
488 let mut span = p.peek(0).span;
489
490 require(p, Keyword(Kw::Configuration))?;
492 let name = parse_ident(p, "configuration name")?;
493 require(p, Keyword(Kw::Of))?;
494 let target = parse_name(p)?;
495 require(p, Keyword(Kw::Is))?;
496
497 let decl_items = repeat_until(p, Keyword(Kw::End), parse_block_comp_decl_item)?;
499
500 require(p, Keyword(Kw::End))?;
502 accept(p, Keyword(Kw::Configuration));
503 parse_optional_matching_ident(p, name, "configuration", "section 3.4");
504 require(p, Semicolon)?;
505 span.expand(p.last_span());
506 Ok(ast::CfgDecl {
507 id: Default::default(),
508 span: span,
509 name: name,
510 target: target,
511 decls: decl_items,
512 })
513}
514
515pub fn parse_arch_body<P: Parser>(p: &mut P) -> ReportedResult<ast::ArchBody> {
526 let mut span = p.peek(0).span;
527
528 require(p, Keyword(Kw::Architecture))?;
530 let name = parse_ident(p, "architecture name")?;
531 require(p, Keyword(Kw::Of))?;
532 let target = parse_name(p)?;
533 require(p, Keyword(Kw::Is))?;
534
535 let decl_items = repeat(p, try_decl_item)?;
537 require(p, Keyword(Kw::Begin))?;
538 let stmts = repeat_until(p, Keyword(Kw::End), parse_stmt)?;
539
540 require(p, Keyword(Kw::End))?;
542 accept(p, Keyword(Kw::Architecture));
543 parse_optional_matching_ident(p, name, "architecture", "section 3.3");
544 require(p, Semicolon)?;
545 span.expand(p.last_span());
546 Ok(ast::ArchBody {
547 id: Default::default(),
548 span: span,
549 name: name,
550 target: target,
551 decls: decl_items,
552 stmts: stmts,
553 })
554}
555
556pub fn try_generic_clause<P: Parser>(
562 p: &mut P,
563) -> ReportedResult<Option<Spanned<Vec<ast::IntfDecl>>>> {
564 if p.peek(0).value == Keyword(Kw::Generic) && p.peek(1).value != Keyword(Kw::Map) {
565 p.bump();
566 let mut span = p.last_span();
567 let i = flanked(p, Paren, |p| {
568 Ok(separated_nonempty(
569 p,
570 Semicolon,
571 CloseDelim(Paren),
572 "generic interface declaration",
573 |p| parse_intf_decl(p, Some(ast::IntfObjKind::Const)),
574 )?)
575 })?;
576 require(p, Semicolon)?;
577 span.expand(p.last_span());
578 Ok(Some(Spanned::new(i, span)))
579 } else {
580 Ok(None)
581 }
582}
583
584pub fn try_port_clause<P: Parser>(
590 p: &mut P,
591) -> ReportedResult<Option<Spanned<Vec<ast::IntfDecl>>>> {
592 if p.peek(0).value == Keyword(Kw::Port) && p.peek(1).value != Keyword(Kw::Map) {
593 p.bump();
594 let mut span = p.last_span();
595 let i = flanked(p, Paren, |p| {
596 Ok(separated_nonempty(
597 p,
598 Semicolon,
599 CloseDelim(Paren),
600 "port interface declaration",
601 |p| parse_intf_decl(p, Some(ast::IntfObjKind::Signal)),
602 )?)
603 })?;
604 require(p, Semicolon)?;
605 span.expand(p.last_span());
606 Ok(Some(Spanned::new(i, span)))
607 } else {
608 Ok(None)
609 }
610}
611
612pub fn parse_intf_decl<P: Parser>(
616 p: &mut P,
617 default: Option<ast::IntfObjKind>,
618) -> ReportedResult<ast::IntfDecl> {
619 let Spanned {
620 value: tkn,
621 mut span,
622 } = p.peek(0);
623 let kind = match tkn {
624 Keyword(Kw::Type) => return parse_type_decl(p, false).map(|d| ast::IntfDecl::TypeDecl(d)),
626
627 Keyword(Kw::Pure)
629 | Keyword(Kw::Impure)
630 | Keyword(Kw::Procedure)
631 | Keyword(Kw::Function) => {
632 let spec = parse_subprog_spec(p)?;
633 let default = if accept(p, Keyword(Kw::Is)) {
634 if accept(p, LtGt) {
635 Some(ast::SubprogDefault::Any)
637 } else if let Some(name) = try_name(p)? {
638 Some(ast::SubprogDefault::Name(name))
640 } else {
641 p.emit(
642 DiagBuilder2::error(format!(
643 "Expected default subprogram name or `<>` after `is`, found {} instead",
644 tkn
645 ))
646 .span(span)
647 .add_note("see IEEE 1076-2008 section 6.5.4"),
648 );
649 return Err(Reported);
650 }
651 } else {
652 None
653 };
654 span.expand(p.last_span());
655 return Ok(ast::IntfDecl::SubprogSpec(ast::IntfSubprogDecl {
656 id: Default::default(),
657 span: span,
658 spec: spec,
659 default: default,
660 }));
661 }
662
663 Keyword(Kw::Package) => {
665 let inst = parse_package_inst(p, false)?;
666 return Ok(ast::IntfDecl::PkgInst(inst));
667 }
668
669 Keyword(Kw::Constant) => {
671 p.bump();
672 ast::IntfObjKind::Const
673 }
674 Keyword(Kw::Signal) => {
675 p.bump();
676 ast::IntfObjKind::Signal
677 }
678 Keyword(Kw::Variable) => {
679 p.bump();
680 ast::IntfObjKind::Var
681 }
682 Keyword(Kw::File) => {
683 p.bump();
684 ast::IntfObjKind::File
685 }
686 _ => {
687 if let Some(k) = default {
688 k
689 } else {
690 p.emit(
691 DiagBuilder2::error("Expected an interface declaration")
692 .span(span)
693 .add_note(
694 "`constant`, `signal`, `variable`, and `file` start an object \
695 declaration",
696 )
697 .add_note("`type` starts a type declaration")
698 .add_note(
699 "`procedure`, `function`, `pure function`, or `impure function` start \
700 a subprogram declaration",
701 )
702 .add_note("`package` starts a package declaration")
703 .add_note("see IEEE 1076-2008 section 6.5"),
704 );
705 return Err(Reported);
706 }
707 }
708 };
709
710 let names = separated_nonempty(p, Comma, Colon, "object name", |p| {
712 parse_ident(p, "object name")
713 })?;
714 require(p, Colon)?;
715
716 let mode = match p.peek(0).value {
718 Keyword(Kw::In) => {
719 p.bump();
720 Some(ast::IntfMode::In)
721 }
722 Keyword(Kw::Out) => {
723 p.bump();
724 Some(ast::IntfMode::Out)
725 }
726 Keyword(Kw::Inout) => {
727 p.bump();
728 Some(ast::IntfMode::Inout)
729 }
730 Keyword(Kw::Buffer) => {
731 p.bump();
732 Some(ast::IntfMode::Buffer)
733 }
734 Keyword(Kw::Linkage) => {
735 p.bump();
736 Some(ast::IntfMode::Linkage)
737 }
738 _ => None,
739 };
740
741 let ty = parse_subtype_ind(p)?;
743 let bus = accept(p, Keyword(Kw::Bus));
744
745 let def = if accept(p, VarAssign) {
747 Some(parse_expr(p)?)
748 } else {
749 None
750 };
751
752 span.expand(p.last_span());
753 Ok(ast::IntfDecl::ObjDecl(ast::IntfObjDecl {
754 kind: kind,
755 span: span,
756 names: names.into_iter().map(|n| ast::Ident::from(n)).collect(),
757 mode: mode,
758 ty: ty,
759 bus: bus,
760 default: def,
761 }))
762}
763
764pub fn try_decl_item<P: Parser>(p: &mut P) -> ReportedResult<Option<ast::DeclItem>> {
766 let mut span = p.peek(0).span;
767 Ok(match p.peek(0).value {
768 Keyword(Kw::Package) => {
772 if p.peek(1).value == Keyword(Kw::Body) {
773 Some(ast::DeclItem::PkgBody(parse_package_body(p)?))
774 } else if p.peek(2).value == Keyword(Kw::Is) && p.peek(3).value == Keyword(Kw::New) {
775 Some(ast::DeclItem::PkgInst(parse_package_inst(p, true)?))
776 } else {
777 Some(ast::DeclItem::PkgDecl(parse_package_decl(p)?))
778 }
779 }
780 Keyword(Kw::Type) => Some(ast::DeclItem::TypeDecl(parse_type_decl(p, true)?)),
782 Keyword(Kw::Subtype) => Some(ast::DeclItem::SubtypeDecl(parse_subtype_decl(p)?)),
784 Keyword(Kw::Constant)
789 | Keyword(Kw::Signal)
790 | Keyword(Kw::Variable)
791 | Keyword(Kw::Shared)
792 | Keyword(Kw::File) => Some(ast::DeclItem::ObjDecl(parse_object_decl(p)?)),
793 Keyword(Kw::Alias) => Some(ast::DeclItem::AliasDecl(parse_alias_decl(p)?)),
795 Keyword(Kw::Use) => Some(ast::DeclItem::UseClause(span, parse_use_clause(p)?)),
797 Keyword(Kw::Pure)
799 | Keyword(Kw::Impure)
800 | Keyword(Kw::Procedure)
801 | Keyword(Kw::Function) => Some(ast::DeclItem::SubprogDecl(parse_subprog_decl_item(p)?)),
802 Keyword(Kw::Component) => Some(ast::DeclItem::CompDecl(parse_component_decl(p)?)),
804 Keyword(Kw::Disconnect) => Some(ast::DeclItem::DisconDecl(parse_discon_spec(p)?)),
806 Keyword(Kw::For) => Some(ast::DeclItem::CfgSpec(parse_config_spec(p)?)),
808 Keyword(Kw::Attribute) => Some(ast::DeclItem::AttrDecl(parse_attr_decl(p)?)),
810 Keyword(Kw::Generic) => {
813 let pk = Spanned::new(ast::PortgenKind::Generic, p.peek(0).span);
814 if p.peek(1).value == Keyword(Kw::Map) {
815 let a = try_map_aspect(p, Kw::Generic)?.unwrap();
816 require(p, Semicolon)?;
817 span.expand(p.last_span());
818 Some(ast::DeclItem::PortgenMap(span, pk, a))
819 } else {
820 let c = try_generic_clause(p)?.unwrap();
821 span.expand(p.last_span());
822 Some(ast::DeclItem::PortgenClause(span, pk, c))
823 }
824 }
825 Keyword(Kw::Port) => {
828 let pk = Spanned::new(ast::PortgenKind::Port, p.peek(0).span);
829 if p.peek(1).value == Keyword(Kw::Map) {
830 let a = try_map_aspect(p, Kw::Port)?.unwrap();
831 require(p, Semicolon)?;
832 span.expand(p.last_span());
833 Some(ast::DeclItem::PortgenMap(span, pk, a))
834 } else {
835 let c = try_port_clause(p)?.unwrap();
836 span.expand(p.last_span());
837 Some(ast::DeclItem::PortgenClause(span, pk, c))
838 }
839 }
840 Keyword(Kw::Group) => Some(ast::DeclItem::GroupDecl(parse_group_decl(p)?)),
842 _ => None,
843 })
844}
845
846pub fn parse_subprog_decl_item<P: Parser>(p: &mut P) -> ReportedResult<ast::Subprog> {
855 let mut span = p.peek(0).span;
856 let spec = parse_subprog_spec(p)?;
857
858 if accept(p, Semicolon) {
860 span.expand(p.last_span());
861 return Ok(ast::Subprog {
862 id: Default::default(),
863 span: span,
864 spec: spec,
865 data: ast::SubprogData::Decl,
866 });
867 }
868
869 if accept(p, Keyword(Kw::Is)) {
871 if accept(p, Keyword(Kw::New)) {
874 let name = parse_name(p)?;
875 let gm = try_map_aspect(p, Kw::Generic)?;
876 require(p, Semicolon)?;
877 span.expand(p.last_span());
878 return Ok(ast::Subprog {
879 id: Default::default(),
880 span: span,
881 spec: spec,
882 data: ast::SubprogData::Inst {
883 name: name,
884 generics: gm,
885 },
886 });
887 } else {
888 let decl_items = repeat(p, try_decl_item)?;
889 require(p, Keyword(Kw::Begin))?;
890 let stmts = repeat_until(p, Keyword(Kw::End), parse_stmt)?;
891 require(p, Keyword(Kw::End))?;
892 accept(p, Keyword(Kw::Function));
895 accept(p, Keyword(Kw::Procedure));
896 try_primary_name(p);
897 require(p, Semicolon)?;
898 span.expand(p.last_span());
899 return Ok(ast::Subprog {
900 id: Default::default(),
901 span: span,
902 spec: spec,
903 data: ast::SubprogData::Body {
904 decls: decl_items,
905 stmts: stmts,
906 },
907 });
908 }
909 }
910
911 let pk = p.peek(0);
914 p.emit(
915 DiagBuilder2::error(format!(
916 "Expected `;` or keyword `is` after subprogram specification, found {} instead",
917 pk.value
918 ))
919 .span(pk.span)
920 .add_note("see IEEE 1076-2008 section 4.2"),
921 );
922 Err(Reported)
923}
924
925pub fn parse_subtype_ind<P: Parser>(p: &mut P) -> ReportedResult<ast::SubtypeInd> {
934 let Spanned {
935 value: tkn,
936 mut span,
937 } = p.peek(0);
938
939 let (res, name) = if let Some(exprs) = try_paren_expr(p)? {
943 let name = parse_name(p)?;
944 (Some(ast::ResolInd::Exprs(exprs)), name)
945 } else {
946 let name = parse_name(p)?;
947 if let Some(other) = try_name(p)? {
948 (Some(ast::ResolInd::Name(name)), other)
949 } else {
950 (None, name)
951 }
952 };
953
954 span.expand(p.last_span());
955 Ok(ast::SubtypeInd {
956 span: span,
957 res: res,
958 name: name,
959 })
960}
961
962pub fn parse_paren_expr<P: Parser>(p: &mut P) -> ReportedResult<ast::ParenElems> {
975 let mut span = p.peek(0).span;
976 let v = flanked(p, Paren, parse_paren_elem_vec)?;
977 span.expand(p.last_span());
978 Ok(Spanned::new(v, span))
979}
980
981pub fn try_paren_expr<P: Parser>(p: &mut P) -> ReportedResult<Option<ast::ParenElems>> {
982 let mut span = p.peek(0).span;
983 match try_flanked(p, Paren, parse_paren_elem_vec)? {
984 Some(v) => {
985 span.expand(p.last_span());
986 Ok(Some(Spanned::new(v, span)))
987 }
988 None => Ok(None),
989 }
990}
991
992pub fn parse_paren_elem_vec<P: Parser>(p: &mut P) -> ReportedResult<Vec<ast::ParenElem>> {
993 separated(p, Comma, CloseDelim(Paren), "expression", |p| {
994 let mut choices_span = p.peek(0).span;
996 let mut choices = separated_nonempty(
997 p,
998 Pipe,
999 token_predicate!(Arrow, Comma, CloseDelim(Paren)),
1000 "expression",
1001 parse_expr,
1002 )?;
1003 choices_span.expand(p.last_span());
1004
1005 if accept(p, Arrow) {
1009 let q = p.last_span();
1010 let actual = parse_expr(p)?;
1011 let span = Span::union(choices_span, actual.span);
1012 Ok(ast::ParenElem {
1013 span: span,
1014 choices: Spanned::new(choices, choices_span),
1015 expr: actual,
1016 })
1017 } else {
1018 let mut it = choices.drain(..);
1019 let first = it.next().unwrap();
1020
1021 let mut it = it.map(|x| x.span);
1023 if let Some(second) = it.next() {
1024 let span = it.fold(second, Span::union);
1025 p.emit(
1026 DiagBuilder2::error("Superfluous additional expressions")
1027 .span(span)
1028 .add_note(
1029 "If you wanted an association list, did you forget a `=>` after the \
1030 list of choices?",
1031 ),
1032 );
1033 return Err(Reported);
1034 }
1035
1036 let span = first.span;
1037 Ok(ast::ParenElem {
1038 span: span,
1039 choices: Spanned::new(vec![], INVALID_SPAN),
1040 expr: first,
1041 })
1042 }
1043 })
1044 .map_err(|e| e.into())
1045}
1046
1047pub fn parse_expr<P: Parser>(p: &mut P) -> ReportedResult<ast::Expr> {
1048 parse_expr_prec(p, ExprPrec::lowest())
1049}
1050
1051pub fn parse_primary_expr<P: Parser>(p: &mut P) -> ReportedResult<ast::Expr> {
1052 let Spanned {
1053 value: tkn,
1054 mut span,
1055 } = p.peek(0);
1056
1057 if let Some(data) = match tkn {
1060 Keyword(Kw::Null) => {
1061 p.bump();
1062 Some(ast::NullExpr)
1063 }
1064 Keyword(Kw::Open) => {
1065 p.bump();
1066 Some(ast::OpenExpr)
1067 }
1068 Keyword(Kw::Others) => {
1069 p.bump();
1070 Some(ast::OthersExpr)
1071 }
1072 Keyword(Kw::Default) => {
1073 p.bump();
1074 Some(ast::DefaultExpr)
1075 }
1076 LtGt => {
1077 p.bump();
1078 Some(ast::BoxExpr)
1079 }
1080
1081 Keyword(Kw::New) => {
1082 p.bump();
1083 let expr = parse_primary_expr(p)?;
1084 span.expand(p.last_span());
1085 Some(ast::NewExpr(Box::new(expr)))
1086 }
1114
1115 Lit(l @ Literal::Abstract(_, _, _, _)) => {
1116 p.bump();
1117 let unit = try_ident(p);
1118 span.expand(p.last_span());
1119 Some(ast::LitExpr(l, unit))
1120 }
1121
1122 Lit(l @ Literal::BitString(_, _, _)) => {
1123 p.bump();
1124 Some(ast::LitExpr(l, None))
1125 }
1126
1127 OpenDelim(Paren) => {
1128 let expr = parse_paren_expr(p)?;
1129
1130 if let Some(name) = try_name(p)? {
1133 span.expand(p.last_span());
1134 Some(ast::ResolExpr(expr, name))
1135 } else {
1136 span.expand(p.last_span());
1137 Some(ast::ParenExpr(expr))
1138 }
1139 }
1140
1141 _ => None,
1142 } {
1143 return Ok(ast::Expr {
1144 span: span,
1145 data: data,
1146 });
1147 }
1148
1149 if let Some(expr) = try_name_or_qualified_primary_expr(p)? {
1151 return Ok(expr);
1152 }
1153
1154 let q = p.peek(0).span;
1157 p.emit(
1158 DiagBuilder2::error(format!(
1159 "Expected a primary expression, found {} instead",
1160 tkn
1161 ))
1162 .span(q)
1163 .add_note(
1164 "A primary expression is either an abstract, bit string, character, or string \
1165 literal; a name; a parenthesized expression `( ... )`; an allocation `new ...`; or \
1166 the constants `null`, `open`, or `others`.",
1167 ),
1168 );
1169 Err(Reported)
1170}
1171
1172pub fn try_name_or_qualified_primary_expr<P: Parser>(
1173 p: &mut P,
1174) -> ReportedResult<Option<ast::Expr>> {
1175 let mut span = p.peek(0).span;
1176
1177 if let Some(name) = try_name(p)? {
1179 if let Some(suffix_name) = try_name(p)? {
1182 span.expand(p.last_span());
1183 return Ok(Some(ast::Expr {
1184 span: span,
1185 data: ast::DoubleNameExpr(name, suffix_name),
1186 }));
1187 }
1188
1189 if accept(p, Apostrophe) {
1191 if p.peek(0).value == OpenDelim(Paren) {
1192 let expr = parse_paren_expr(p)?;
1193 span.expand(p.last_span());
1194 return Ok(Some(ast::Expr {
1195 span: span,
1196 data: ast::QualExpr(name, expr),
1197 }));
1198 } else {
1199 let q = p.last_span();
1200 p.emit(
1201 DiagBuilder2::error("Expected a parenthesized expression after `'`")
1202 .span(q)
1203 .add_note(
1204 "`'` introduces a qualified expression, which is of the form \
1205 `<name>'(<expr>)`",
1206 )
1207 .add_note("see IEEE 1076-2008 section 9.3.5"),
1208 );
1209 return Err(Reported);
1210 }
1211 }
1212
1213 span.expand(p.last_span());
1214 return Ok(Some(ast::Expr {
1215 span: span,
1216 data: ast::NameExpr(name),
1217 }));
1218 }
1219
1220 Ok(None)
1221}
1222
1223#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
1225pub enum ExprPrec {
1226 Inertial,
1227 Condition,
1228 Logical,
1229 Relational,
1230 Shift,
1231 Range,
1232 Add,
1233 Sign,
1234 Mul,
1235 Pow,
1236 Unary,
1237 Primary,
1238}
1239
1240impl ExprPrec {
1241 fn highest() -> ExprPrec {
1242 ExprPrec::Primary
1243 }
1244
1245 fn lowest() -> ExprPrec {
1246 ExprPrec::Inertial
1247 }
1248}
1249
1250pub fn parse_expr_prec<P: Parser>(p: &mut P, prec: ExprPrec) -> ReportedResult<ast::Expr> {
1256 let tkn = p.peek(0);
1257 let mut span = tkn.span;
1258
1259 if let Some(op) = as_unary_op(tkn.value) {
1261 let op_prec = unary_prec(op);
1262 if prec <= op_prec {
1263 p.bump();
1264 let arg = parse_expr_prec(p, op_prec)?;
1265 span.expand(p.last_span());
1266 return parse_expr_suffix(
1267 p,
1268 ast::Expr {
1269 span: span,
1270 data: ast::UnaryExpr(Spanned::new(op, tkn.span), Box::new(arg)),
1271 },
1272 prec,
1273 );
1274 }
1275 }
1276
1277 let primary = parse_primary_expr(p)?;
1279
1280 parse_expr_suffix(p, primary, prec)
1282}
1283
1284pub fn parse_expr_suffix<P: Parser>(
1288 p: &mut P,
1289 prefix: ast::Expr,
1290 prec: ExprPrec,
1291) -> ReportedResult<ast::Expr> {
1292 let tkn = p.peek(0);
1293
1294 if let Some(op) = as_binary_op(tkn.value) {
1296 let op_prec = binary_prec(op);
1297 if prec <= op_prec {
1298 p.bump();
1299 let rhs = parse_expr_prec(p, op_prec)?;
1300 let span = Span::union(prefix.span, p.last_span());
1301 return parse_expr_suffix(
1302 p,
1303 ast::Expr {
1304 span: span,
1305 data: ast::BinaryExpr(
1306 Spanned::new(op, tkn.span),
1307 Box::new(prefix),
1308 Box::new(rhs),
1309 ),
1310 },
1311 prec,
1312 );
1313 }
1314 }
1315
1316 Ok(prefix)
1319}
1320
1321fn as_unary_op(tkn: Token) -> Option<ast::UnaryOp> {
1323 Some(match tkn {
1324 Keyword(Kw::Inertial) => ast::UnaryOp::Inertial,
1325 Condition => ast::UnaryOp::Condition,
1326
1327 Keyword(Kw::Not) => ast::UnaryOp::Not,
1328 Keyword(Kw::Abs) => ast::UnaryOp::Abs,
1329
1330 Add => ast::UnaryOp::Sign(ast::Sign::Pos),
1331 Sub => ast::UnaryOp::Sign(ast::Sign::Neg),
1332
1333 Keyword(Kw::And) => ast::UnaryOp::Logical(ast::LogicalOp::And),
1334 Keyword(Kw::Or) => ast::UnaryOp::Logical(ast::LogicalOp::Or),
1335 Keyword(Kw::Nand) => ast::UnaryOp::Logical(ast::LogicalOp::Nand),
1336 Keyword(Kw::Nor) => ast::UnaryOp::Logical(ast::LogicalOp::Nor),
1337 Keyword(Kw::Xor) => ast::UnaryOp::Logical(ast::LogicalOp::Xor),
1338 Keyword(Kw::Xnor) => ast::UnaryOp::Logical(ast::LogicalOp::Xnor),
1339 _ => return None,
1340 })
1341}
1342
1343fn as_binary_op(tkn: Token) -> Option<ast::BinaryOp> {
1345 Some(match tkn {
1346 Keyword(Kw::To) => ast::BinaryOp::Dir(ast::Dir::To),
1347 Keyword(Kw::Downto) => ast::BinaryOp::Dir(ast::Dir::Downto),
1348
1349 Keyword(Kw::And) => ast::BinaryOp::Logical(ast::LogicalOp::And),
1350 Keyword(Kw::Or) => ast::BinaryOp::Logical(ast::LogicalOp::Or),
1351 Keyword(Kw::Nand) => ast::BinaryOp::Logical(ast::LogicalOp::Nand),
1352 Keyword(Kw::Nor) => ast::BinaryOp::Logical(ast::LogicalOp::Nor),
1353 Keyword(Kw::Xor) => ast::BinaryOp::Logical(ast::LogicalOp::Xor),
1354 Keyword(Kw::Xnor) => ast::BinaryOp::Logical(ast::LogicalOp::Xnor),
1355
1356 Eq => ast::BinaryOp::Rel(ast::RelationalOp::Eq),
1357 Neq => ast::BinaryOp::Rel(ast::RelationalOp::Neq),
1358 Lt => ast::BinaryOp::Rel(ast::RelationalOp::Lt),
1359 Leq => ast::BinaryOp::Rel(ast::RelationalOp::Leq),
1360 Gt => ast::BinaryOp::Rel(ast::RelationalOp::Gt),
1361 Geq => ast::BinaryOp::Rel(ast::RelationalOp::Geq),
1362
1363 MatchEq => ast::BinaryOp::Match(ast::RelationalOp::Eq),
1364 MatchNeq => ast::BinaryOp::Match(ast::RelationalOp::Neq),
1365 MatchLt => ast::BinaryOp::Match(ast::RelationalOp::Lt),
1366 MatchLeq => ast::BinaryOp::Match(ast::RelationalOp::Leq),
1367 MatchGt => ast::BinaryOp::Match(ast::RelationalOp::Gt),
1368 MatchGeq => ast::BinaryOp::Match(ast::RelationalOp::Geq),
1369
1370 Keyword(Kw::Sll) => ast::BinaryOp::Shift(ast::ShiftOp::Sll),
1371 Keyword(Kw::Srl) => ast::BinaryOp::Shift(ast::ShiftOp::Srl),
1372 Keyword(Kw::Sla) => ast::BinaryOp::Shift(ast::ShiftOp::Sla),
1373 Keyword(Kw::Sra) => ast::BinaryOp::Shift(ast::ShiftOp::Sra),
1374 Keyword(Kw::Rol) => ast::BinaryOp::Shift(ast::ShiftOp::Rol),
1375 Keyword(Kw::Ror) => ast::BinaryOp::Shift(ast::ShiftOp::Ror),
1376
1377 Add => ast::BinaryOp::Add,
1378 Sub => ast::BinaryOp::Sub,
1379 Ampersand => ast::BinaryOp::Concat,
1380
1381 Mul => ast::BinaryOp::Mul,
1382 Div => ast::BinaryOp::Div,
1383 Keyword(Kw::Mod) => ast::BinaryOp::Mod,
1384 Keyword(Kw::Rem) => ast::BinaryOp::Rem,
1385 Pow => ast::BinaryOp::Pow,
1386 _ => return None,
1387 })
1388}
1389
1390fn unary_prec(op: ast::UnaryOp) -> ExprPrec {
1392 match op {
1393 ast::UnaryOp::Not => ExprPrec::Unary,
1394 ast::UnaryOp::Abs => ExprPrec::Unary,
1395 ast::UnaryOp::Logical(_) => ExprPrec::Unary,
1396 ast::UnaryOp::Sign(_) => ExprPrec::Sign,
1397 ast::UnaryOp::Inertial => ExprPrec::Inertial,
1398 ast::UnaryOp::Condition => ExprPrec::Condition,
1399 }
1400}
1401
1402fn binary_prec(op: ast::BinaryOp) -> ExprPrec {
1404 match op {
1405 ast::BinaryOp::Dir(_) => ExprPrec::Range,
1406 ast::BinaryOp::Logical(_) => ExprPrec::Logical,
1407 ast::BinaryOp::Rel(_) => ExprPrec::Relational,
1408 ast::BinaryOp::Match(_) => ExprPrec::Relational,
1409 ast::BinaryOp::Shift(_) => ExprPrec::Shift,
1410 ast::BinaryOp::Add => ExprPrec::Add,
1411 ast::BinaryOp::Sub => ExprPrec::Add,
1412 ast::BinaryOp::Concat => ExprPrec::Add,
1413 ast::BinaryOp::Mul => ExprPrec::Mul,
1414 ast::BinaryOp::Div => ExprPrec::Mul,
1415 ast::BinaryOp::Mod => ExprPrec::Mul,
1416 ast::BinaryOp::Rem => ExprPrec::Mul,
1417 ast::BinaryOp::Pow => ExprPrec::Pow,
1418 }
1419}
1420
1421pub fn parse_package_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::PkgDecl> {
1431 let mut span = p.peek(0).span;
1432
1433 require(p, Keyword(Kw::Package))?;
1435 let name = parse_ident(p, "package name")?;
1436 require(p, Keyword(Kw::Is))?;
1437
1438 let decl_items = repeat(p, try_decl_item)?;
1440
1441 require(p, Keyword(Kw::End))?;
1443 accept(p, Keyword(Kw::Package));
1444 parse_optional_matching_ident(p, name, "package", "section 4.7");
1445 require(p, Semicolon)?;
1446 span.expand(p.last_span());
1447 Ok(ast::PkgDecl {
1448 id: Default::default(),
1449 span: span,
1450 name: name,
1451 decls: decl_items,
1452 })
1453}
1454
1455pub fn parse_package_body<P: Parser>(p: &mut P) -> ReportedResult<ast::PkgBody> {
1464 let mut span = p.peek(0).span;
1465 require(p, Keyword(Kw::Package))?;
1466 require(p, Keyword(Kw::Body))?;
1467 let name = parse_ident(p, "package name")?;
1468 require(p, Keyword(Kw::Is))?;
1469 let decl_items = repeat(p, try_decl_item)?;
1470 require(p, Keyword(Kw::End))?;
1471 accept(p, Keyword(Kw::Package)); accept(p, Keyword(Kw::Body)); parse_optional_matching_ident(p, name, "package body", "section 4.8");
1474 require(p, Semicolon)?;
1475 span.expand(p.last_span());
1476 Ok(ast::PkgBody {
1477 id: Default::default(),
1478 span: span,
1479 name: name,
1480 decls: decl_items,
1481 })
1482}
1483
1484pub fn parse_package_inst<P: Parser>(
1490 p: &mut P,
1491 with_semicolon: bool,
1492) -> ReportedResult<ast::PkgInst> {
1493 let mut span = p.peek(0).span;
1494 require(p, Keyword(Kw::Package))?;
1495 let name = parse_ident(p, "package name")?;
1496 require(p, Keyword(Kw::Is))?;
1497 require(p, Keyword(Kw::New))?;
1498 let pkg = parse_name(p)?;
1499 let gm = try_map_aspect(p, Kw::Generic)?;
1500 if with_semicolon {
1501 require(p, Semicolon)?;
1502 }
1503 span.expand(p.last_span());
1504 Ok(ast::PkgInst {
1505 id: Default::default(),
1506 span: span,
1507 name: name,
1508 target: pkg,
1509 generics: gm,
1510 })
1511}
1512
1513pub fn try_map_aspect<P: Parser>(p: &mut P, kw: Kw) -> ReportedResult<Option<ast::ParenElems>> {
1520 if p.peek(0).value == Keyword(kw) && p.peek(1).value == Keyword(Kw::Map) {
1521 p.bump();
1522 p.bump();
1523 let v = parse_paren_expr(p)?;
1524 Ok(Some(v))
1525 } else {
1526 Ok(None)
1527 }
1528}
1529
1530pub fn parse_type_decl<P: Parser>(
1546 p: &mut P,
1547 with_semicolon: bool,
1548) -> ReportedResult<ast::TypeDecl> {
1549 let mut span = p.peek(0).span;
1550 require(p, Keyword(Kw::Type))?;
1551 let name = parse_ident(p, "type name")?;
1552
1553 let data = if accept(p, Keyword(Kw::Is)) {
1556 let Spanned {
1557 value: tkn,
1558 span: mut sp,
1559 } = p.peek(0);
1560 let data = match tkn {
1561 OpenDelim(Paren) => ast::EnumType(parse_paren_expr(p)?),
1563
1564 Keyword(Kw::Range) => {
1566 p.bump();
1567 let range = parse_expr(p)?;
1568 let units = if accept(p, Keyword(Kw::Units)) {
1569 let u = repeat_until(p, Keyword(Kw::End), |p| {
1570 let name = parse_ident(p, "unit name")?;
1571 let rel = if accept(p, Eq) {
1572 Some(Box::new(parse_expr(p)?))
1573 } else {
1574 None
1575 };
1576 require(p, Semicolon)?;
1577 Ok((name.into(), rel))
1578 })?;
1579 require(p, Keyword(Kw::End))?;
1580 require(p, Keyword(Kw::Units))?;
1581 parse_optional_matching_ident(p, name, "type", "section 5.2.4");
1582 Some(u)
1583 } else {
1584 None
1585 };
1586 ast::RangeType(Box::new(range), units)
1587 }
1588
1589 Keyword(Kw::Array) => {
1591 p.bump();
1592 let indices = parse_paren_expr(p)?;
1593 require(p, Keyword(Kw::Of))?;
1594 let subtype = parse_subtype_ind(p)?;
1595 sp.expand(p.last_span());
1596 ast::ArrayType(indices, subtype)
1597 }
1598
1599 Keyword(Kw::Record) => {
1601 p.bump();
1602 let fields = repeat_until(p, Keyword(Kw::End), |p| {
1603 let names = separated_nonempty(p, Comma, Colon, "field name", |p| {
1604 parse_ident(p, "field name").map(|i| i.into())
1605 })?;
1606 require(p, Colon)?;
1607 let subtype = parse_subtype_ind(p)?;
1608 require(p, Semicolon)?;
1609 Ok((names, subtype))
1610 })?;
1611 require(p, Keyword(Kw::End))?;
1612 require(p, Keyword(Kw::Record))?;
1613 parse_optional_matching_ident(p, name, "type", "section 5.3.3");
1614 sp.expand(p.last_span());
1615 ast::RecordType(fields)
1616 }
1617
1618 Keyword(Kw::Access) => {
1620 p.bump();
1621 let subtype = parse_subtype_ind(p)?;
1622 sp.expand(p.last_span());
1623 ast::AccessType(subtype)
1624 }
1625
1626 Keyword(Kw::File) => {
1628 p.bump();
1629 require(p, Keyword(Kw::Of))?;
1630 let ty = parse_name(p)?;
1631 span.expand(p.last_span());
1632 ast::FileType(ty)
1633 }
1634
1635 Keyword(Kw::Protected) => {
1637 p.bump();
1638 let body = accept(p, Keyword(Kw::Body));
1639 let decl_items = repeat(p, try_decl_item)?;
1640 require(p, Keyword(Kw::End))?;
1641 require(p, Keyword(Kw::Protected))?;
1642 if body {
1643 require(p, Keyword(Kw::Body))?;
1644 }
1645 parse_optional_matching_ident(p, name, "type", "section 5.6");
1646 ast::ProtectedType(decl_items)
1647 }
1648
1649 wrong => {
1651 p.emit(
1652 DiagBuilder2::error(format!(
1653 "Expected type definition after keyword `is`, found {} instead",
1654 tkn
1655 ))
1656 .span(sp),
1657 );
1658 return Err(Reported);
1659 }
1660 };
1661 sp.expand(p.last_span());
1662 Some(Spanned::new(data, sp))
1663 } else {
1664 None
1665 };
1666
1667 if with_semicolon {
1668 require(p, Semicolon)?;
1669 }
1670 span.expand(p.last_span());
1671 Ok(ast::TypeDecl {
1672 id: Default::default(),
1673 span: span,
1674 name: name,
1675 data: data,
1676 })
1677}
1678
1679pub fn parse_subtype_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::SubtypeDecl> {
1685 let mut span = p.peek(0).span;
1686 require(p, Keyword(Kw::Subtype))?;
1687 let name = parse_ident(p, "subtype name")?;
1688 require(p, Keyword(Kw::Is))?;
1689 let subtype = parse_subtype_ind(p)?;
1690 require(p, Semicolon)?;
1691 span.expand(p.last_span());
1692 Ok(ast::SubtypeDecl {
1693 id: Default::default(),
1694 span: span,
1695 name: name,
1696 subtype: subtype,
1697 })
1698}
1699
1700pub fn parse_alias_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::AliasDecl> {
1707 let mut span = p.peek(0).span;
1708 require(p, Keyword(Kw::Alias))?;
1709 let name = match try_primary_name(p) {
1710 Some(n) => n,
1711 None => {
1712 let pk = p.peek(0);
1713 p.emit(
1714 DiagBuilder2::error(format!(
1715 "Expected alias designator after keyword `alias`, found {} instead",
1716 pk.value
1717 ))
1718 .span(pk.span)
1719 .add_note(
1720 "An alias designator is either an identifier, a character literal, or an \
1721 operator symbol",
1722 )
1723 .add_note("see IEEE 1076-2008 section 6.6"),
1724 );
1725 return Err(Reported);
1726 }
1727 };
1728 let subtype = if accept(p, Colon) {
1729 Some(parse_subtype_ind(p)?)
1730 } else {
1731 None
1732 };
1733 require(p, Keyword(Kw::Is))?;
1734 let target = parse_name(p)?;
1735 require(p, Semicolon)?;
1736 span.expand(p.last_span());
1737 Ok(ast::AliasDecl {
1738 id: Default::default(),
1739 span: span,
1740 name: name,
1741 subtype: subtype,
1742 target: target,
1743 })
1744}
1745
1746pub fn parse_signature<P: Parser>(p: &mut P) -> ReportedResult<ast::Signature> {
1747 let mut span = p.last_span();
1748 let args = separated(
1749 p,
1750 Comma,
1751 token_predicate!(CloseDelim(Brack), Keyword(Kw::Return)),
1752 "type mark",
1753 parse_name,
1754 )?;
1755 let retty = if accept(p, Keyword(Kw::Return)) {
1756 Some(parse_name(p)?)
1757 } else {
1758 None
1759 };
1760 span.expand(p.peek(0).span);
1761 Ok(ast::Signature {
1762 span: span,
1763 args: args,
1764 retty: retty,
1765 })
1766}
1767
1768pub fn parse_object_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::ObjDecl> {
1785 let mut span = p.peek(0).span;
1786
1787 let kind = match p.peek(0).value {
1789 Keyword(Kw::Constant) => {
1790 p.bump();
1791 ast::ObjKind::Const
1792 }
1793 Keyword(Kw::Signal) => {
1794 p.bump();
1795 ast::ObjKind::Signal
1796 }
1797 Keyword(Kw::File) => {
1798 p.bump();
1799 ast::ObjKind::File
1800 }
1801 Keyword(Kw::Variable) => {
1802 p.bump();
1803 ast::ObjKind::Var
1804 }
1805 Keyword(Kw::Shared) => {
1806 p.bump();
1807 require(p, Keyword(Kw::Variable))?;
1808 ast::ObjKind::SharedVar
1809 }
1810 wrong => {
1811 p.emit(
1812 DiagBuilder2::error(format!(
1813 "Expected a constant, signal, variable, or file declaration, found {} instead",
1814 wrong
1815 ))
1816 .span(span)
1817 .add_note("see IEEE 1076-2008 section 6.4.2"),
1818 );
1819 return Err(Reported);
1820 }
1821 };
1822
1823 let names = separated_nonempty(p, Comma, Colon, "object name", |p| {
1825 parse_ident(p, "object name")
1826 })?;
1827 require(p, Colon)?;
1828 let subtype = parse_subtype_ind(p)?;
1829
1830 let pk = p.peek(0);
1832 let detail = match pk.value {
1833 Keyword(Kw::Register) => {
1834 p.bump();
1835 Some(Spanned::new(ast::ObjDetail::Register, p.last_span()))
1836 }
1837 Keyword(Kw::Bus) => {
1838 p.bump();
1839 Some(Spanned::new(ast::ObjDetail::Bus, p.last_span()))
1840 }
1841 Keyword(Kw::Open) | Keyword(Kw::Is) => {
1842 let mut span = p.peek(0).span;
1843 let open = if accept(p, Keyword(Kw::Open)) {
1844 Some(parse_expr(p)?)
1845 } else {
1846 None
1847 };
1848 require(p, Keyword(Kw::Is))?;
1849 let path = parse_expr(p)?;
1850 span.expand(p.last_span());
1851 Some(Spanned::new(ast::ObjDetail::Open(open, path), span))
1852 }
1853 _ => None,
1854 };
1855
1856 let init = if accept(p, VarAssign) {
1858 Some(parse_expr(p)?)
1859 } else {
1860 None
1861 };
1862
1863 require(p, Semicolon)?;
1864 span.expand(p.last_span());
1865 Ok(ast::ObjDecl {
1866 span: span,
1867 kind: kind,
1868 names: names.into_iter().map(|n| n.into()).collect(),
1869 subtype: subtype,
1870 detail: detail,
1871 init: init,
1872 })
1873}
1874
1875pub fn parse_subprog_spec<P: Parser>(p: &mut P) -> ReportedResult<ast::SubprogSpec> {
1889 let mut span = p.peek(0).span;
1890
1891 let purity = match p.peek(0).value {
1893 Keyword(Kw::Pure) => {
1894 p.bump();
1895 Some(ast::SubprogPurity::Pure)
1896 }
1897 Keyword(Kw::Impure) => {
1898 p.bump();
1899 Some(ast::SubprogPurity::Impure)
1900 }
1901 _ => None,
1902 };
1903
1904 let pk = p.peek(0);
1906 let kind = match pk.value {
1907 Keyword(Kw::Procedure) => {
1908 p.bump();
1909 ast::SubprogKind::Proc
1910 }
1911 Keyword(Kw::Function) => {
1912 p.bump();
1913 ast::SubprogKind::Func
1914 }
1915 wrong => {
1916 p.emit(
1917 DiagBuilder2::error(format!(
1918 "Expected `procedure` or `function`, found {} instead",
1919 wrong
1920 ))
1921 .span(span)
1922 .add_note("see IEEE 1076-2008 section 4.2"),
1923 );
1924 return Err(Reported);
1925 }
1926 };
1927
1928 let name = match try_primary_name(p) {
1930 Some(n) => n,
1931 None => {
1932 let pk = p.peek(0);
1933 p.emit(
1934 DiagBuilder2::error(format!(
1935 "Expected subprogram name, found {} instead",
1936 pk.value
1937 ))
1938 .span(pk.span)
1939 .add_note("A subprogram name is either an identifier or an operator symbol")
1940 .add_note("see IEEE 1076-2008 section 4.2"),
1941 );
1942 return Err(Reported);
1943 }
1944 };
1945
1946 let gc = if p.peek(0).value == Keyword(Kw::Generic) && p.peek(1).value != Keyword(Kw::Map) {
1948 p.bump();
1949 Some(flanked(p, Paren, |p| {
1950 Ok(separated_nonempty(
1951 p,
1952 Semicolon,
1953 CloseDelim(Paren),
1954 "generic interface declaration",
1955 |p| parse_intf_decl(p, Some(ast::IntfObjKind::Const)),
1956 )?)
1957 })?)
1958 } else {
1959 None
1960 };
1961
1962 let gm = try_map_aspect(p, Kw::Generic)?;
1964
1965 let params = if accept(p, Keyword(Kw::Parameter)) || p.peek(0).value == OpenDelim(Paren) {
1967 Some(flanked(p, Paren, |p| {
1968 Ok(separated_nonempty(
1969 p,
1970 Semicolon,
1971 CloseDelim(Paren),
1972 "parameter interface declaration",
1973 |p| parse_intf_decl(p, Some(ast::IntfObjKind::Var)),
1974 )?)
1975 })?)
1976 } else {
1977 None
1978 };
1979
1980 let retty = if accept(p, Keyword(Kw::Return)) {
1982 Some(parse_name(p)?)
1983 } else {
1984 None
1985 };
1986
1987 span.expand(p.last_span());
1988 Ok(ast::SubprogSpec {
1989 span: span,
1990 name: name,
1991 kind: kind,
1992 purity: purity,
1993 generic_clause: gc,
1994 generic_map: gm,
1995 params: params,
1996 retty: retty,
1997 })
1998}
1999
2000pub fn parse_component_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::CompDecl> {
2010 let mut span = p.peek(0).span;
2011 require(p, Keyword(Kw::Component))?;
2012 let name = parse_ident(p, "component name")?;
2013 accept(p, Keyword(Kw::Is));
2014 let gc = try_generic_clause(p)?;
2015 let pc = try_port_clause(p)?;
2016 require(p, Keyword(Kw::End))?;
2017 accept(p, Keyword(Kw::Component));
2018 parse_optional_matching_ident(p, name, "component", "section 6.8");
2019 require(p, Semicolon)?;
2020 span.expand(p.last_span());
2021 Ok(ast::CompDecl {
2022 id: Default::default(),
2023 span: span,
2024 name: name,
2025 generics: gc,
2026 ports: pc,
2027 })
2028}
2029
2030pub fn parse_discon_spec<P: Parser>(p: &mut P) -> ReportedResult<ast::DisconSpec> {
2037 let mut span = p.peek(0).span;
2038 require(p, Keyword(Kw::Disconnect))?;
2039 let target = match p.peek(0).value {
2040 Keyword(Kw::Others) => {
2041 p.bump();
2042 ast::DisconTarget::Others
2043 }
2044 Keyword(Kw::All) => {
2045 p.bump();
2046 ast::DisconTarget::All
2047 }
2048 _ => ast::DisconTarget::Signals(separated_nonempty(
2049 p,
2050 Comma,
2051 Colon,
2052 "signal name",
2053 parse_name,
2054 )?),
2055 };
2056 require(p, Colon)?;
2057 let ty = parse_name(p)?;
2058 require(p, Keyword(Kw::After))?;
2059 let after = parse_expr(p)?;
2060 require(p, Semicolon)?;
2061 span.expand(p.last_span());
2062 Ok(ast::DisconSpec {
2063 span: span,
2064 target: target,
2065 ty: ty,
2066 after: after,
2067 })
2068}
2069
2070pub fn parse_vunit_binding_ind<P: Parser>(p: &mut P) -> ReportedResult<()> {
2071 unimp!(p, "Verification unit binding indications")
2072}
2073
2074pub fn parse_block_comp_decl_item<P: Parser>(p: &mut P) -> ReportedResult<ast::DeclItem> {
2085 match (p.peek(0).value, p.peek(1).value) {
2086 (Keyword(Kw::Use), Keyword(Kw::Vunit)) => {
2088 parse_vunit_binding_ind(p).map(|i| ast::DeclItem::VunitBindInd(i))
2089 }
2090 (Keyword(Kw::Use), _) => {
2092 let span = p.peek(1).span;
2093 parse_use_clause(p).map(|i| ast::DeclItem::UseClause(span, i))
2094 }
2095 (Keyword(Kw::For), _) => parse_block_comp_config(p).map(|i| ast::DeclItem::BlockCompCfg(i)),
2097 (Keyword(Kw::Attribute), _) => parse_attr_decl(p).map(|i| ast::DeclItem::AttrDecl(i)),
2099 (Keyword(Kw::Group), _) => parse_group_decl(p).map(|i| ast::DeclItem::GroupDecl(i)),
2101
2102 (wrong, _) => {
2103 let sp = p.peek(0).span;
2104 p.emit(
2105 DiagBuilder2::error(format!(
2106 "Expected configuration item, found {} instead",
2107 wrong
2108 ))
2109 .span(sp),
2110 );
2111 Err(Reported)
2112 }
2113 }
2114}
2115
2116pub fn parse_block_comp_config<P: Parser>(p: &mut P) -> ReportedResult<ast::BlockCompCfg> {
2124 let mut span = p.peek(0).span;
2125 require(p, Keyword(Kw::For))?;
2126 let spec = parse_block_comp_spec(p)?;
2127 let bind = parse_binding_ind(p)?;
2128 let decl_items = repeat_until(p, Keyword(Kw::End), parse_block_comp_decl_item)?;
2129 require(p, Keyword(Kw::End))?;
2130 require(p, Keyword(Kw::For))?;
2131 require(p, Semicolon)?;
2132 span.expand(p.last_span());
2133 Ok(ast::BlockCompCfg {
2134 span: span,
2135 spec: spec,
2136 bind: bind,
2137 decls: decl_items,
2138 })
2139}
2140
2141pub fn parse_binding_ind<P: Parser>(p: &mut P) -> ReportedResult<ast::BindingInd> {
2152 let mut span = p.peek(0).span;
2153
2154 let entity = if accept(p, Keyword(Kw::Use)) {
2156 let pk = p.peek(0);
2157 Some(match pk.value {
2158 Keyword(Kw::Entity) => {
2159 p.bump();
2160 ast::EntityAspect::Entity(parse_name(p)?)
2161 }
2162 Keyword(Kw::Configuration) => {
2163 p.bump();
2164 ast::EntityAspect::Cfg(parse_name(p)?)
2165 }
2166 Keyword(Kw::Open) => {
2167 p.bump();
2168 ast::EntityAspect::Open
2169 }
2170 _ => {
2171 p.emit(
2172 DiagBuilder2::error(format!(
2173 "Expected entity aspect after `use`, found {} instead",
2174 pk.value
2175 ))
2176 .span(pk.span)
2177 .add_note("An entity aspect is one of the following:")
2178 .add_note("`entity <name>(<architecture>)`")
2179 .add_note("`configuration <name>`")
2180 .add_note("`open`")
2181 .add_note("see IEEE 1076-2008 section 7.3.2.2"),
2182 );
2183 return Err(Reported);
2184 }
2185 })
2186 } else {
2187 None
2188 };
2189
2190 let gm = try_map_aspect(p, Kw::Generic)?;
2192
2193 let pm = try_map_aspect(p, Kw::Port)?;
2195
2196 if entity.is_some() || gm.is_some() || pm.is_some() {
2197 require(p, Semicolon)?;
2198 }
2199 span.expand(p.last_span());
2200 Ok(ast::BindingInd {
2201 span: span,
2202 entity: entity,
2203 generics: gm,
2204 ports: pm,
2205 })
2206}
2207
2208pub fn parse_block_comp_spec<P: Parser>(p: &mut P) -> ReportedResult<Spanned<ast::BlockCompSpec>> {
2218 let mut span = p.peek(0).span;
2219
2220 let spec = match (p.peek(0).value, p.peek(1).value) {
2222 (Keyword(Kw::Others), _) => {
2223 p.bump();
2224 require(p, Colon)?;
2225 let name = parse_name(p)?;
2226 ast::BlockCompSpec::CompOthers(name)
2227 }
2228
2229 (Keyword(Kw::All), _) => {
2230 p.bump();
2231 require(p, Colon)?;
2232 let name = parse_name(p)?;
2233 ast::BlockCompSpec::CompAll(name)
2234 }
2235
2236 (Ident(_), Comma) | (Ident(_), Colon) => {
2237 let names = separated_nonempty(p, Comma, Colon, "label", |p| {
2238 parse_ident(p, "label").map(|n| n.into())
2239 })?;
2240 require(p, Colon)?;
2241 let name = parse_name(p)?;
2242 ast::BlockCompSpec::CompNames(names, name)
2243 }
2244
2245 (wrong, _) => {
2246 if let Some(name) = try_name(p)? {
2247 ast::BlockCompSpec::Block(name)
2248 } else {
2249 let sp = p.peek(0).span;
2250 p.emit(
2251 DiagBuilder2::error(format!(
2252 "Expected block name, component label, `all`, or `others`, found {} \
2253 instead",
2254 wrong
2255 ))
2256 .span(sp),
2257 );
2258 return Err(Reported);
2259 }
2260 }
2261 };
2262
2263 span.expand(p.last_span());
2264 Ok(Spanned::new(spec, span))
2265}
2266
2267pub fn parse_config_spec<P: Parser>(p: &mut P) -> ReportedResult<ast::CfgSpec> {
2273 let mut span = p.peek(0).span;
2274 require(p, Keyword(Kw::For))?;
2275 let spec = parse_block_comp_spec(p)?;
2276 let bind = parse_binding_ind(p)?;
2277 let vunits = repeat(p, |p| -> ReportedResult<Option<()>> {
2278 if p.peek(0).value == Keyword(Kw::Use) && p.peek(1).value == Keyword(Kw::Vunit) {
2279 Ok(Some(parse_vunit_binding_ind(p)?))
2280 } else {
2281 Ok(None)
2282 }
2283 })?;
2284 if accept(p, Keyword(Kw::End)) {
2285 require(p, Keyword(Kw::For))?;
2286 require(p, Semicolon)?;
2287 }
2288 span.expand(p.last_span());
2289 Ok(ast::CfgSpec {
2290 span: span,
2291 spec: spec,
2292 bind: bind,
2293 vunits: vunits,
2294 })
2295}
2296
2297pub fn parse_attr_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::AttrDecl> {
2306 let mut span = p.peek(0).span;
2307 require(p, Keyword(Kw::Attribute))?;
2308 let name = parse_ident(p, "attribute name")?;
2309
2310 if accept(p, Colon) {
2313 let ty = parse_name(p)?;
2314 require(p, Semicolon)?;
2315 span.expand(p.last_span());
2316 Ok(ast::AttrDecl {
2317 id: Default::default(),
2318 span: span,
2319 name: name,
2320 data: ast::AttrData::Decl(ty),
2321 })
2322 } else if accept(p, Keyword(Kw::Of)) {
2323 let target = match p.peek(0).value {
2325 Keyword(Kw::Others) => {
2326 p.bump();
2327 ast::AttrTarget::Others
2328 }
2329 Keyword(Kw::All) => {
2330 p.bump();
2331 ast::AttrTarget::All
2332 }
2333 _ => {
2334 let l = separated_nonempty(p, Comma, Colon, "name", |p| {
2335 let name = parse_name(p)?;
2336 let sig = try_flanked(p, Brack, parse_signature)?;
2337 Ok((name, sig))
2338 })?;
2339 ast::AttrTarget::List(l)
2340 }
2341 };
2342
2343 require(p, Colon)?;
2345 let cls = parse_entity_class(p)?;
2346
2347 require(p, Keyword(Kw::Is))?;
2349 let expr = parse_expr(p)?;
2350 require(p, Semicolon)?;
2351 span.expand(p.last_span());
2352 Ok(ast::AttrDecl {
2353 id: Default::default(),
2354 span: span,
2355 name: name,
2356 data: ast::AttrData::Spec {
2357 target: target,
2358 cls: cls,
2359 expr: expr,
2360 },
2361 })
2362 } else {
2363 let pk = p.peek(0);
2364 p.emit(
2365 DiagBuilder2::error(format!(
2366 "Expected `:` or `of` after attribute name, found {} instead",
2367 pk.value
2368 ))
2369 .span(pk.span)
2370 .add_note("see IEEE 1076-2008 sections 6.7 and 7.2"),
2371 );
2372 Err(Reported)
2373 }
2374}
2375
2376pub fn parse_entity_class<P: Parser>(p: &mut P) -> ReportedResult<ast::EntityClass> {
2401 let pk = p.peek(0);
2402 let cls = match pk.value {
2403 Keyword(Kw::Architecture) => ast::EntityClass::Arch,
2404 Keyword(Kw::Component) => ast::EntityClass::Comp,
2405 Keyword(Kw::Configuration) => ast::EntityClass::Cfg,
2406 Keyword(Kw::Constant) => ast::EntityClass::Const,
2407 Keyword(Kw::Entity) => ast::EntityClass::Entity,
2408 Keyword(Kw::File) => ast::EntityClass::File,
2409 Keyword(Kw::Function) => ast::EntityClass::Func,
2410 Keyword(Kw::Group) => ast::EntityClass::Group,
2411 Keyword(Kw::Label) => ast::EntityClass::Label,
2412 Keyword(Kw::Literal) => ast::EntityClass::Literal,
2413 Keyword(Kw::Package) => ast::EntityClass::Pkg,
2414 Keyword(Kw::Procedure) => ast::EntityClass::Proc,
2415 Keyword(Kw::Property) => ast::EntityClass::Prop,
2416 Keyword(Kw::Sequence) => ast::EntityClass::Seq,
2417 Keyword(Kw::Signal) => ast::EntityClass::Signal,
2418 Keyword(Kw::Subtype) => ast::EntityClass::Subtype,
2419 Keyword(Kw::Type) => ast::EntityClass::Type,
2420 Keyword(Kw::Units) => ast::EntityClass::Units,
2421 Keyword(Kw::Variable) => ast::EntityClass::Var,
2422 wrong => {
2423 p.emit(
2424 DiagBuilder2::error(format!("Expected entity class, found {} instead", wrong))
2425 .span(pk.span)
2426 .add_note(
2427 "An entity class is any of the keywords `architecture`, `component`, \
2428 `configuration`, `constant`, `entity`, `file`, `function`, `group`, \
2429 `label`, `literal`, `package`, `procedure`, `property`, `sequence`, \
2430 `signal`, `subtype`, `type`, `units`, or `variable`",
2431 )
2432 .add_note("see IEEE 1076-2008 section 7.2"),
2433 );
2434 return Err(Reported);
2435 }
2436 };
2437 p.bump();
2438 Ok(cls)
2439}
2440
2441pub fn parse_group_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::GroupDecl> {
2450 let mut span = p.peek(0).span;
2451 require(p, Keyword(Kw::Group))?;
2452 let name = parse_ident(p, "group name")?;
2453
2454 let data = if accept(p, Colon) {
2457 let ty = parse_name(p)?;
2458 ast::GroupData::Decl(ty)
2459 } else if accept(p, Keyword(Kw::Is)) {
2460 let elems = flanked(p, Paren, |p| {
2461 separated_nonempty(p, Comma, CloseDelim(Paren), "group element", |p| {
2462 let cls = parse_entity_class(p)?;
2463 let open = accept(p, LtGt);
2464 Ok((cls, open))
2465 })
2466 .map_err(|e| e.into())
2467 })?;
2468 ast::GroupData::Temp(elems)
2469 } else {
2470 let pk = p.peek(0);
2471 p.emit(
2472 DiagBuilder2::error(format!(
2473 "Expected `:` or `is` after group name, found {} instead",
2474 pk.value
2475 ))
2476 .span(pk.span)
2477 .add_note("`group <name> is ...` declares a group template")
2478 .add_note("`group <name> : ...` declares group")
2479 .add_note("see IEEE 1076-2008 sections 6.9 and 6.10"),
2480 );
2481 return Err(Reported);
2482 };
2483
2484 require(p, Semicolon)?;
2485 span.expand(p.last_span());
2486 Ok(ast::GroupDecl {
2487 id: Default::default(),
2488 span: span,
2489 name: name,
2490 data: data,
2491 })
2492}
2493
2494pub fn parse_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::Stmt> {
2496 let mut span = p.peek(0).span;
2497
2498 let label = try_label(p);
2500
2501 let data = match p.peek(0).value {
2505 Keyword(Kw::Wait) => parse_wait_stmt(p)?,
2506 Keyword(Kw::Assert) => parse_assert_stmt(p)?,
2507 Keyword(Kw::Report) => parse_report_stmt(p)?,
2508
2509 Keyword(Kw::If) => match earliest(
2513 p,
2514 &[Keyword(Kw::Generate), Keyword(Kw::Then), Keyword(Kw::End)],
2515 )
2516 .value
2517 {
2518 Keyword(Kw::Generate) => parse_if_generate_stmt(p, label)?,
2519 _ => parse_if_stmt(p, label)?,
2520 },
2521
2522 Keyword(Kw::Case) => match earliest(
2526 p,
2527 &[Keyword(Kw::Generate), Keyword(Kw::Is), Keyword(Kw::End)],
2528 )
2529 .value
2530 {
2531 Keyword(Kw::Generate) => parse_case_generate_stmt(p, label)?,
2532 _ => parse_case_stmt(p, label)?,
2533 },
2534
2535 Keyword(Kw::For) => match earliest(
2539 p,
2540 &[Keyword(Kw::Generate), Keyword(Kw::Loop), Keyword(Kw::End)],
2541 )
2542 .value
2543 {
2544 Keyword(Kw::Generate) => parse_for_generate_stmt(p, label)?,
2545 _ => parse_loop_stmt(p, label)?,
2546 },
2547 Keyword(Kw::While) | Keyword(Kw::Loop) => parse_loop_stmt(p, label)?,
2548
2549 Keyword(Kw::Next) | Keyword(Kw::Exit) => parse_nexit_stmt(p)?,
2550 Keyword(Kw::Return) => parse_return_stmt(p)?,
2551 Keyword(Kw::Null) => parse_null_stmt(p)?,
2552 Keyword(Kw::Block) => parse_block_stmt(p, label)?,
2553 Keyword(Kw::Process) => parse_proc_stmt(p, label)?,
2554 Keyword(Kw::With) => parse_select_assign(p)?,
2555 Keyword(Kw::Component) | Keyword(Kw::Entity) | Keyword(Kw::Configuration) => {
2556 let target = match p.peek(0).value {
2557 Keyword(Kw::Component) => ast::InstTarget::Comp,
2558 Keyword(Kw::Entity) => ast::InstTarget::Entity,
2559 Keyword(Kw::Configuration) => ast::InstTarget::Cfg,
2560 _ => unreachable!(),
2561 };
2562 p.bump();
2563 let name = parse_name(p)?;
2564 parse_inst_or_call_tail(p, Some(target), name)?
2565 }
2566
2567 wrong => {
2568 if let Some(name) = try_name(p)? {
2569 let span = name.span;
2571 match p.peek(0).value {
2572 Leq | VarAssign => {
2573 parse_assign_tail(p, Spanned::new(ast::AssignTarget::Name(name), span))?
2574 }
2575 _ => parse_inst_or_call_tail(p, None, name)?,
2576 }
2577 } else if let Some(expr) = try_paren_expr(p)? {
2578 let span = expr.span;
2581 parse_assign_tail(p, Spanned::new(ast::AssignTarget::Aggregate(expr), span))?
2582 } else {
2583 let q = p.peek(0).span;
2585 p.emit(
2586 DiagBuilder2::error(format!("Expected statement, found {} instead", wrong))
2587 .span(q)
2588 .add_note("see IEEE 1076-2008 section 10"),
2589 );
2590 return Err(Reported);
2591 }
2592 }
2593 };
2594
2595 span.expand(p.last_span());
2596 Ok(ast::Stmt {
2597 id: Default::default(),
2598 span: span,
2599 label: label,
2600 data: data,
2601 })
2602}
2603
2604pub fn try_label<P: Parser>(p: &mut P) -> Option<Spanned<Name>> {
2608 if let (
2609 Spanned {
2610 value: Ident(n),
2611 span,
2612 },
2613 Colon,
2614 ) = (p.peek(0), p.peek(1).value)
2615 {
2616 p.bump();
2617 p.bump();
2618 Some(Spanned::new(n, span))
2619 } else {
2620 None
2621 }
2622}
2623
2624pub fn parse_wait_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2630 require(p, Keyword(Kw::Wait))?;
2631
2632 let on = if accept(p, Keyword(Kw::On)) {
2634 let mut names_span = p.peek(0).span;
2635 let names = separated_nonempty(
2636 p,
2637 Comma,
2638 token_predicate!(Keyword(Kw::Until), Keyword(Kw::For), Semicolon),
2639 "signal name",
2640 parse_name,
2641 )?;
2642 names_span.expand(p.last_span());
2643 Some(Spanned::new(names, names_span))
2644 } else {
2645 None
2646 };
2647
2648 let until = if accept(p, Keyword(Kw::Until)) {
2650 Some(parse_expr(p)?)
2651 } else {
2652 None
2653 };
2654
2655 let time = if accept(p, Keyword(Kw::For)) {
2657 Some(parse_expr(p)?)
2658 } else {
2659 None
2660 };
2661
2662 require(p, Semicolon)?;
2663 Ok(ast::WaitStmt {
2664 on: on,
2665 until: until,
2666 time: time,
2667 })
2668}
2669
2670pub fn parse_assert_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2676 require(p, Keyword(Kw::Assert))?;
2677 let cond = parse_expr(p)?;
2678
2679 let report = if accept(p, Keyword(Kw::Report)) {
2681 Some(parse_expr(p)?)
2682 } else {
2683 None
2684 };
2685
2686 let severity = if accept(p, Keyword(Kw::Severity)) {
2688 Some(parse_expr(p)?)
2689 } else {
2690 None
2691 };
2692
2693 require(p, Semicolon)?;
2694 Ok(ast::AssertStmt {
2695 cond: cond,
2696 report: report,
2697 severity: severity,
2698 })
2699}
2700
2701pub fn parse_report_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2707 require(p, Keyword(Kw::Report))?;
2708 let msg = parse_expr(p)?;
2709
2710 let severity = if accept(p, Keyword(Kw::Severity)) {
2712 Some(parse_expr(p)?)
2713 } else {
2714 None
2715 };
2716
2717 require(p, Semicolon)?;
2718 Ok(ast::ReportStmt {
2719 msg: msg,
2720 severity: severity,
2721 })
2722}
2723
2724pub fn parse_if_stmt<P: Parser>(
2734 p: &mut P,
2735 label: Option<Spanned<Name>>,
2736) -> ReportedResult<ast::StmtData> {
2737 require(p, Keyword(Kw::If))?;
2738
2739 let conds = separated_nonempty(
2741 p,
2742 Keyword(Kw::Elsif),
2743 token_predicate!(Keyword(Kw::Else), Keyword(Kw::End)),
2744 "if branch",
2745 |p| {
2746 let cond = parse_expr(p)?;
2747 require(p, Keyword(Kw::Then))?;
2748 let stmts = repeat_until(
2749 p,
2750 token_predicate!(Keyword(Kw::Elsif), Keyword(Kw::Else), Keyword(Kw::End)),
2751 parse_stmt,
2752 )?;
2753 Ok((
2754 cond,
2755 ast::StmtBody {
2756 id: Default::default(),
2757 stmts: stmts,
2758 },
2759 ))
2760 },
2761 )?;
2762
2763 let alt = if accept(p, Keyword(Kw::Else)) {
2765 Some(ast::StmtBody {
2766 id: Default::default(),
2767 stmts: repeat_until(p, Keyword(Kw::End), parse_stmt)?,
2768 })
2769 } else {
2770 None
2771 };
2772
2773 require(p, Keyword(Kw::End))?;
2775 require(p, Keyword(Kw::If))?;
2776 parse_optional_matching_ident(p, label, "if statement", "section 10.8");
2777 require(p, Semicolon)?;
2778 Ok(ast::IfStmt {
2779 conds: conds,
2780 alt: alt,
2781 })
2782}
2783
2784pub fn parse_case_stmt<P: Parser>(
2790 p: &mut P,
2791 label: Option<Spanned<Name>>,
2792) -> ReportedResult<ast::StmtData> {
2793 require(p, Keyword(Kw::Case))?;
2794 let has_qm = accept(p, Qmark);
2795 let switch = parse_expr(p)?;
2796 require(p, Keyword(Kw::Is))?;
2797
2798 let cases = repeat(p, |p| -> ReportedResult<Option<(_, _)>> {
2800 if accept(p, Keyword(Kw::When)) {
2801 let mut choices_span = p.peek(0).span;
2802 let choices = separated_nonempty(p, Pipe, Arrow, "choice", parse_expr)?;
2803 choices_span.expand(p.last_span());
2804 require(p, Arrow)?;
2805 let stmts = repeat_until(
2806 p,
2807 token_predicate!(Keyword(Kw::When), Keyword(Kw::End)),
2808 parse_stmt,
2809 )?;
2810 Ok(Some((
2811 Spanned::new(choices, choices_span),
2812 ast::StmtBody {
2813 id: Default::default(),
2814 stmts: stmts,
2815 },
2816 )))
2817 } else {
2818 Ok(None)
2819 }
2820 })?;
2821
2822 require(p, Keyword(Kw::End))?;
2824 require(p, Keyword(Kw::Case))?;
2825 let trail_qm = accept(p, Qmark); parse_optional_matching_ident(p, label, "case statement", "section 10.9");
2827 require(p, Semicolon)?;
2828 Ok(ast::CaseStmt {
2829 qm: has_qm,
2830 switch: switch,
2831 cases: cases,
2832 })
2833}
2834
2835pub fn parse_loop_stmt<P: Parser>(
2841 p: &mut P,
2842 label: Option<Spanned<Name>>,
2843) -> ReportedResult<ast::StmtData> {
2844 let pk = p.peek(0);
2846 let scheme = match pk.value {
2847 Keyword(Kw::While) => {
2848 p.bump();
2849 let cond = parse_expr(p)?;
2850 ast::LoopScheme::While(cond)
2851 }
2852 Keyword(Kw::For) => {
2853 p.bump();
2854 let param = parse_ident(p, "loop parameter name")?;
2855 require(p, Keyword(Kw::In))?;
2856 let range = parse_expr(p)?;
2857 ast::LoopScheme::For(param.into(), range)
2858 }
2859 _ => ast::LoopScheme::Loop,
2860 };
2861
2862 require(p, Keyword(Kw::Loop))?;
2864 let stmts = repeat_until(p, Keyword(Kw::End), parse_stmt)?;
2865 require(p, Keyword(Kw::End))?;
2866 require(p, Keyword(Kw::Loop))?;
2867 parse_optional_matching_ident(p, label, "loop statement", "section 10.10");
2868 require(p, Semicolon)?;
2869 Ok(ast::LoopStmt {
2870 scheme: scheme,
2871 body: ast::StmtBody {
2872 id: Default::default(),
2873 stmts: stmts,
2874 },
2875 })
2876}
2877
2878pub fn parse_nexit_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2884 let pk = p.peek(0);
2885 let mode = match pk.value {
2886 Keyword(Kw::Next) => {
2887 p.bump();
2888 ast::NexitMode::Next
2889 }
2890 Keyword(Kw::Exit) => {
2891 p.bump();
2892 ast::NexitMode::Exit
2893 }
2894 _ => {
2895 p.emit(
2896 DiagBuilder2::error(format!(
2897 "Expected `next` or `exit`, found {} instead",
2898 pk.value
2899 ))
2900 .span(pk.span)
2901 .add_note("see IEEE 1076-2008 sections 10.11 and 10.12"),
2902 );
2903 return Err(Reported);
2904 }
2905 };
2906 let target = try_ident(p);
2907 let cond = if accept(p, Keyword(Kw::When)) {
2908 Some(parse_expr(p)?)
2909 } else {
2910 None
2911 };
2912 require(p, Semicolon)?;
2913 Ok(ast::NexitStmt {
2914 mode: mode,
2915 target: target.map(|t| t.into()),
2916 cond: cond,
2917 })
2918}
2919
2920pub fn parse_return_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2926 require(p, Keyword(Kw::Return))?;
2927 let expr = if !accept(p, Semicolon) {
2928 let e = parse_expr(p)?;
2929 require(p, Semicolon)?;
2930 Some(e)
2931 } else {
2932 None
2933 };
2934 Ok(ast::ReturnStmt(expr))
2935}
2936
2937pub fn parse_null_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2943 require(p, Keyword(Kw::Null))?;
2944 require(p, Semicolon)?;
2945 Ok(ast::NullStmt)
2946}
2947
2948pub fn parse_if_generate_stmt<P: Parser>(
2958 p: &mut P,
2959 label: Option<Spanned<Name>>,
2960) -> ReportedResult<ast::StmtData> {
2961 require(p, Keyword(Kw::If))?;
2962
2963 let conds = separated_nonempty(
2965 p,
2966 Keyword(Kw::Elsif),
2967 token_predicate!(Keyword(Kw::Else), Keyword(Kw::End)),
2968 "if generate branch",
2969 |p| {
2970 let label = try_label(p);
2971 let cond = parse_expr(p)?;
2972 require(p, Keyword(Kw::Generate))?;
2973 let body = parse_generate_body(
2974 p,
2975 label,
2976 token_predicate!(Keyword(Kw::Elsif), Keyword(Kw::Else), Keyword(Kw::End)),
2977 )?;
2978 Ok((cond, body))
2979 },
2980 )?;
2981
2982 let alt = if accept(p, Keyword(Kw::Else)) {
2984 let label = try_label(p);
2985 require(p, Keyword(Kw::Generate))?;
2986 let body = parse_generate_body(p, label, Keyword(Kw::End))?;
2987 Some(body)
2988 } else {
2989 None
2990 };
2991
2992 require(p, Keyword(Kw::End))?;
2994 require(p, Keyword(Kw::Generate))?;
2995 parse_optional_matching_ident(p, label, "generate statement", "section 11.8");
2996 require(p, Semicolon)?;
2997 Ok(ast::IfGenStmt {
2998 conds: conds,
2999 alt: alt,
3000 })
3001}
3002
3003pub fn parse_case_generate_stmt<P: Parser>(
3009 p: &mut P,
3010 label: Option<Spanned<Name>>,
3011) -> ReportedResult<ast::StmtData> {
3012 require(p, Keyword(Kw::Case))?;
3013 let switch = parse_expr(p)?;
3014 require(p, Keyword(Kw::Generate))?;
3015
3016 let cases = repeat(
3018 p,
3019 |p| -> ReportedResult<Option<(Spanned<Vec<ast::Expr>>, ast::GenBody)>> {
3020 if accept(p, Keyword(Kw::When)) {
3021 let label = try_label(p);
3022 let mut choices_span = p.peek(0).span;
3023 let choices = separated_nonempty(p, Pipe, Arrow, "choice", parse_expr)?;
3024 choices_span.expand(p.last_span());
3025 require(p, Arrow)?;
3026 let body = parse_generate_body(
3027 p,
3028 label,
3029 token_predicate!(Keyword(Kw::When), Keyword(Kw::End)),
3030 )?;
3031 Ok(Some((Spanned::new(choices, choices_span), body)))
3032 } else {
3033 Ok(None)
3034 }
3035 },
3036 )?;
3037
3038 require(p, Keyword(Kw::End))?;
3040 require(p, Keyword(Kw::Generate))?;
3041 parse_optional_matching_ident(p, label, "generate statement", "section 11.8");
3042 require(p, Semicolon)?;
3043 Ok(ast::CaseGenStmt {
3044 switch: switch,
3045 cases: cases,
3046 })
3047}
3048
3049pub fn parse_for_generate_stmt<P: Parser>(
3055 p: &mut P,
3056 label: Option<Spanned<Name>>,
3057) -> ReportedResult<ast::StmtData> {
3058 require(p, Keyword(Kw::For))?;
3059 let param = parse_ident(p, "loop parameter name")?;
3060 require(p, Keyword(Kw::In))?;
3061 let range = parse_expr(p)?;
3062 require(p, Keyword(Kw::Generate))?;
3063 let body = parse_generate_body(p, label, Keyword(Kw::End))?;
3064 require(p, Keyword(Kw::End))?;
3065 require(p, Keyword(Kw::Generate))?;
3066 parse_optional_matching_ident(p, label, "generate statement", "section 11.8");
3067 require(p, Semicolon)?;
3068 Ok(ast::ForGenStmt {
3069 param: param.into(),
3070 range: range,
3071 body: body,
3072 })
3073}
3074
3075pub fn parse_generate_body<P: Parser, T>(
3081 p: &mut P,
3082 label: Option<Spanned<Name>>,
3083 term: T,
3084) -> ReportedResult<ast::GenBody>
3085where
3086 T: Predicate<P>,
3087{
3088 let mut span = p.peek(0).span;
3089
3090 let decl_items = repeat(p, |p| {
3094 if p.peek(0).value.is_ident() && p.peek(1).value == Colon {
3096 return Ok(None);
3097 }
3098 if p.peek(0).value == Keyword(Kw::Component) && p.peek(2).value != Keyword(Kw::Is) {
3100 return Ok(None);
3101 }
3102 if p.peek(0).value == Keyword(Kw::For)
3109 && earliest(p, &[Keyword(Kw::Loop), Keyword(Kw::Generate), Semicolon]).value
3110 == Semicolon
3111 {
3112 return Ok(None);
3113 }
3114
3115 try_decl_item(p)
3116 })?;
3117
3118 let has_begin = accept(p, Keyword(Kw::Begin));
3121 if !decl_items.is_empty() && !has_begin {
3122 let pk = p.peek(0);
3123 p.emit(
3124 DiagBuilder2::error(format!(
3125 "`begin` is required before {}, to separate it from the preceding declarative \
3126 items",
3127 pk.value
3128 ))
3129 .span(pk.span),
3130 );
3131 return Err(Reported);
3132 }
3133
3134 let stmts = repeat_until(p, term, parse_stmt)?;
3136
3137 let has_end = if p.peek(0).value == Keyword(Kw::End) && p.peek(1).value != Keyword(Kw::Generate)
3139 {
3140 p.bump();
3141 parse_optional_matching_ident(p, label, "generate body", "section 11.8");
3142 require(p, Semicolon)?;
3143 true
3144 } else {
3145 false
3146 };
3147
3148 span.expand(p.last_span());
3149 Ok(ast::GenBody {
3150 id: Default::default(),
3151 label: label,
3152 span: span,
3153 decls: decl_items,
3154 stmts: stmts,
3155 })
3156}
3157
3158pub fn parse_block_stmt<P: Parser>(
3164 p: &mut P,
3165 label: Option<Spanned<Name>>,
3166) -> ReportedResult<ast::StmtData> {
3167 require(p, Keyword(Kw::Block))?;
3168 let guard = try_flanked(p, Paren, parse_expr)?;
3169 accept(p, Keyword(Kw::Is));
3170 let decl_items = repeat(p, try_decl_item)?;
3171 require(p, Keyword(Kw::Begin))?;
3172 let stmts = repeat_until(p, Keyword(Kw::End), parse_stmt)?;
3173 require(p, Keyword(Kw::End))?;
3174 require(p, Keyword(Kw::Block))?;
3175 parse_optional_matching_ident(p, label, "block", "section 11.2");
3176 require(p, Semicolon)?;
3177 Ok(ast::BlockStmt {
3178 guard: guard,
3179 decls: decl_items,
3180 stmts: stmts,
3181 })
3182}
3183
3184pub fn parse_proc_stmt<P: Parser>(
3190 p: &mut P,
3191 label: Option<Spanned<Name>>,
3192) -> ReportedResult<ast::StmtData> {
3193 require(p, Keyword(Kw::Process))?;
3194
3195 let sensitivity = try_flanked(p, Paren, |p| {
3197 if accept(p, Keyword(Kw::All)) {
3198 Ok(ast::Sensitivity::All)
3199 } else {
3200 let l = separated(p, Comma, CloseDelim(Paren), "signal name", parse_name)?;
3201 Ok(ast::Sensitivity::List(l))
3202 }
3203 })?;
3204 accept(p, Keyword(Kw::Is));
3205
3206 let decl_items = repeat(p, try_decl_item)?;
3208
3209 require(p, Keyword(Kw::Begin))?;
3211 let stmts = repeat_until(p, Keyword(Kw::End), parse_stmt)?;
3212 require(p, Keyword(Kw::End))?;
3213
3214 let postponed = accept(p, Keyword(Kw::Postponed));
3216 require(p, Keyword(Kw::Process))?;
3217 parse_optional_matching_ident(p, label, "process", "section 11.3");
3218 require(p, Semicolon)?;
3219 Ok(ast::ProcStmt {
3220 sensitivity: sensitivity,
3221 decls: decl_items,
3222 stmts: stmts,
3223 postponed: postponed,
3224 })
3225}
3226
3227pub fn parse_assign_tail<P: Parser>(
3242 p: &mut P,
3243 target: Spanned<ast::AssignTarget>,
3244) -> ReportedResult<ast::StmtData> {
3245 let (kind, guarded) = parse_assign_dst_tail(p)?;
3246 let (mode, mode_span) = match p.peek(0).value {
3247 Keyword(Kw::Release) => {
3248 let mut span = p.peek(0).span;
3249 p.bump();
3250 let fm = try_force_mode(p);
3251 span.expand(p.last_span());
3252 (ast::AssignMode::Release(fm), span)
3253 }
3254
3255 Keyword(Kw::Force) => {
3256 let mut span = p.peek(0).span;
3257 p.bump();
3258 let fm = try_force_mode(p);
3259 let waves = parse_cond_waves(p)?;
3260 span.expand(p.last_span());
3261 (ast::AssignMode::Force(fm, waves), span)
3262 }
3263
3264 _ => {
3265 let mut span = p.peek(0).span;
3266 let dm = try_delay_mech(p)?;
3267 let waves = parse_cond_waves(p)?;
3268 span.expand(p.last_span());
3269 (ast::AssignMode::Normal(dm, waves), span)
3270 }
3271 };
3272 require(p, Semicolon)?;
3273 Ok(ast::AssignStmt {
3274 target: target,
3275 kind: kind,
3276 guarded: guarded,
3277 mode: Spanned::new(mode, mode_span),
3278 })
3279}
3280
3281pub fn parse_select_assign<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
3292 require(p, Keyword(Kw::With))?;
3293 let select = parse_expr(p)?;
3294 require(p, Keyword(Kw::Select))?;
3295 let qm = accept(p, Qmark);
3296
3297 let target = if let Some(name) = try_name(p)? {
3300 let span = name.span;
3301 Spanned::new(ast::AssignTarget::Name(name), span)
3302 } else if let Some(exprs) = try_paren_expr(p)? {
3303 let span = exprs.span;
3304 Spanned::new(ast::AssignTarget::Aggregate(exprs), span)
3305 } else {
3306 let pk = p.peek(0);
3307 p.emit(
3308 DiagBuilder2::error(format!(
3309 "Expected signal name, variable name or aggregate, found {} instead",
3310 pk.value
3311 ))
3312 .span(pk.span)
3313 .add_note("see IEEE 1076-2008 section 10.5"),
3314 );
3315 return Err(Reported);
3316 };
3317
3318 let (kind, guarded) = parse_assign_dst_tail(p)?;
3320
3321 let (mode, waves) = match p.peek(0).value {
3323 Keyword(Kw::Force) => {
3324 p.bump();
3325 let fm = try_force_mode(p);
3326 let waves = parse_selected_waves(p)?;
3327 (ast::SelectAssignMode::Force(fm), waves)
3328 }
3329
3330 _ => {
3331 let dm = try_delay_mech(p)?;
3332 let waves = parse_selected_waves(p)?;
3333 (ast::SelectAssignMode::Normal(dm), waves)
3334 }
3335 };
3336 require(p, Semicolon)?;
3337 Ok(ast::SelectAssignStmt {
3338 select: select,
3339 qm: qm,
3340 target: target,
3341 kind: kind,
3342 guarded: guarded,
3343 mode: mode,
3344 waves: waves,
3345 })
3346}
3347
3348pub fn parse_assign_dst_tail<P: Parser>(p: &mut P) -> ReportedResult<(ast::AssignKind, bool)> {
3349 let pk = p.peek(0);
3350 let kind = match pk.value {
3351 Leq => ast::AssignKind::Signal,
3352 VarAssign => ast::AssignKind::Var,
3353 _ => {
3354 p.emit(
3355 DiagBuilder2::error(format!(
3356 "Expected `<=` or `:=` after assignment target, found {} instead",
3357 pk.value
3358 ))
3359 .span(pk.span)
3360 .add_note("see IEEE 1076-2008 section 10.5"),
3361 );
3362 return Err(Reported);
3363 }
3364 };
3365 p.bump();
3366 let guarded = accept(p, Keyword(Kw::Guarded));
3367 Ok((kind, guarded))
3368}
3369
3370pub fn try_force_mode<P: Parser>(p: &mut P) -> Option<Spanned<ast::ForceMode>> {
3371 if let Some(m) = match p.peek(0).value {
3372 Keyword(Kw::In) => Some(ast::ForceMode::In),
3373 Keyword(Kw::Out) => Some(ast::ForceMode::Out),
3374 _ => None,
3375 } {
3376 p.bump();
3377 Some(Spanned::new(m, p.last_span()))
3378 } else {
3379 None
3380 }
3381}
3382
3383pub fn try_delay_mech<P: Parser>(p: &mut P) -> ReportedResult<Option<Spanned<ast::DelayMech>>> {
3389 Ok(match p.peek(0).value {
3390 Keyword(Kw::Transport) => {
3391 p.bump();
3392 Some(Spanned::new(ast::DelayMech::Transport, p.last_span()))
3393 }
3394 Keyword(Kw::Inertial) => {
3395 p.bump();
3396 Some(Spanned::new(ast::DelayMech::Inertial, p.last_span()))
3397 }
3398 Keyword(Kw::Reject) => {
3399 p.bump();
3400 let sp = p.last_span();
3401 let expr = parse_expr(p)?;
3402 require(p, Keyword(Kw::Inertial))?;
3403 Some(Spanned::new(ast::DelayMech::InertialReject(expr), sp))
3404 }
3405 _ => return Ok(None),
3406 })
3407}
3408
3409pub fn parse_cond_waves<P: Parser>(p: &mut P) -> ReportedResult<Vec<ast::CondWave>> {
3415 separated_nonempty(p, Keyword(Kw::Else), Semicolon, "waveform", |p| {
3416 let wave = parse_wave(p)?;
3417 let cond = if accept(p, Keyword(Kw::When)) {
3418 Some(parse_expr(p)?)
3419 } else {
3420 None
3421 };
3422 Ok(ast::CondWave(wave, cond))
3423 })
3424 .map_err(|e| e.into())
3425}
3426
3427pub fn parse_selected_waves<P: Parser>(p: &mut P) -> ReportedResult<Vec<ast::SelectWave>> {
3433 separated_nonempty(p, Comma, Semicolon, "waveform", |p| {
3434 let wave = parse_wave(p)?;
3435 require(p, Keyword(Kw::When))?;
3436 let mut choices_span = p.peek(0).span;
3437 let choices = separated_nonempty(
3438 p,
3439 Pipe,
3440 token_predicate!(Comma, Semicolon),
3441 "choice",
3442 parse_expr,
3443 )?;
3444 choices_span.expand(p.last_span());
3445 Ok(ast::SelectWave(wave, Spanned::new(choices, choices_span)))
3446 })
3447 .map_err(|e| e.into())
3448}
3449
3450pub fn parse_wave<P: Parser>(p: &mut P) -> ReportedResult<ast::Wave> {
3456 let mut span = p.peek(0).span;
3457 let elems = if accept(p, Keyword(Kw::Unaffected)) {
3458 None
3459 } else {
3460 Some(separated(
3461 p,
3462 Comma,
3463 token_predicate!(Keyword(Kw::When), Semicolon),
3464 "waveform element",
3465 |p| {
3466 let expr = parse_expr(p)?;
3467 let delay = if accept(p, Keyword(Kw::After)) {
3468 Some(parse_expr(p)?)
3469 } else {
3470 None
3471 };
3472 Ok((expr, delay))
3473 },
3474 )?)
3475 };
3476 span.expand(p.last_span());
3477 Ok(ast::Wave {
3478 span: span,
3479 elems: elems,
3480 })
3481}
3482
3483pub fn parse_inst_or_call_tail<P: Parser>(
3490 p: &mut P,
3491 target: Option<ast::InstTarget>,
3492 name: ast::CompoundName,
3493) -> ReportedResult<ast::StmtData> {
3494 let gm = try_map_aspect(p, Kw::Generic)?;
3495 let pm = try_map_aspect(p, Kw::Port)?;
3496 require(p, Semicolon)?;
3497 Ok(ast::InstOrCallStmt {
3498 target: target,
3499 name: name,
3500 generics: gm,
3501 ports: pm,
3502 })
3503}