Skip to content

Commit dbb016c

Browse files
committed
Add matching select statement
1 parent 1a2e2b7 commit dbb016c

File tree

6 files changed

+71
-4
lines changed

6 files changed

+71
-4
lines changed

vhdl_lang/src/analysis/assignment.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl<'a> AnalyzeContext<'a, '_> {
4545
AssignmentRightHand::Selected(selection) => {
4646
let Selection {
4747
expression,
48+
is_matching: _,
4849
alternatives,
4950
} = selection;
5051
let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?;
@@ -95,6 +96,7 @@ impl<'a> AnalyzeContext<'a, '_> {
9596
AssignmentRightHand::Selected(selection) => {
9697
let Selection {
9798
expression,
99+
is_matching: _,
98100
alternatives,
99101
} = selection;
100102
let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?;

vhdl_lang/src/analysis/concurrent.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ impl<'a> AnalyzeContext<'a, '_> {
197197
sels:
198198
Selection {
199199
ref mut expression,
200+
is_matching: _,
200201
ref mut alternatives,
201202
},
202203
end_label_pos: _,

vhdl_lang/src/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,7 @@ pub struct Alternative<T> {
10751075
#[derive(PartialEq, Debug, Clone)]
10761076
pub struct Selection<T> {
10771077
pub expression: WithTokenSpan<Expression>,
1078+
pub is_matching: bool,
10781079
pub alternatives: Vec<Alternative<T>>,
10791080
}
10801081

vhdl_lang/src/ast/search.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ fn search_selection<T: Search>(
215215
) -> SearchResult {
216216
let Selection {
217217
expression,
218+
is_matching: _,
218219
alternatives,
219220
} = selection;
220221
return_if_found!(expression.search(ctx, searcher));
@@ -246,6 +247,7 @@ fn search_assignment<T: Search>(
246247
AssignmentRightHand::Selected(selection) => {
247248
let Selection {
248249
expression,
250+
is_matching: _,
249251
alternatives,
250252
} = selection;
251253
// expression comes before target

vhdl_lang/src/syntax/concurrent_statement.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,12 +323,18 @@ fn parse_selected_signal_assignment(
323323
ctx.stream.expect_kind(With)?;
324324
let expression = parse_expression(ctx)?;
325325
ctx.stream.expect_kind(Select)?;
326+
let is_matching = ctx.stream.pop_if_kind(Que).is_some();
326327
let target = parse_target(ctx)?;
327328
ctx.stream.expect_kind(LTE)?;
328329
// @TODO guarded
329330
let guarded = false;
330331
let delay_mechanism = parse_delay_mechanism(ctx)?;
331-
let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?);
332+
let rhs = AssignmentRightHand::Selected(parse_selection(
333+
ctx,
334+
expression,
335+
is_matching,
336+
parse_waveform,
337+
)?);
332338
Ok(ConcurrentSignalAssignment {
333339
postponed,
334340
guarded,
@@ -591,6 +597,7 @@ fn parse_case_generate_statement(
591597
Ok(CaseGenerateStatement {
592598
sels: Selection {
593599
expression,
600+
is_matching: false,
594601
alternatives,
595602
},
596603
end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident),
@@ -1360,6 +1367,7 @@ with x(0) + 1 select
13601367

13611368
let selection = Selection {
13621369
expression: code.s1("x(0) + 1").expr(),
1370+
is_matching: false,
13631371
alternatives: vec![Alternative {
13641372
choices: code.s1("0|1").choices(),
13651373
item: code.s1("bar(1,2) after 2 ns").waveform(),
@@ -2126,6 +2134,7 @@ end generate;",
21262134
let gen = CaseGenerateStatement {
21272135
sels: Selection {
21282136
expression: code.s1("expr(0) + 2").expr(),
2137+
is_matching: false,
21292138
alternatives: vec![
21302139
Alternative {
21312140
choices: code.s1("1 | 2").choices(),
@@ -2180,6 +2189,7 @@ end generate gen1;",
21802189
let gen = CaseGenerateStatement {
21812190
sels: Selection {
21822191
expression: code.s1("expr(0) + 2").expr(),
2192+
is_matching: false,
21832193
alternatives: vec![
21842194
Alternative {
21852195
choices: code.s1("1 | 2").choices(),

vhdl_lang/src/syntax/sequential_statement.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ where
393393
pub fn parse_selection<T, F>(
394394
ctx: &mut ParsingContext<'_>,
395395
expression: WithTokenSpan<Expression>,
396+
is_matching: bool,
396397
parse_item: F,
397398
) -> ParseResult<Selection<T>>
398399
where
@@ -422,6 +423,7 @@ where
422423

423424
Ok(Selection {
424425
expression,
426+
is_matching,
425427
alternatives,
426428
})
427429
}
@@ -520,12 +522,13 @@ pub fn parse_target(ctx: &mut ParsingContext<'_>) -> ParseResult<WithTokenSpan<T
520522
fn parse_selected_assignment(ctx: &mut ParsingContext<'_>) -> ParseResult<SequentialStatement> {
521523
let expression = parse_expression(ctx)?;
522524
ctx.stream.expect_kind(Select)?;
525+
let is_matching = ctx.stream.pop_if_kind(Que).is_some();
523526
let target = parse_target(ctx)?;
524527
expect_token!(
525528
ctx.stream,
526529
token,
527530
ColonEq => {
528-
let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?);
531+
let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_expression)?);
529532
Ok(SequentialStatement::VariableAssignment(VariableAssignment {
530533
target,
531534
rhs,
@@ -536,13 +539,13 @@ fn parse_selected_assignment(ctx: &mut ParsingContext<'_>) -> ParseResult<Sequen
536539
Ok(SequentialStatement::SignalForceAssignment(SignalForceAssignment {
537540
target,
538541
force_mode: parse_optional_force_mode(ctx)?,
539-
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?)
542+
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_expression)?)
540543
}))
541544
} else {
542545
Ok(SequentialStatement::SignalAssignment(SignalAssignment {
543546
target,
544547
delay_mechanism: parse_delay_mechanism(ctx)?,
545-
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?)
548+
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_waveform)?)
546549
}))
547550
}
548551
}
@@ -1097,6 +1100,7 @@ with x(0) + 1 select
10971100

10981101
let selection = Selection {
10991102
expression: code.s1("x(0) + 1").expr(),
1103+
is_matching: false,
11001104
alternatives: vec![
11011105
Alternative {
11021106
choices: code.s1("0|1").choices(),
@@ -1246,6 +1250,7 @@ with x(0) + 1 select
12461250

12471251
let selection = Selection {
12481252
expression: code.s1("x(0) + 1").expr(),
1253+
is_matching: false,
12491254
alternatives: vec![
12501255
Alternative {
12511256
choices: code.s1("0|1").choices(),
@@ -1290,6 +1295,7 @@ with x(0) + 1 select
12901295

12911296
let selection = Selection {
12921297
expression: code.s1("x(0) + 1").expr(),
1298+
is_matching: false,
12931299
alternatives: vec![
12941300
Alternative {
12951301
choices: code.s1("0|1").choices(),
@@ -1320,6 +1326,51 @@ with x(0) + 1 select
13201326
);
13211327
}
13221328

1329+
#[test]
1330+
fn parse_matching_selected_assignment() {
1331+
let (code, statement) = parse(
1332+
"\
1333+
with x(0) + 1 select?
1334+
foo(0) <= transport bar(1,2) after 2 ns when 0|1,
1335+
def when others;",
1336+
);
1337+
1338+
let selection = Selection {
1339+
expression: code.s1("x(0) + 1").expr(),
1340+
is_matching: true,
1341+
alternatives: vec![
1342+
Alternative {
1343+
choices: code.s1("0|1").choices(),
1344+
item: code.s1("bar(1,2) after 2 ns").waveform(),
1345+
span: code.s1("bar(1,2) after 2 ns when 0|1").token_span(),
1346+
},
1347+
Alternative {
1348+
choices: code.s1("others").choices(),
1349+
item: code.s1("def").waveform(),
1350+
span: code.s1("def when others").token_span(),
1351+
},
1352+
],
1353+
};
1354+
1355+
assert_eq!(
1356+
statement,
1357+
with_label(
1358+
None,
1359+
WithTokenSpan::new(
1360+
SequentialStatement::SignalAssignment(SignalAssignment {
1361+
target: code.s1("foo(0)").name().map_into(Target::Name),
1362+
delay_mechanism: Some(WithTokenSpan::new(
1363+
DelayMechanism::Transport,
1364+
code.s1("transport").token_span()
1365+
)),
1366+
rhs: AssignmentRightHand::Selected(selection),
1367+
}),
1368+
code.token_span()
1369+
)
1370+
)
1371+
);
1372+
}
1373+
13231374
#[test]
13241375
fn parse_procedure_call_statement() {
13251376
let (code, statement) = parse("foo(1,2);");

0 commit comments

Comments
 (0)