From b87111cf10c974104bc5ef706515b97b4531e02e Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 27 Nov 2025 21:15:41 +0100 Subject: [PATCH] Add matching select statement --- vhdl_lang/src/analysis/assignment.rs | 2 + vhdl_lang/src/analysis/concurrent.rs | 1 + vhdl_lang/src/ast.rs | 1 + vhdl_lang/src/ast/search.rs | 2 + vhdl_lang/src/syntax/concurrent_statement.rs | 12 ++++- vhdl_lang/src/syntax/sequential_statement.rs | 57 ++++++++++++++++++-- 6 files changed, 71 insertions(+), 4 deletions(-) diff --git a/vhdl_lang/src/analysis/assignment.rs b/vhdl_lang/src/analysis/assignment.rs index 67a06ed4b..ece744802 100644 --- a/vhdl_lang/src/analysis/assignment.rs +++ b/vhdl_lang/src/analysis/assignment.rs @@ -45,6 +45,7 @@ impl<'a> AnalyzeContext<'a, '_> { AssignmentRightHand::Selected(selection) => { let Selection { expression, + is_matching: _, alternatives, } = selection; let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?; @@ -95,6 +96,7 @@ impl<'a> AnalyzeContext<'a, '_> { AssignmentRightHand::Selected(selection) => { let Selection { expression, + is_matching: _, alternatives, } = selection; let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?; diff --git a/vhdl_lang/src/analysis/concurrent.rs b/vhdl_lang/src/analysis/concurrent.rs index 98a74abf6..f0cad0f4a 100644 --- a/vhdl_lang/src/analysis/concurrent.rs +++ b/vhdl_lang/src/analysis/concurrent.rs @@ -197,6 +197,7 @@ impl<'a> AnalyzeContext<'a, '_> { sels: Selection { ref mut expression, + is_matching: _, ref mut alternatives, }, end_label_pos: _, diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index 5b062726e..2380e3f66 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -1075,6 +1075,7 @@ pub struct Alternative { #[derive(PartialEq, Debug, Clone)] pub struct Selection { pub expression: WithTokenSpan, + pub is_matching: bool, pub alternatives: Vec>, } diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index dc7916c7e..2213496a3 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -215,6 +215,7 @@ fn search_selection( ) -> SearchResult { let Selection { expression, + is_matching: _, alternatives, } = selection; return_if_found!(expression.search(ctx, searcher)); @@ -246,6 +247,7 @@ fn search_assignment( AssignmentRightHand::Selected(selection) => { let Selection { expression, + is_matching: _, alternatives, } = selection; // expression comes before target diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index 0d6f503c3..a2508f362 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -323,12 +323,18 @@ fn parse_selected_signal_assignment( ctx.stream.expect_kind(With)?; let expression = parse_expression(ctx)?; ctx.stream.expect_kind(Select)?; + let is_matching = ctx.stream.pop_if_kind(Que).is_some(); let target = parse_target(ctx)?; ctx.stream.expect_kind(LTE)?; // @TODO guarded let guarded = false; let delay_mechanism = parse_delay_mechanism(ctx)?; - let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?); + let rhs = AssignmentRightHand::Selected(parse_selection( + ctx, + expression, + is_matching, + parse_waveform, + )?); Ok(ConcurrentSignalAssignment { postponed, guarded, @@ -591,6 +597,7 @@ fn parse_case_generate_statement( Ok(CaseGenerateStatement { sels: Selection { expression, + is_matching: false, alternatives, }, end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident), @@ -1360,6 +1367,7 @@ with x(0) + 1 select let selection = Selection { expression: code.s1("x(0) + 1").expr(), + is_matching: false, alternatives: vec![Alternative { choices: code.s1("0|1").choices(), item: code.s1("bar(1,2) after 2 ns").waveform(), @@ -2126,6 +2134,7 @@ end generate;", let gen = CaseGenerateStatement { sels: Selection { expression: code.s1("expr(0) + 2").expr(), + is_matching: false, alternatives: vec![ Alternative { choices: code.s1("1 | 2").choices(), @@ -2180,6 +2189,7 @@ end generate gen1;", let gen = CaseGenerateStatement { sels: Selection { expression: code.s1("expr(0) + 2").expr(), + is_matching: false, alternatives: vec![ Alternative { choices: code.s1("1 | 2").choices(), diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index 3db8f4748..4f269647a 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -393,6 +393,7 @@ where pub fn parse_selection( ctx: &mut ParsingContext<'_>, expression: WithTokenSpan, + is_matching: bool, parse_item: F, ) -> ParseResult> where @@ -422,6 +423,7 @@ where Ok(Selection { expression, + is_matching, alternatives, }) } @@ -520,12 +522,13 @@ pub fn parse_target(ctx: &mut ParsingContext<'_>) -> ParseResult) -> ParseResult { let expression = parse_expression(ctx)?; ctx.stream.expect_kind(Select)?; + let is_matching = ctx.stream.pop_if_kind(Que).is_some(); let target = parse_target(ctx)?; expect_token!( ctx.stream, token, ColonEq => { - let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?); + let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_expression)?); Ok(SequentialStatement::VariableAssignment(VariableAssignment { target, rhs, @@ -536,13 +539,13 @@ fn parse_selected_assignment(ctx: &mut ParsingContext<'_>) -> ParseResult