moore_vhdl_syntax/parser/
rules.rs

1// Copyright (c) 2016-2021 Fabian Schuiki
2
3//! This module implements a first stage recursive descent parser for VHDL. It
4//! can process a stream of input tokens into the coarse, generalized abstract
5//! syntax tree defined in [`ast`]. The grammar productions/rules outlined in
6//! the VHDL standard are collapsed into more general rules as outlined in the
7//! following table.
8//!
9//! | VHDL Standard                        | Generalized to       |
10//! |--------------------------------------|----------------------|
11//! | aggregate                            | paren_expr           |
12//! | array_constraint                     | name                 |
13//! | attribute_declaration                | attr_decl            |
14//! | attribute_name                       | name                 |
15//! | attribute_specification              | attr_decl            |
16//! | block_specification                  | name                 |
17//! | configuration_item                   | decl_item            |
18//! | constraint                           | primary_expr         |
19//! | enumeration_type_definition          | paren_expr           |
20//! | external_name                        | *ignored*            |
21//! | function_call                        | name                 |
22//! | generate_specification               | expr                 |
23//! | generic_clause                       | generic_clause       |
24//! | generic_map_aspect                   | map_aspect           |
25//! | group_declaration                    | group_decl           |
26//! | group_template_declaration           | group_decl           |
27//! | indexed_name                         | name                 |
28//! | interface_subprogram_declaration     | subprog_spec         |
29//! | name                                 | name                 |
30//! | name/character_literal               | primary_name         |
31//! | name/operator_symbol                 | primary_name         |
32//! | name/simple_name                     | primary_name         |
33//! | port_clause                          | port_clause          |
34//! | port_map_aspect                      | map_aspect           |
35//! | range_constraint                     | name                 |
36//! | record_constraint                    | name, paren_expr     |
37//! | resolution_indication                | primary_expr         |
38//! | selected_name                        | name                 |
39//! | slice_name                           | name                 |
40//! | subprogram_body                      | subprog_spec         |
41//! | subprogram_declaration               | subprog_spec         |
42//! | subprogram_instantiation_declaration | subprog_spec         |
43//! | subtype_indication                   | name, primary_expr   |
44//! | target                               | primary_expr         |
45//! | time_expression                      | expr                 |
46//! | type_mark                            | name                 |
47
48use 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
82/// Parse an entire design file. IEEE 1076-2008 section 13.1.
83///
84/// ```text
85/// design_file := {design_unit}+
86/// ```
87pub 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
98/// Parse a single design unit. IEEE 1076-2008 section 13.1.
99///
100/// ```text
101/// design_unit := {context_item} library_unit
102/// library_unit
103///   := entity_decl
104///   := config_decl
105///   := package_decl
106///   := package_inst_decl
107///   := context_decl
108///   := arch_body
109///   := package_body
110/// ```
111pub 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
166/// Parse a context item. IEEE 1076-2008 section 13.4.
167///
168/// ```text
169/// context_item := library_clause | use_clause | context_ref
170/// ```
171pub 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
189/// Parse a library clause. IEEE 1076-2008 section 13.2.
190///
191/// ```text
192/// library_clause := "library" {ident}","+
193/// ```
194pub 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
208/// Parse a use clause. IEEE 1076-2008 section 12.4.
209///
210/// ```text
211/// use_clause := "use" {name}","+
212/// ```
213pub 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
231/// Parse a name. IEEE 1076-2008 section 8.
232pub 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
243/// Try to parse a name. IEEE 1076-2008 section 8.
244pub fn try_name<P: Parser>(p: &mut P) -> ReportedResult<Option<ast::CompoundName>> {
245    // Parse a primary name.
246    let primary = match try_primary_name(p) {
247        Some(pn) => pn,
248        None => return Ok(None),
249    };
250
251    // Wrap it up in a compound name, to be extended with suffices.
252    let name = ast::CompoundName {
253        id: Default::default(),
254        span: primary.span,
255        primary: primary,
256        parts: Vec::new(),
257    };
258
259    // Parse a potential name suffix.
260    parse_name_suffix(p, name).map(|x| Some(x))
261}
262
263/// Try to parse a primary name. IEEE 1076-2008 section 8.
264///
265/// ```text
266/// primary_name := ident | char_lit | string_lit
267/// ```
268pub 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
284/// Parse the suffix to a name. IEEE 1076-2008 section 8.
285///
286/// ```text
287/// name
288///   := primary_name
289///   := name "." (ident | char_lit | string_lit | "all")
290///   := name [signature] "'" ident
291///   := name paren_expr
292/// ```
293pub fn parse_name_suffix<P: Parser>(
294    p: &mut P,
295    mut name: ast::CompoundName,
296) -> ReportedResult<ast::CompoundName> {
297    // Try to parse a selected name.
298    if accept(p, Period) {
299        // Parse the suffix, which is a primary name or the keyword `all`.
300        let suffix = {
301            if let Some(pn) = try_primary_name(p) {
302                ast::NamePart::Select(pn)
303            } else {
304                // `else if accept(...)` breaks on rust 1.15: p borrowed mutably in pattern guard
305                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        // Extend the name
323        name.span.expand(p.last_span());
324        name.parts.push(suffix);
325        return parse_name_suffix(p, name);
326    }
327
328    // Try to parse a signature.
329    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    // Try to parse an attribute name.
336    if p.peek(0).value == Apostrophe && p.peek(1).value != OpenDelim(Paren) {
337        require(p, Apostrophe)?;
338
339        // Unfortunately `range` is a valid attribute name, even though it is
340        // defined as a language keyword. The solution here is quite hacky, but
341        // works: We generate a "range" name on the fly and return it as
342        // attribute name. The downside is that we lose the capitalization that
343        // was present in the source text, which might confuse the user.
344        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    // Try to parse a function call, slice name, or indexed name.
356    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    // Try to parse a range constraint.
363    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    // If we arrive here, none of the suffices matched, and we simply return the
371    // prefix that we have received.
372    Ok(name)
373}
374
375/// Parse the optional trailing name after an entity, configuration, etc., which
376/// must match the name at the beginning of the declaration.
377fn 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
409/// Parse a context declaration. IEEE 1076-2008 section 13.3.
410///
411/// ```text
412/// context_decl :=
413///   "context" ident "is"
414///     {context_item}
415///   "end" ["context"] [ident] ";"
416/// ```
417pub 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
436/// Parse an entity declaration. See IEEE 1076-2008 section 3.2.
437///
438/// ```text
439/// entity_decl :=
440///   "entity" ident "is"
441///     entity_header
442///     entity_decl_part
443///   ["begin" {stmt}]
444///   "end" ["entity"] [ident] ";"
445/// ```
446pub fn parse_entity_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::EntityDecl> {
447    let mut span = p.peek(0).span;
448
449    // Parse the head of the declaration.
450    require(p, Keyword(Kw::Entity))?;
451    let name = parse_ident(p, "entity name")?;
452    require(p, Keyword(Kw::Is))?;
453
454    // Parse the declarative part.
455    let decl_items = repeat(p, try_decl_item)?;
456
457    // Parse the optional statement part.
458    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    // Parse the tail of the declaration.
465    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
479/// Parse a configuration declaration. See IEEE 1076-2008 section 3.4.
480///
481/// ```text
482/// config_decl :=
483///   "configuration" ident "of" name "is"
484///     {config_decl_item}
485///   "end" ["configuration"] [ident] ";"
486/// ```
487pub fn parse_config_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::CfgDecl> {
488    let mut span = p.peek(0).span;
489
490    // Parse the head of the declaration.
491    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    // Parse the configuration declarative items.
498    let decl_items = repeat_until(p, Keyword(Kw::End), parse_block_comp_decl_item)?;
499
500    // Parse the tail of the declaration.
501    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
515/// Parse an architecture body. See IEEE 1076-2008 section 3.3.
516///
517/// ```text
518/// arch_body :=
519///   "architecture" ident "of" name "is"
520///     {decl_item}
521///   "begin"
522///     {stmt}
523///   "end" ["architecture"] [ident] ";"
524/// ```
525pub fn parse_arch_body<P: Parser>(p: &mut P) -> ReportedResult<ast::ArchBody> {
526    let mut span = p.peek(0).span;
527
528    // Parse the head of the body.
529    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    // Parse the declarative and statement parts.
536    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    // Parse the tail of the body.
541    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
556/// Try to parse a generic clause. See IEEE 1076-2008 section 6.5.6.2.
557///
558/// ```text
559/// generic_clause := "generic" "clause" "(" {intf_decl}";"+ ")" ";"
560/// ```
561pub 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
584/// Try to parse a port clause. See IEEE 1076-2008 section 6.5.6.3.
585///
586/// ```text
587/// port_clause := "port" "clause" "(" {intf_decl}";"+ ")" ";"
588/// ```
589pub 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
612/// Parse an interface declaration. These are generally part of an interface
613/// list as they appear in generic and port clauses within for example entity
614/// declarations. See IEEE 1076-2008 section 6.5.1.
615pub 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        // Try to short-circuit a type interface declarations.
625        Keyword(Kw::Type) => return parse_type_decl(p, false).map(|d| ast::IntfDecl::TypeDecl(d)),
626
627        // Try to short-circuit a subprogram interface declaration.
628        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                    // subprog_spec "is" "<>"
636                    Some(ast::SubprogDefault::Any)
637                } else if let Some(name) = try_name(p)? {
638                    // subprog_spec "is" name
639                    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        // Try to short-circuit a package interface declaration.
664        Keyword(Kw::Package) => {
665            let inst = parse_package_inst(p, false)?;
666            return Ok(ast::IntfDecl::PkgInst(inst));
667        }
668
669        // Try to parse one of the object declarations.
670        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    // Parse the object names.
711    let names = separated_nonempty(p, Comma, Colon, "object name", |p| {
712        parse_ident(p, "object name")
713    })?;
714    require(p, Colon)?;
715
716    // Parse the optional mode.
717    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    // Parse the type and optional `bus` keyword.
742    let ty = parse_subtype_ind(p)?;
743    let bus = accept(p, Keyword(Kw::Bus));
744
745    // Parse the optional default expression.
746    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
764/// Try to parse a declarative item. See IEEE 1076-2008 section 3.2.3.
765pub 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        // package_decl := "package" ident "is" ...
769        // package_body := "package" "body" ident "is" ...
770        // package_inst := "package" ident "is" "new" ...
771        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        // type_decl := "type" ...
781        Keyword(Kw::Type) => Some(ast::DeclItem::TypeDecl(parse_type_decl(p, true)?)),
782        // subtype_decl := "subtype" ...
783        Keyword(Kw::Subtype) => Some(ast::DeclItem::SubtypeDecl(parse_subtype_decl(p)?)),
784        // constant_decl := "constant" ...
785        // signal_decl   := "signal" ...
786        // variable_decl := ("variable"|"shared") ...
787        // file_decl     := "file" ...
788        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        // alias_decl := "alias" ...
794        Keyword(Kw::Alias) => Some(ast::DeclItem::AliasDecl(parse_alias_decl(p)?)),
795        // use_clause := "use" ...
796        Keyword(Kw::Use) => Some(ast::DeclItem::UseClause(span, parse_use_clause(p)?)),
797        // subprog_spec := "pure"|"impure"|"procedure"|"function" ...
798        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        // component_decl := "component" ...
803        Keyword(Kw::Component) => Some(ast::DeclItem::CompDecl(parse_component_decl(p)?)),
804        // discon_spec := "disconnect" ...
805        Keyword(Kw::Disconnect) => Some(ast::DeclItem::DisconDecl(parse_discon_spec(p)?)),
806        // config_spec := "for" ...
807        Keyword(Kw::For) => Some(ast::DeclItem::CfgSpec(parse_config_spec(p)?)),
808        // attr_decl := "attribute" ...
809        Keyword(Kw::Attribute) => Some(ast::DeclItem::AttrDecl(parse_attr_decl(p)?)),
810        // generic_clause     := "generic" ...
811        // generic_map_aspect := "generic" "map" ...
812        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        // port_clause     := "port" ...
826        // port_map_aspect := "port" "map" ...
827        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        // group_decl := "group" ...
841        Keyword(Kw::Group) => Some(ast::DeclItem::GroupDecl(parse_group_decl(p)?)),
842        _ => None,
843    })
844}
845
846/// Parse a subprogram declarative item, which is either a subprogram
847/// declaration, body, or instantiation. See IEEE 1076-2008 section 4.2.
848///
849/// ```text
850/// subprog_decl := subprog_spec ";"
851/// subprog_body := subprog_spec "is" ...
852/// subprog_inst := subprog_spec "is" "new" name [signature] [generic_map_aspect] ";"
853/// ```
854pub 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    // Try to parse a subprogram declaration.
859    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    // Try to parse a subprogram body or instantiation.
870    if accept(p, Keyword(Kw::Is)) {
871        // Try to parse a subprogram instantiation. Otherwise fall back to a
872        // subprogram body.
873        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            // TODO: Check if things match once the subprog_spec returns
893            // something useful.
894            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    // If we arrive here, none of the above matched. Emit an error that
912    // describes what we expected.
913    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
925/// Parse a subtype indication. See IEEE 1076-2008 section 6.3.
926///
927/// ```text
928/// subtype_ind
929///   := name
930///   := name name
931///   := paren_expr name
932/// ```
933pub 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    // Try to determine if the subtype indication starts out with a resolution
940    // indication. This might either be another name in front of the subtype
941    // name, or a element resolution in parenthesis.
942    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
962/// Try to parse a parenthesized expression. This is a combination of a variety
963/// of rules from the VHDL grammar. Most notably, it combines the following:
964///
965/// - `aggregate`
966/// - `association_list`
967/// - suffix of `slice_name`
968/// - suffix of `indexed_name`
969/// - suffix of `function_call`
970///
971/// ```text
972/// paren_expr := "(" { [ { expr }"|"+ "=>" ] expr }","+ ")"
973/// ```
974pub 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        // Parse a list of choices, i.e. expressions separated by `|`.
995        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 the expressions are followed by a "=>", what we have parsed is a
1006        // list of choices. Otherwise, ensure that there is only one expression
1007        // in the list.
1008        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            // Emit errors for additional expressions.
1022            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    // Try to handle the easy cases where the next token clearly identifies the
1058    // kind of primary expression that follows.
1059    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            // let mut expr_span = p.peek(0).span;
1087            //
1088            // // Try to parse a name or qualified expression.
1089            // if let Some(expr) = try_name_or_qualified_primary_expr(p)? {
1090            //     span.expand(p.last_span());
1091            //     Some(ast::NewExpr(expr))
1092            // }
1093            //
1094            // // Try to parse a name prefixed by parenthesis.
1095            // else if let Some(paren) = try_paren_expr(p)? {
1096            //     let name = parse_name(p)?;
1097            //     span.expand(p.last_span());
1098            //     expr_span.expand(p.last_span());
1099            //     Some(ast::NewExpr(ast::Expr{
1100            //         span: expr_span,
1101            //         data: ast::ParenPrefixExpr(paren, )
1102            //     }))
1103            // }
1104            //
1105            // // Throw an error.
1106            // else {
1107            //     p.emit(
1108            //         DiagBuilder2::error("Expected subtype or qualified expression after `new`")
1109            //         .span(span)
1110            //     );
1111            //     return Err(Reported);
1112            // }
1113        }
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            // Try to parse a name, which caters for the case of subtype
1131            // indications that are prefixed with element resolution.
1132            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    // Try to parse a name-prefixed primary expression.
1150    if let Some(expr) = try_name_or_qualified_primary_expr(p)? {
1151        return Ok(expr);
1152    }
1153
1154    // If we arrive here, nothing matched. Emit an error that describes what a
1155    // primary expression may entail.
1156    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    // Try to parse a name.
1178    if let Some(name) = try_name(p)? {
1179        // Try to parse another name, for things that look like element
1180        // resolutions.
1181        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        // Try to parse a `'`, which would make this a qualified expression.
1190        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/// The precedence of an expression.
1224#[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
1250/// Parse an expression with a precedence higher than `prec`.
1251///
1252/// ```text
1253/// expr[10] := "inertial" expr[9]
1254/// ```
1255pub 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    // Try to parse a unary operator.
1260    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    // Parse a primary expression.
1278    let primary = parse_primary_expr(p)?;
1279
1280    // Parse any optional expression suffix.
1281    parse_expr_suffix(p, primary, prec)
1282}
1283
1284/// Parse an expression suffix. Given an already parsed expression and its
1285/// precedence, try to parse additional tokens that extend the already parsed
1286/// expression. This is currently limited to binary operations.
1287pub 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    // Try to parse a binary operation.
1295    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    // If we arrive here, none of the suffices matched, so we simply return the
1317    // expression that we have received.
1318    Ok(prefix)
1319}
1320
1321/// Try to interpret a token as a unary operator.
1322fn 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
1343/// Try to interpret a token as a binary operator.
1344fn 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
1390/// Obtain the precedence of a unary operator.
1391fn 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
1402/// Obtain the precedence of a binary operator.
1403fn 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
1421/// Parse a package declaration. See IEEE 1076-2008 section 4.7.
1422///
1423/// ```text
1424/// package_decl :=
1425///   "package" ident "is"
1426///     [generic_clause [generic_map_aspect ";"]]
1427///     {decl_item}
1428///   "end" ["package"] [ident] ";"
1429/// ```
1430pub fn parse_package_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::PkgDecl> {
1431    let mut span = p.peek(0).span;
1432
1433    // Parse the head of the declaration.
1434    require(p, Keyword(Kw::Package))?;
1435    let name = parse_ident(p, "package name")?;
1436    require(p, Keyword(Kw::Is))?;
1437
1438    // Parse the declarative part.
1439    let decl_items = repeat(p, try_decl_item)?;
1440
1441    // Parse the tail of the declaration.
1442    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
1455/// Parse a package body. See IEEE 1076-2008 section 4.8.
1456///
1457/// ```text
1458/// package_decl :=
1459///   "package" "body" ident "is"
1460///     {decl_item}
1461///   "end" ["package" "body"] [ident] ";"
1462/// ```
1463pub 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)); // TODO: add proper warnings if these are missing
1472    accept(p, Keyword(Kw::Body)); // TODO: add proper warnings if these are missing
1473    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
1484/// Parse a package instantiation declaration. See IEEE 1076-2008 section 4.9.
1485///
1486/// ```text
1487/// package_inst := "package" ident "is" "new" name [generic_map] ";"
1488/// ```
1489pub 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
1513/// Try to parse a generic or port map aspect. See IEEE 1076-2008 sections
1514/// 6.5.7.2 and 6.5.7.3.
1515///
1516/// ```text
1517/// map_aspect := ["generic"|"port"] "map" paren_expr
1518/// ```
1519pub 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
1530/// Parse a type declaration. See IEEE 1076-2008 section 6.2.
1531///
1532/// ```text
1533/// type_decl := "type" ident ["is" type_def] ";"
1534/// type_def
1535///   := paren_expr
1536///   := "range" range
1537///   := "range" range units_decl
1538///   := "array" paren_expr "of" subtype_ind
1539///   := "record" {{ident}","+ ":" subtype_ind ";"}+ "end" "record" [ident]
1540///   := "access" subtype_ind
1541///   := "file" "of" name
1542///   := protected_type_decl
1543///   := protected_type_body
1544/// ```
1545pub 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    // Parse the optional type definition. If present, this is a full type
1554    // declaration. Otherwise it is an incomplete type declaration.
1555    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            // Enumeration type definition
1562            OpenDelim(Paren) => ast::EnumType(parse_paren_expr(p)?),
1563
1564            // Integer, float, physical type definition
1565            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            // Array type definition
1590            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            // Record type definition
1600            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            // Access type definition
1619            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            // File type definition
1627            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            // Protected type declaration and body
1636            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            // Emit an error for anything else.
1650            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
1679/// Parse a subtype declaration. See IEEE 1076-2008 section 6.3.
1680///
1681/// ```text
1682/// subtype_decl := "subtype" ident "is" subtype_ind ";"
1683/// ```
1684pub 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
1700/// Parse an alias declaration. See IEEE 1076-2008 section 6.6.
1701///
1702/// ```text
1703/// alias_decl := "alias" alias_desig [":" subtype_ind] "is" name [signature] ";"
1704/// alias_desig := ident | char_lit | string_lit
1705/// ```
1706pub 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
1768/// Parse a constant, signal, variable, or file declaration. See IEEE 1076-2008
1769/// section 6.4.2.
1770///
1771/// ```text
1772/// object_decl := object_kind {ident}","+ ":" subtype_ind [object_details] [":=" expr] ";"
1773/// object_kind
1774///   := "constant"
1775///   := "signal"
1776///   := "variable"
1777///   := "shared" "variable"
1778///   := "file"
1779/// object_details
1780///   := "register"
1781///   := "bus"
1782///   := ["open" expr] "is" expr
1783/// ```
1784pub fn parse_object_decl<P: Parser>(p: &mut P) -> ReportedResult<ast::ObjDecl> {
1785    let mut span = p.peek(0).span;
1786
1787    // Parse the object kind.
1788    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    // Parse the name list and subtype indication.
1824    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    // Parse the additional object details.
1831    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    // Parse the optional initial expression.
1857    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
1875/// Parse a subprogram specification. This covers the initial part of a
1876/// subprogram declaration, body, instantiation, or interface declaration. See
1877/// IEEE 1076-2008 sections 4.2 and 6.5.4. Note that not all combinations of
1878/// keywords and qualifiers that this parser accepts are actually valid.
1879///
1880/// ```text
1881/// subprog_spec :=
1882///   ["pure"|"impure"] "procedure"|"function" primary_name
1883///   ["generic" paren_expr]
1884///   ["generic" "map" paren_expr]
1885///   [["parameter"] paren_expr]
1886///   ["return" name]
1887/// ```
1888pub fn parse_subprog_spec<P: Parser>(p: &mut P) -> ReportedResult<ast::SubprogSpec> {
1889    let mut span = p.peek(0).span;
1890
1891    // Parse the optional purity qualifier.
1892    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    // Parse the subprogram kind.
1905    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    // Parse the name.
1929    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    // Parse the optional generic clause.
1947    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    // Parse the optional generic map aspect.
1963    let gm = try_map_aspect(p, Kw::Generic)?;
1964
1965    // Parse the optional parameter keyword and list.
1966    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    // Parse the optional return type.
1981    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
2000/// Parse a component declaration. See IEEE 1076-2008 section 6.8.
2001///
2002/// ```text
2003/// component_decl :=
2004///   "component" ident ["is"]
2005///     [generic_clause]
2006///     [port_clause]
2007///   "end" ["component"] [ident] ";"
2008/// ```
2009pub 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
2030/// Parse a disconnection specification. See IEEE 1076-2008 section 7.4.
2031///
2032/// ```text
2033/// discon_spec := "disconnect" signal_list ":" name "after" expr ";"
2034/// signal_list := {name}","+ | "others" | "all"
2035/// ```
2036pub 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
2074/// Parse a block or component configuration declarative item.
2075///
2076/// ```text
2077/// block_decl_item
2078///   := use_clause
2079///   := attr_spec
2080///   := group_decl
2081///   := vunit_binding_ind
2082///   := block_comp_config
2083/// ```
2084pub 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        // vunit_binding_ind := "use" "vunit" ...
2087        (Keyword(Kw::Use), Keyword(Kw::Vunit)) => {
2088            parse_vunit_binding_ind(p).map(|i| ast::DeclItem::VunitBindInd(i))
2089        }
2090        // use_clause := "use" ...
2091        (Keyword(Kw::Use), _) => {
2092            let span = p.peek(1).span;
2093            parse_use_clause(p).map(|i| ast::DeclItem::UseClause(span, i))
2094        }
2095        // block_comp_config := "for" ...
2096        (Keyword(Kw::For), _) => parse_block_comp_config(p).map(|i| ast::DeclItem::BlockCompCfg(i)),
2097        // attr_spec := "attribute" ...
2098        (Keyword(Kw::Attribute), _) => parse_attr_decl(p).map(|i| ast::DeclItem::AttrDecl(i)),
2099        // group_decl := "group" ...
2100        (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
2116/// Parse a block or component configuration. See IEEE 1076-2008 sections 3.4.2
2117/// and 3.4.3.
2118///
2119/// ```text
2120/// block_comp_config := "for" block_comp_spec [binding_ind] {block_config_item} "end" "for" ";"
2121/// block_comp_spec := name | {ident}","+ ":" name | "others" ":" name | "all" ":" name
2122/// ```
2123pub 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
2141/// Parse a binding indication. See IEEE 1076-2008 section 7.3.2.1. The trailing
2142/// semicolon is required only if at least one of the aspect has been parsed.
2143///
2144/// ```text
2145/// binding_ind := ["use" entity_aspect] [generic_map_aspect] [port_map_aspect] [";"]
2146/// entity_aspect
2147///   := "entity" name
2148///   := "configuration" name
2149///   := "open"
2150/// ```
2151pub fn parse_binding_ind<P: Parser>(p: &mut P) -> ReportedResult<ast::BindingInd> {
2152    let mut span = p.peek(0).span;
2153
2154    // Parse the entity aspect.
2155    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    // Parse the generic map aspect.
2191    let gm = try_map_aspect(p, Kw::Generic)?;
2192
2193    // Parse the port map aspect.
2194    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
2208/// Parse a block or component specification. See IEEE 1067-2008 section 7.3.1.
2209///
2210/// ```text
2211/// block_comp_spec
2212///   := name
2213///   := {ident}","+ ":" name
2214///   := "others" ":" name
2215///   := "all" ":" name
2216/// ```
2217pub fn parse_block_comp_spec<P: Parser>(p: &mut P) -> ReportedResult<Spanned<ast::BlockCompSpec>> {
2218    let mut span = p.peek(0).span;
2219
2220    // Try to detect if this is a block or component specification.
2221    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
2267/// Parse a configuration specification. See IEEE 1076-2008 section 7.3.1.
2268///
2269/// ```text
2270/// config_spec := "for" block_comp_spec binding_ind {vunit_binding_ind} ["end" "for" ";"]
2271/// ```
2272pub 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
2297/// Parse an attribute declaration or specification. See IEEE 1076-2008 sections
2298/// 6.7 and 7.2.
2299///
2300/// ```text
2301/// attribute_decl
2302///   := "attribute" ident ":" name ";"
2303///   := "attribute" ident "of" ({name [signature]}","+ | "others" | "all") ":" entity_class "is" expr ";"
2304/// ```
2305pub 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    // Depending on the next token, parse either a declaration or a
2311    // specification.
2312    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        // Parse the entity specification.
2324        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        // Parse the entity class.
2344        require(p, Colon)?;
2345        let cls = parse_entity_class(p)?;
2346
2347        // Parse the rest.
2348        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
2376/// Parse an entity class. See IEEE 1076-2008 section 7.2.
2377///
2378/// ```text
2379/// entity_class
2380///   := "entity"
2381///   := "architecture"
2382///   := "configuration"
2383///   := "procedure"
2384///   := "function"
2385///   := "package"
2386///   := "type"
2387///   := "subtype"
2388///   := "constant"
2389///   := "signal"
2390///   := "variable"
2391///   := "component"
2392///   := "label"
2393///   := "literal"
2394///   := "units"
2395///   := "group"
2396///   := "file"
2397///   := "property"
2398///   := "sequence"
2399/// ```
2400pub 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
2441/// Parse a group declaration or group template declaration. See IEEE 1076-2008
2442/// sections 6.9 and 6.10.
2443///
2444/// ```text
2445/// group_decl
2446///   := "group" ident "is" "(" {entity_class ["<>"]}","+ ")" ";"
2447///   := "group" ident ":" name ";"
2448/// ```
2449pub 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    // Parse either a declaration or template declaration, depending on the next
2455    // token.
2456    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
2494/// Parse a sequential or concurrent statement.
2495pub fn parse_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::Stmt> {
2496    let mut span = p.peek(0).span;
2497
2498    // Parse the leading statement label, if any.
2499    let label = try_label(p);
2500
2501    // Handle the simple cases where the statement is clearly identified and
2502    // introduced by a keyword. Otherwise try the more complex cases introduced
2503    // by a name or parenthesized expression (aggregate).
2504    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        // For the if statement, check if the `generate` or the `then` keyword
2510        // occurs earlier. This allows us to determine whether we should parse a
2511        // generate or regular statement.
2512        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        // For the case statement, check if the `generate` or the `is` keyword
2523        // occurs earlier. This allows us to determine whether we should parse a
2524        // generate or regular statement.
2525        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        // For the loop statements, check if the `generate` or the `loop`
2536        // keyword occurs earlier. This allows us to determine whether we should
2537        // parse a generate or a regular statement.
2538        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                // Try to parse a statement that begins with a name.
2570                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                // Try to parse a statement that begins with a parenthesized
2579                // expression, aka an assignment.
2580                let span = expr.span;
2581                parse_assign_tail(p, Spanned::new(ast::AssignTarget::Aggregate(expr), span))?
2582            } else {
2583                // If we get here, nothing matched, so throw an error.
2584                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
2604/// Parse an optional label, which basically is just an identifier followed by
2605/// a colon. This is interesting for statement parsing. See IEEE 1076-2008
2606/// section 10.
2607pub 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
2624/// Parse a wait statement. See IEEE 1076-2008 section 10.2.
2625///
2626/// ```text
2627/// wait_stmt := "wait" ["on" {name}","+] ["until" expr] ["for" expr] ";"
2628/// ```
2629pub fn parse_wait_stmt<P: Parser>(p: &mut P) -> ReportedResult<ast::StmtData> {
2630    require(p, Keyword(Kw::Wait))?;
2631
2632    // Parse the optional "on" part.
2633    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    // Parse the optional "until" part.
2649    let until = if accept(p, Keyword(Kw::Until)) {
2650        Some(parse_expr(p)?)
2651    } else {
2652        None
2653    };
2654
2655    // Parse the optional "for" part.
2656    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
2670/// Parse an assertion statement. See IEEE 1076-2008 section 10.3.
2671///
2672/// ```text
2673/// assert_stmt := "assert" expr ["report" expr] ["severity" expr] ";"
2674/// ```
2675pub 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    // Parse the optional "report" part.
2680    let report = if accept(p, Keyword(Kw::Report)) {
2681        Some(parse_expr(p)?)
2682    } else {
2683        None
2684    };
2685
2686    // Parse the optional "severity" part.
2687    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
2701/// Parse a report statement. See IEEE 1076-2008 section 10.4.
2702///
2703/// ```text
2704/// report_stmt := "report" expr ["severity" expr] ";"
2705/// ```
2706pub 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    // Parse the optional "severity" part.
2711    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
2724/// Parse an if statement. See IEEE 1076-2008 section 10.8.
2725///
2726/// ```text
2727/// if_stmt :=
2728///   "if" expr "then" {stmt}
2729///   {"elsif" expr "then" {stmt}}
2730///   ["else" {stmt}]
2731///   "end" "if" [ident] ";"
2732/// ```
2733pub 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    // Parse the first `if` and subsequent `elsif` branches.
2740    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    // Parse the optional `else` branch.
2764    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    // Parse the rest.
2774    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
2784/// Parse a case statement. See IEEE 1076-2008 section 10.9.
2785///
2786/// ```text
2787/// case_stmt:= "case" ["?"] expr "is" {"when" {expr}"|"+ "=>" {stmt}} "end" "case" ["?"] [ident] ";"
2788/// ```
2789pub 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    // Parse the cases.
2799    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    // Parse the rest.
2823    require(p, Keyword(Kw::End))?;
2824    require(p, Keyword(Kw::Case))?;
2825    let trail_qm = accept(p, Qmark); // TODO: Check if this matches.
2826    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
2835/// Parse a loop statement. See IEEE 1076-2008 section 10.10.
2836///
2837/// ```text
2838/// loop_stmt := ("while" expr | "for" ident "in" expr) "loop" {stmt} "end" "loop" [ident] ";"
2839/// ```
2840pub fn parse_loop_stmt<P: Parser>(
2841    p: &mut P,
2842    label: Option<Spanned<Name>>,
2843) -> ReportedResult<ast::StmtData> {
2844    // Determine the looping scheme.
2845    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    // Parse the rest.
2863    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
2878/// Parse a next or exit statement. See IEEE 1076-2008 sections 10.11 and 10.12.
2879///
2880/// ```text
2881/// nexit_stmt := ("next"|"exit") [ident] ["when" expr] ";"
2882/// ```
2883pub 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
2920/// Parse a return statement. See IEEE 1076-2008 section 10.13.
2921///
2922/// ```text
2923/// return_stmt := "return" [expr] ";"
2924/// ```
2925pub 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
2937/// Parse a null statement. See IEEE 1076-2008 section 10.14.
2938///
2939/// ```text
2940/// null_stmt := "null" ";"
2941/// ```
2942pub 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
2948/// Parse a generate if statement. See IEEE 1076-2008 section 11.8.
2949///
2950/// ```text
2951/// generate_if_stmt :=
2952///   "if" [ident ":"] expr "generate" generate_body
2953///   {"elsif" [ident ":"] expr "generate" generate_body}
2954///   ["else" [ident ":"] "generate" generate_body]
2955///   "end" "generate" [ident] ";"
2956/// ```
2957pub 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    // Parse the first `if` and subsequent `elsif` branches.
2964    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    // Parse the optional `else` branch.
2983    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    // Parse the rest.
2993    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
3003/// Parse a generate case statement. See IEEE 1076-2008 section 11.8.
3004///
3005/// ```text
3006/// generate_case_stmt := "case" expr "generate" {"when" [ident ":"] {expr}"|"+ "=>" generate_body}+ "end" "generate" [ident] ";"
3007/// ```
3008pub 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    // Parse the cases.
3017    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    // Parse the rest.
3039    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
3049/// Parse a generate for statement. See IEEE 1076-2008 section 11.8.
3050///
3051/// ```text
3052/// generate_for_stmt := "for" ident "in" expr "generate" generate_body "end" "generate" [ident] ";"
3053/// ```
3054pub 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
3075/// Parse a generate body. See IEEE 1076-2008 section 11.8.
3076///
3077/// ```text
3078/// [{decl_item}+ "begin"] {stmt} ["end" [ident] ";"]
3079/// ```
3080pub 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    // Parse the optional declarative part. Care must be taken when parsing the
3091    // declarative items, since the `for` and `component` may introduce both a
3092    // regular statement or a declarative item.
3093    let decl_items = repeat(p, |p| {
3094        // Statement introduced by label `ident ":"`.
3095        if p.peek(0).value.is_ident() && p.peek(1).value == Colon {
3096            return Ok(None);
3097        }
3098        // Component instantiation.
3099        if p.peek(0).value == Keyword(Kw::Component) && p.peek(2).value != Keyword(Kw::Is) {
3100            return Ok(None);
3101        }
3102        // Configuration specification starting with `for`. Hard to distinguish
3103        // from a for statement or for generate statement. We use a cue from the
3104        // structure of the three variants: Statements have a `loop` or
3105        // `generate` keyword very shortly after `for`, whereas a configuration
3106        // specification has at least one semicolon before any of these
3107        // keywords.
3108        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    // Parse the `begin` that introduces the body. Optional if no declarative
3119    // items were given.
3120    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    // Parse the statements in the body.
3135    let stmts = repeat_until(p, term, parse_stmt)?;
3136
3137    // Parse the `end` and optional trailing label.
3138    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
3158/// Parse a block statement. See IEEE 1076-2008 section 11.2.
3159///
3160/// ```text
3161/// block_stmt := "block" ["(" expr ")"] ["is"] {decl_item} "begin" {stmt} "end" "block" [ident] ";"
3162/// ```
3163pub 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
3184/// Parse a process statement. See IEEE 1076-2008 section 11.3.
3185///
3186/// ```text
3187/// process_stmt := "process" ["(" ("all"|{name}",") ")"] ["is"] {decl_item} "begin" {stmt} "end" ["postponed"] "process" [ident] ";"
3188/// ```
3189pub 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    // Parse the optional sensitivity list.
3196    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    // Parse the declarative part.
3207    let decl_items = repeat(p, try_decl_item)?;
3208
3209    // Parse the statement body.
3210    require(p, Keyword(Kw::Begin))?;
3211    let stmts = repeat_until(p, Keyword(Kw::End), parse_stmt)?;
3212    require(p, Keyword(Kw::End))?;
3213
3214    // Parse the rest.
3215    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
3227/// Parse the tail of an assign statement. This function assumes that the name
3228/// of the signal to be assigned has already been parsed. See IEEE 1076-2008
3229/// section 10.5.
3230///
3231/// ```text
3232/// assign_stmt
3233///   := assign_dst "release" [force_mode] ";"
3234///   := assign_dst assign_mode cond_waves ";"
3235/// assign_dst := (name|paren_expr) . ("<=" | ":=") ["guarded"]
3236/// assign_mode := [delay_mech] | "force" [force_mode]
3237///
3238/// force_mode := "in" | "out"
3239/// delay_mech := "transport" | ["reject" expr] "inertial"
3240/// ```
3241pub 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
3281/// Parse a select assign statement. See IEEE 1076-2008 section 10.5.
3282///
3283/// ```text
3284/// assign_stmt := "with" expr "select" ["?"] assign_dst assign_mode selected_waves ";"
3285/// assign_dst  := (name|paren_expr) ("<=" | ":=") ["guarded"]
3286/// assign_mode := [delay_mech] | "force" [force_mode]
3287///
3288/// force_mode := "in" | "out"
3289/// delay_mech := "transport" | ["reject" expr] "inertial"
3290/// ```
3291pub 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    // Parse the assignment target, which is either a signal name or an
3298    // aggregate.
3299    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    // Parse the rest of the destination.
3319    let (kind, guarded) = parse_assign_dst_tail(p)?;
3320
3321    // Parse the assignment mode and rest of the statement.
3322    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
3383/// Try to parse a delay mechanism.
3384///
3385/// ```text
3386/// "transport" | ["reject" expr] "inertial"
3387/// ```
3388pub 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
3409/// Parse a list of conditional waveforms. See IEEE 1076-2008 section 10.5.
3410///
3411/// ```text
3412/// cond_waves := { wave ["when" expr] }"else"+
3413/// ```
3414pub 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
3427/// Parse a list of selected waveforms. See IEEE 1076-2008 section 10.5.
3428///
3429/// ```text
3430/// selected_waves := { wave "when" {expr}"|"+ }","+
3431/// ```
3432pub 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
3450/// Parse a waveform. See IEEE 1076-2008 section 10.5.
3451///
3452/// ```text
3453/// wave := {expr ["after" expr]}","+ | "unaffected"
3454/// ```
3455pub 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
3483/// Parse the tail of an instantiation or procedure call statement. See IEEE
3484/// 1076-2008 sections 10.7, 11.4, and 11.7.
3485///
3486/// ```text
3487/// ["component"|"entity"|"configuration"] name . [generic_map_aspect] [port_map_aspect] ";"
3488/// ```
3489pub 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}