1use super::common::ParseResult;
8use super::names::{parse_name, parse_type_mark};
9use super::subtype_indication::parse_subtype_constraint;
10use super::tokens::{Kind, Kind::*};
11use crate::ast::token_range::{WithToken, WithTokenSpan};
12use crate::ast::{Literal, *};
13use crate::data::Diagnostic;
14use crate::syntax::TokenAccess;
15use crate::{ast, HasTokenSpan, TokenId, TokenSpan};
16use vhdl_lang::syntax::parser::ParsingContext;
17
18impl WithTokenSpan<Name> {
19 pub fn into_expression(self) -> WithTokenSpan<Expression> {
20 self.map_into(|name| Expression::Name(Box::new(name)))
21 }
22}
23
24impl Operator {
25 pub fn binary_precedence(&self) -> Option<usize> {
26 Some(match self {
27 Operator::And => 2,
28 Operator::Or => 2,
29 Operator::Nand => 2,
30 Operator::Nor => 2,
31 Operator::Xor => 2,
32 Operator::Xnor => 2,
33 Operator::EQ => 3,
34 Operator::NE => 3,
35 Operator::LT => 3,
36 Operator::LTE => 3,
37 Operator::GT => 3,
38 Operator::GTE => 3,
39 Operator::QueEQ => 3,
40 Operator::QueNE => 3,
41 Operator::QueLT => 3,
42 Operator::QueLTE => 3,
43 Operator::QueGT => 3,
44 Operator::QueGTE => 3,
45 Operator::SLL => 4,
46 Operator::SRL => 4,
47 Operator::SLA => 4,
48 Operator::SRA => 4,
49 Operator::ROL => 4,
50 Operator::ROR => 4,
51 Operator::Plus => 5,
52 Operator::Minus => 5,
53 Operator::Concat => 5,
54 Operator::Times => 7,
55 Operator::Div => 7,
56 Operator::Mod => 7,
57 Operator::Rem => 7,
58 Operator::Pow => 8,
59 _ => {
60 return None;
61 }
62 })
63 }
64
65 pub fn unary_precedence(&self) -> Option<usize> {
66 Some(match self {
67 Operator::Abs => 8,
68 Operator::Not => 8,
69 Operator::Plus => 6,
70 Operator::Minus => 6,
71 Operator::QueQue => 1,
72
73 Operator::And => 8,
78 Operator::Or => 8,
79 Operator::Nand => 8,
80 Operator::Nor => 8,
81 Operator::Xor => 8,
82 Operator::Xnor => 8,
83
84 _ => {
85 return None;
86 }
87 })
88 }
89}
90
91fn kind_to_operator(kind: Kind) -> Option<Operator> {
92 Some(match kind {
93 And => Operator::And,
94 Or => Operator::Or,
95 Nand => Operator::Nand,
96 Nor => Operator::Nor,
97 Xor => Operator::Xor,
98 Xnor => Operator::Xnor,
99 EQ => Operator::EQ,
100 NE => Operator::NE,
101 LT => Operator::LT,
102 LTE => Operator::LTE,
103 GT => Operator::GT,
104 GTE => Operator::GTE,
105 QueEQ => Operator::QueEQ,
106 QueNE => Operator::QueNE,
107 QueLT => Operator::QueLT,
108 QueLTE => Operator::QueLTE,
109 QueGT => Operator::QueGT,
110 QueGTE => Operator::QueGTE,
111 SLL => Operator::SLL,
112 SRL => Operator::SRL,
113 SLA => Operator::SLA,
114 SRA => Operator::SRA,
115 ROL => Operator::ROL,
116 ROR => Operator::ROR,
117 Plus => Operator::Plus,
118 Minus => Operator::Minus,
119 Concat => Operator::Concat,
120 Times => Operator::Times,
121 Div => Operator::Div,
122 Mod => Operator::Mod,
123 Rem => Operator::Rem,
124 Pow => Operator::Pow,
125 Abs => Operator::Abs,
126 Not => Operator::Not,
127 QueQue => Operator::QueQue,
128 _ => {
129 return None;
130 }
131 })
132}
133
134fn kind_to_prefix_unary_op(kind: Kind) -> Option<(Operator, usize)> {
135 let op = kind_to_operator(kind)?;
136 let prec = op.unary_precedence()?;
137 Some((op, prec))
138}
139
140fn kind_to_binary_op(kind: Kind) -> Option<(Operator, usize)> {
141 let op = kind_to_operator(kind)?;
142 let prec = op.binary_precedence()?;
143 Some((op, prec))
144}
145
146pub fn parse_aggregate_initial_choices(
147 ctx: &mut ParsingContext<'_>,
148 start_token: TokenId,
149 choices: Vec<WithTokenSpan<Choice>>,
150) -> ParseResult<WithTokenSpan<Vec<WithTokenSpan<ElementAssociation>>>> {
151 let mut choices = choices;
152 let mut result = Vec::new();
153 loop {
154 expect_token!(
155 ctx.stream,
156 token,
157 token_id,
158 RightPar => {
159 if choices.len() == 1 {
160 if let Some(WithTokenSpan{item: Choice::Expression(expr), span}) = choices.pop() {
161 result.push(
162 WithTokenSpan::new(
163 ElementAssociation::Positional(WithTokenSpan::new(expr, span)),
164 span,
165 )
166 );
167 return Ok(WithTokenSpan::new(result, TokenSpan::new(start_token, token_id)))
168 }
169 }
170
171 return Err(token.kinds_error(&[RightArrow]));
172 },
173 Comma => {
174 if choices.len() == 1 {
175 if let Some(WithTokenSpan{item: Choice::Expression(expr), span}) = choices.pop() {
176 result.push(
177 WithTokenSpan::new(
178 ElementAssociation::Positional(WithTokenSpan::new(expr, span)),
179 span
180 )
181 );
182 choices = parse_choices(ctx)?;
183 continue;
184 }
185 }
186
187 return Err(token.kinds_error(&[RightArrow]));
188 },
189 RightArrow => {
190 let rhs = parse_expression(ctx)?;
191 let span = TokenSpan::new(choices[0].get_start_token(), rhs.get_end_token());
192 result.push(
193 WithTokenSpan::new(
194 ElementAssociation::Named(choices, rhs),
195 span,
196 )
197 );
198
199 expect_token!(
200 ctx.stream,
201 token,
202 token_id,
203 RightPar => {
204 return Ok(WithTokenSpan::new(result, TokenSpan::new(start_token, token_id)))
205 },
206 Comma => {
207 choices = parse_choices(ctx)?;
208 }
209 )
210 }
211 );
212 }
213}
214
215pub fn parse_aggregate(
216 ctx: &mut ParsingContext<'_>,
217) -> ParseResult<WithTokenSpan<Vec<WithTokenSpan<ElementAssociation>>>> {
218 let start_tok = ctx.stream.expect_kind(LeftPar)?;
219 if let Some(token) = ctx.stream.pop_if_kind(RightPar) {
220 return Ok(WithTokenSpan::from(
221 Vec::new(),
222 TokenSpan::new(start_tok, token),
223 ));
224 };
225 let choices = parse_choices(ctx)?;
226 parse_aggregate_initial_choices(ctx, start_tok, choices)
227}
228
229fn parse_half_range(
230 ctx: &mut ParsingContext<'_>,
231 left_expr: WithTokenSpan<Expression>,
232 direction: Direction,
233) -> ParseResult<WithTokenSpan<DiscreteRange>> {
234 let right_expr = parse_expression(ctx)?;
235 let pos = left_expr.span.combine(right_expr.span);
236
237 let range = DiscreteRange::Range(ast::Range::Range(RangeConstraint {
238 direction,
239 left_expr: Box::new(left_expr),
240 right_expr: Box::new(right_expr),
241 }));
242
243 Ok(WithTokenSpan::new(range, pos))
244}
245
246fn parse_choice(ctx: &mut ParsingContext<'_>) -> ParseResult<WithTokenSpan<Choice>> {
247 if let Some(token) = ctx.stream.pop_if_kind(Others) {
248 return Ok(WithTokenSpan::from(Choice::Others, token));
249 }
250 let left_expr = parse_expression(ctx)?;
251
252 if ctx.stream.skip_if_kind(To) {
253 let range = parse_half_range(ctx, left_expr, Direction::Ascending)?;
254 Ok(range.map_into(Choice::DiscreteRange))
255 } else if ctx.stream.skip_if_kind(Downto) {
256 let range = parse_half_range(ctx, left_expr, Direction::Descending)?;
257 Ok(range.map_into(Choice::DiscreteRange))
258 } else {
259 Ok(left_expr.map_into(Choice::Expression))
260 }
261}
262
263pub fn parse_choices(ctx: &mut ParsingContext<'_>) -> ParseResult<Vec<WithTokenSpan<Choice>>> {
264 let mut choices = Vec::new();
265 loop {
266 choices.push(parse_choice(ctx)?);
267
268 if !ctx.stream.skip_if_kind(Bar) {
269 break;
270 }
271 }
272 Ok(choices)
273}
274
275fn parse_allocator(ctx: &mut ParsingContext<'_>) -> ParseResult<WithTokenSpan<Allocator>> {
277 ctx.stream.expect_kind(New)?;
278 let type_mark = parse_type_mark(ctx)?;
279
280 if ctx.stream.skip_if_kind(Tick) {
281 let expr = parse_expression(ctx)?;
282 let span = type_mark.span.combine(expr.span);
283 Ok(WithTokenSpan {
284 item: Allocator::Qualified(QualifiedExpression { type_mark, expr }),
285 span,
286 })
287 } else {
288 let mut span = type_mark.span;
289
290 let constraint = {
291 if let Some(constraint) = parse_subtype_constraint(ctx)? {
292 span = span.combine(constraint.span);
293 Some(constraint)
294 } else {
295 None
296 }
297 };
298
299 let subtype = SubtypeIndication {
300 resolution: None,
301 type_mark,
302 constraint,
303 };
304
305 Ok(WithTokenSpan {
306 item: Allocator::Subtype(subtype),
307 span,
308 })
309 }
310}
311
312pub fn name_to_type_mark(
313 ctx: &mut ParsingContext<'_>,
314 name: WithTokenSpan<Name>,
315) -> ParseResult<WithTokenSpan<Name>> {
316 let pos = name.pos(ctx);
317 let type_mark = name
318 .try_map_into(|name| match name {
319 Name::Attribute(_) => Some(name),
320 _ => Some(name_to_selected_name(name)?),
321 })
322 .ok_or_else(|| Diagnostic::syntax_error(&pos, "Expected type mark"))?;
323
324 Ok(type_mark)
325}
326
327fn name_to_selected_name(name: Name) -> Option<Name> {
328 match name {
329 Name::Designator(d) => Some(Name::Designator(d)),
330 Name::Selected(p, d) => Some(Name::Selected(
331 Box::new(p.try_map_into(name_to_selected_name)?),
332 d,
333 )),
334 _ => None,
335 }
336}
337
338fn parse_expression_or_aggregate(
339 ctx: &mut ParsingContext<'_>,
340 start_token: TokenId,
341) -> ParseResult<WithTokenSpan<Expression>> {
342 let mut choices = parse_choices(ctx)?;
343
344 if choices.len() == 1
345 && matches!(
346 choices.first().unwrap(),
347 WithTokenSpan {
348 item: Choice::Expression(_),
349 ..
350 }
351 )
352 {
353 let WithTokenSpan {
354 item: Choice::Expression(expr),
355 span,
356 } = choices.pop().unwrap()
357 else {
358 unreachable!();
359 };
360
361 peek_token!(
362 ctx.stream, token, token_id,
363
364 Comma | RightArrow => {
366 Ok(parse_aggregate_initial_choices(
367 ctx,
368 start_token,
369 vec![WithTokenSpan::new(Choice::Expression(expr), span)],
370 )?.map_into(Expression::Aggregate))
371 },
372
373 RightPar => {
375 ctx.stream.skip();
376 let expr = WithTokenSpan::new(Expression::Parenthesized(Box::new(WithTokenSpan::new(expr, span))), TokenSpan::new(start_token, token_id));
377 Ok(expr)
378 }
379 )
380 } else {
381 Ok(parse_aggregate_initial_choices(ctx, start_token, choices)?
383 .map_into(Expression::Aggregate))
384 }
385}
386
387fn parse_primary(ctx: &mut ParsingContext<'_>) -> ParseResult<WithTokenSpan<Expression>> {
392 let token = ctx.stream.peek_expect()?;
393 let token_id = ctx.stream.get_current_token_id();
394 match token.kind {
395 Identifier | LtLt => {
396 let name = parse_name(ctx)?;
397 if ctx.stream.skip_if_kind(Tick) {
398 let lpar = ctx.stream.expect_kind(LeftPar)?;
399 let expr = parse_expression_or_aggregate(ctx, lpar)?;
400 let span = name.span.combine(expr.span);
401 Ok(WithTokenSpan::new(
402 Expression::Qualified(Box::new(QualifiedExpression {
403 type_mark: name_to_type_mark(ctx, name)?,
404 expr,
405 })),
406 span,
407 ))
408 } else {
409 Ok(name.into_expression())
410 }
411 }
412 BitString => {
413 ctx.stream.skip();
414 Ok(token
415 .to_bit_string(token_id)?
416 .map_into_span(|bs| Expression::Literal(Literal::BitString(bs))))
417 }
418 Character => {
419 ctx.stream.skip();
420 Ok(token
421 .to_character_value(token_id)?
422 .map_into_span(|chr| Expression::Literal(Literal::Character(chr))))
423 }
424 StringLiteral => {
425 if ctx.stream.next_kinds_are(&[StringLiteral, LeftPar]) {
426 parse_name(ctx).map(|name| name.map_into(|name| Expression::Name(Box::new(name))))
428 } else {
429 ctx.stream.skip();
430 Ok(token
431 .to_string_value(token_id)?
432 .map_into_span(|string| Expression::Literal(Literal::String(string))))
433 }
434 }
435 Null => {
436 ctx.stream.skip();
437 Ok(WithTokenSpan::from(
438 Expression::Literal(Literal::Null),
439 token_id,
440 ))
441 }
442 New => {
443 let alloc = parse_allocator(ctx)?;
444
445 let new_pos = TokenSpan::new(token_id, alloc.span.end_token);
446 Ok(WithTokenSpan::new(
447 Expression::New(Box::new(alloc)),
448 new_pos,
449 ))
450 }
451 AbstractLiteral => {
452 ctx.stream.skip();
453 let value = token.to_abstract_literal(token_id)?;
454 if let Some(unit_token) = ctx.stream.pop_if_kind(Identifier) {
456 let unit = ctx
457 .stream
458 .index(unit_token)
459 .to_identifier_value(unit_token)?;
460 let span = TokenSpan::new(value.token, unit.token);
461 let physical = PhysicalLiteral {
462 value: value.item,
463 unit: WithRef::new(unit),
464 };
465 Ok(WithTokenSpan::new(
466 Expression::Literal(Literal::Physical(physical)),
467 span,
468 ))
469 } else {
470 Ok(value
471 .map_into_span(|value| Expression::Literal(Literal::AbstractLiteral(value))))
472 }
473 }
474
475 LeftPar => {
476 let start_token = ctx.stream.get_current_token_id();
477 ctx.stream.skip();
478 parse_expression_or_aggregate(ctx, start_token)
479 }
480
481 kind => {
482 if let Some((unary_op, op_precedence)) = kind_to_prefix_unary_op(kind) {
484 ctx.stream.skip();
485
486 let expr = parse_expr(ctx, op_precedence)?;
487 let span = TokenSpan::new(token_id, expr.span.end_token);
488
489 Ok(WithTokenSpan::new(
490 Expression::Unary(
491 WithToken::new(WithRef::new(unary_op), token_id),
492 Box::new(expr),
493 ),
494 span,
495 ))
496 } else {
497 Err(Diagnostic::syntax_error(
498 ctx.stream.pos_before(token),
499 "Expected {expression}",
500 ))
501 }
502 }
503 }
504}
505
506fn parse_expr(
507 ctx: &mut ParsingContext<'_>,
508 min_precedence: usize,
509) -> ParseResult<WithTokenSpan<Expression>> {
510 let mut lhs = parse_primary(ctx)?;
511 while let Some(token) = ctx.stream.peek() {
512 let token_id = ctx.stream.get_current_token_id();
513 if token.kind == RightPar {
514 return Ok(lhs);
515 };
516
517 if let Some((binary_op, op_precedence)) = kind_to_binary_op(token.kind) {
518 if op_precedence > min_precedence {
520 ctx.stream.skip();
521 let rhs = parse_expr(ctx, op_precedence)?;
522 let pos = lhs.span.combine(rhs.span);
523 lhs = WithTokenSpan::new(
524 Expression::Binary(
525 WithToken::new(WithRef::new(binary_op), token_id),
526 Box::new(lhs),
527 Box::new(rhs),
528 ),
529 pos,
530 );
531 } else {
532 return Ok(lhs);
533 }
534 } else {
535 return Ok(lhs);
536 };
537 }
538
539 Ok(lhs)
540}
541
542pub fn parse_expression(ctx: &mut ParsingContext<'_>) -> ParseResult<WithTokenSpan<Expression>> {
556 let state = ctx.stream.state();
557 parse_expr(ctx, 0).inspect_err(|_| ctx.stream.set_state(state))
558}
559
560#[cfg(test)]
561mod tests {
562 use super::*;
563 use crate::ast::{AbstractLiteral, Name};
564 use crate::data::Latin1String;
565 use crate::syntax::test::Code;
566
567 #[test]
568 fn parses_character_literal() {
569 let code = Code::new("'a'");
570 assert_eq!(
571 code.with_stream(parse_expression),
572 WithTokenSpan {
573 item: Expression::Literal(Literal::Character(b'a')),
574 span: code.token_span()
575 }
576 );
577 }
578
579 #[test]
580 fn parses_abstract_literal_integer() {
581 let code = Code::new("71");
582 assert_eq!(
583 code.with_stream(parse_expression),
584 WithTokenSpan {
585 item: Expression::Literal(Literal::AbstractLiteral(AbstractLiteral::Integer(71))),
586 span: code.token_span()
587 }
588 );
589 }
590
591 #[test]
592 fn parses_abstract_literal_real() {
593 let code = Code::new("7.1");
594 assert_eq!(
595 code.with_stream(parse_expression),
596 WithTokenSpan {
597 item: Expression::Literal(Literal::AbstractLiteral(AbstractLiteral::Real(7.1))),
598 span: code.token_span()
599 }
600 );
601 }
602
603 #[test]
604 fn parses_string_literal() {
605 let code = Code::new("\"string\"");
606 assert_eq!(
607 code.with_stream(parse_expression),
608 WithTokenSpan {
609 item: Expression::Literal(Literal::String(Latin1String::from_utf8_unchecked(
610 "string"
611 ))),
612 span: code.token_span()
613 }
614 );
615 }
616
617 #[test]
618 fn parses_operator_symbol() {
619 let code = Code::new("\"+\"(1, 2)");
620 assert_eq!(
621 code.with_stream(parse_expression),
622 code.s1("\"+\"(1, 2)")
623 .name()
624 .map_into(|name| Expression::Name(Box::new(name)))
625 );
626 }
627
628 #[test]
629 fn parses_exteral_name() {
630 let code = Code::new("<< signal dut.foo : boolean >>");
631 assert_eq!(
632 code.with_stream(parse_expression),
633 code.s1("<< signal dut.foo : boolean >>")
634 .name()
635 .map_into(|name| Expression::Name(Box::new(name)))
636 );
637 }
638
639 #[test]
640 fn parses_null_literal() {
641 let code = Code::new("null");
642 assert_eq!(
643 code.with_stream(parse_expression),
644 WithTokenSpan {
645 item: Expression::Literal(Literal::Null),
646 span: code.token_span()
647 }
648 );
649 }
650
651 fn int(value: u64) -> Literal {
652 Literal::AbstractLiteral(AbstractLiteral::Integer(value))
653 }
654
655 #[test]
656 fn parses_add_expression() {
657 let code = Code::new("1 + 2");
658
659 let lhs = WithTokenSpan {
660 item: Expression::Literal(int(1)),
661 span: code.s1("1").token_span(),
662 };
663
664 let rhs = WithTokenSpan {
665 item: Expression::Literal(int(2)),
666 span: code.s1("2").token_span(),
667 };
668
669 let expr_add = WithTokenSpan {
670 item: Expression::Binary(
671 WithToken::new(WithRef::new(Operator::Plus), code.s1("+").token()),
672 Box::new(lhs),
673 Box::new(rhs),
674 ),
675 span: code.token_span(),
676 };
677
678 assert_eq!(code.with_stream(parse_expression), expr_add);
679 }
680
681 #[test]
682 fn parses_sub_expression() {
683 let code = Code::new("1 - 2");
684 let lhs = WithTokenSpan {
685 item: Expression::Literal(int(1)),
686 span: code.s1("1").token_span(),
687 };
688
689 let rhs = WithTokenSpan {
690 item: Expression::Literal(int(2)),
691 span: code.s1("2").token_span(),
692 };
693
694 let expr_sub = WithTokenSpan {
695 item: Expression::Binary(
696 WithToken::new(WithRef::new(Operator::Minus), code.s1("-").token()),
697 Box::new(lhs),
698 Box::new(rhs),
699 ),
700 span: code.token_span(),
701 };
702
703 assert_eq!(code.with_stream(parse_expression), expr_sub);
704 }
705
706 #[test]
707 fn parses_abs_expression() {
708 let code = Code::new("abs 9");
709 let expr = WithTokenSpan {
710 item: Expression::Literal(int(9)),
711 span: code.s1("9").token_span(),
712 };
713
714 let expr_abs = WithTokenSpan {
715 item: Expression::Unary(
716 WithToken::new(WithRef::new(Operator::Abs), code.s1("abs").token()),
717 Box::new(expr),
718 ),
719 span: code.token_span(),
720 };
721
722 assert_eq!(code.with_stream(parse_expression), expr_abs);
723 }
724
725 #[test]
726 fn parses_condition_operator() {
727 let code = Code::new("?? 9");
728 let expr = WithTokenSpan {
729 item: Expression::Literal(int(9)),
730 span: code.s1("9").token_span(),
731 };
732
733 let expr_cond = WithTokenSpan {
734 item: Expression::Unary(
735 WithToken::new(WithRef::new(Operator::QueQue), code.s1("??").token()),
736 Box::new(expr),
737 ),
738 span: code.token_span(),
739 };
740
741 assert_eq!(code.with_stream(parse_expression), expr_cond);
742 }
743
744 #[test]
745 fn parses_not_expression() {
746 let code = Code::new("not false");
747 let name_false = WithTokenSpan {
748 item: Expression::Name(Box::new(Name::Designator(
749 Designator::Identifier(code.symbol("false")).into_ref(),
750 ))),
751 span: code.s1("false").token_span(),
752 };
753
754 let expr_not = WithTokenSpan {
755 item: Expression::Unary(
756 WithToken::new(WithRef::new(Operator::Not), code.s1("not").token()),
757 Box::new(name_false),
758 ),
759 span: code.token_span(),
760 };
761
762 assert_eq!(code.with_stream(parse_expression), expr_not);
763 }
764
765 #[test]
766 fn parses_new_allocator_qualified() {
767 let code = Code::new("new integer_vector'(0, 1)");
768 let type_mark = code.s1("integer_vector").type_mark();
769 let expr = code.s1("(0, 1)").expr();
770
771 let alloc = WithTokenSpan {
772 item: Allocator::Qualified(QualifiedExpression { type_mark, expr }),
773 span: code.s1("integer_vector'(0, 1)").token_span(),
774 };
775
776 let new_expr = WithTokenSpan {
777 item: Expression::New(Box::new(alloc)),
778 span: code.token_span(),
779 };
780
781 assert_eq!(code.with_stream(parse_expression), new_expr);
782 }
783
784 #[test]
785 fn parses_new_allocator_subtype() {
786 let code = Code::new("new integer_vector");
787
788 let alloc = WithTokenSpan {
789 item: Allocator::Subtype(code.s1("integer_vector").subtype_indication()),
790 span: code.s1("integer_vector").token_span(),
791 };
792
793 let new_expr = WithTokenSpan {
794 item: Expression::New(Box::new(alloc)),
795 span: code.token_span(),
796 };
797
798 assert_eq!(code.with_stream(parse_expression), new_expr);
799 }
800
801 #[test]
802 fn parses_new_allocator_subtype_constraint() {
803 let code = Code::new("new integer_vector(0 to 1)");
804
805 let alloc = WithTokenSpan {
806 item: Allocator::Subtype(code.s1("integer_vector(0 to 1)").subtype_indication()),
807 span: code.s1("integer_vector(0 to 1)").token_span(),
808 };
809
810 let new_expr = WithTokenSpan {
811 item: Expression::New(Box::new(alloc)),
812 span: code.token_span(),
813 };
814
815 assert_eq!(code.with_stream(parse_expression), new_expr);
816 }
817
818 #[test]
819 fn parses_new_allocator_subtype_constraint_range_attribute() {
820 let code = Code::new("new integer_vector(foo'range)");
821
822 let alloc = WithTokenSpan {
823 item: Allocator::Subtype(code.s1("integer_vector(foo'range)").subtype_indication()),
824 span: code.s1("integer_vector(foo'range)").token_span(),
825 };
826
827 let new_expr = WithTokenSpan {
828 item: Expression::New(Box::new(alloc)),
829 span: code.token_span(),
830 };
831
832 assert_eq!(code.with_stream(parse_expression), new_expr);
833 }
834
835 #[test]
836 fn parses_physical_unit_expression() {
837 let code = Code::new("1 ns");
838 let expr = WithTokenSpan {
839 item: Expression::Literal(Literal::Physical(PhysicalLiteral {
840 value: AbstractLiteral::Integer(1),
841 unit: code.s1("ns").ident().into_ref(),
842 })),
843 span: code.token_span(),
844 };
845
846 assert_eq!(code.with_stream(parse_expression), expr);
847 }
848
849 #[test]
850 fn parses_physical_unit_expression_real() {
851 let code = Code::new("1.0 ns");
852 let expr = WithTokenSpan {
853 item: Expression::Literal(Literal::Physical(PhysicalLiteral {
854 value: AbstractLiteral::Real(1.0),
855 unit: code.s1("ns").ident().into_ref(),
856 })),
857 span: code.token_span(),
858 };
859
860 assert_eq!(code.with_stream(parse_expression), expr);
861 }
862
863 #[test]
864 fn parses_physical_unit_expression_binary() {
865 let code = Code::new("2 * 1 ns");
866 let time_expr = WithTokenSpan {
867 item: Expression::Literal(Literal::Physical(PhysicalLiteral {
868 value: AbstractLiteral::Integer(1),
869 unit: code.s1("ns").ident().into_ref(),
870 })),
871 span: code.s1("1 ns").token_span(),
872 };
873 let two_expr = WithTokenSpan {
874 item: Expression::Literal(int(2)),
875 span: code.s1("2").token_span(),
876 };
877 let expr = WithTokenSpan {
878 item: Expression::Binary(
879 WithToken::new(WithRef::new(Operator::Times), code.s1("*").token()),
880 Box::new(two_expr),
881 Box::new(time_expr),
882 ),
883 span: code.token_span(),
884 };
885 assert_eq!(code.with_stream(parse_expression), expr);
886 }
887
888 #[test]
889 fn parses_physical_unit_expression_unary() {
890 let code = Code::new("- 1 ns");
891 let time_expr = WithTokenSpan {
892 item: Expression::Literal(Literal::Physical(PhysicalLiteral {
893 value: AbstractLiteral::Integer(1),
894 unit: code.s1("ns").ident().into_ref(),
895 })),
896 span: code.s1("1 ns").token_span(),
897 };
898 let expr = WithTokenSpan {
899 item: Expression::Unary(
900 WithToken::new(WithRef::new(Operator::Minus), code.s1("-").token()),
901 Box::new(time_expr),
902 ),
903 span: code.token_span(),
904 };
905
906 assert_eq!(code.with_stream(parse_expression), expr);
907 }
908
909 #[test]
910 fn parses_qualified_expression() {
911 let code = Code::new("foo'(1+2)");
912 let type_mark = code.s1("foo").type_mark();
913 let expr = code.s1("(1+2)").expr();
914
915 let qexpr = WithTokenSpan {
916 item: Expression::Qualified(Box::new(QualifiedExpression { type_mark, expr })),
917 span: code.token_span(),
918 };
919
920 assert_eq!(code.with_stream(parse_expression), qexpr);
921 }
922
923 #[test]
924 fn qualified_expression_precedence() {
925 let code = Code::new("mark0'(0) < mark1'(1)");
926 let expr = WithTokenSpan {
927 item: Expression::Binary(
928 WithToken::new(WithRef::new(Operator::LT), code.s1("<").token()),
929 Box::new(code.s1("mark0'(0)").expr()),
930 Box::new(code.s1("mark1'(1)").expr()),
931 ),
932 span: code.token_span(),
933 };
934
935 assert_eq!(code.expr(), expr);
936 }
937
938 #[test]
939 fn parses_qualified_aggregate() {
940 let code = Code::new("foo'(others => '1')");
941 let type_mark = code.s1("foo").type_mark();
942 let expr = code.s1("(others => '1')").expr();
943
944 let qexpr = WithTokenSpan {
945 item: Expression::Qualified(Box::new(QualifiedExpression { type_mark, expr })),
946 span: code.token_span(),
947 };
948
949 assert_eq!(code.with_stream(parse_expression), qexpr);
950 }
951
952 #[test]
953 fn parses_positional_aggregate() {
954 let code = Code::new("(1, 2)");
955 let one_expr = WithTokenSpan {
956 item: Expression::Literal(int(1)),
957 span: code.s1("1").token_span(),
958 };
959 let two_expr = WithTokenSpan {
960 item: Expression::Literal(int(2)),
961 span: code.s1("2").token_span(),
962 };
963
964 let assoc_list = vec![
965 WithTokenSpan::new(
966 ElementAssociation::Positional(one_expr),
967 code.s1("1").token_span(),
968 ),
969 WithTokenSpan::new(
970 ElementAssociation::Positional(two_expr),
971 code.s1("2").token_span(),
972 ),
973 ];
974 let expr = WithTokenSpan {
975 item: Expression::Aggregate(assoc_list),
976 span: code.token_span(),
977 };
978
979 assert_eq!(code.with_stream(parse_expression), expr);
980 }
981
982 #[test]
983 fn parses_named_aggregate() {
984 let code = Code::new("(1 => 2)");
985 let one_expr = WithTokenSpan {
986 item: Expression::Literal(int(1)),
987 span: code.s1("1").token_span(),
988 };
989 let two_expr = WithTokenSpan {
990 item: Expression::Literal(int(2)),
991 span: code.s1("2").token_span(),
992 };
993
994 let assoc_list = vec![WithTokenSpan::new(
995 ElementAssociation::Named(vec![one_expr.map_into(Choice::Expression)], two_expr),
996 code.s1("1 => 2").token_span(),
997 )];
998 let expr = WithTokenSpan {
999 item: Expression::Aggregate(assoc_list),
1000 span: code.token_span(),
1001 };
1002
1003 assert_eq!(code.with_stream(parse_expression), expr);
1004 }
1005
1006 #[test]
1007 fn parses_named_aggregate_many_choices() {
1008 let code = Code::new("(1 | 2 => 3)");
1009 let one_expr = WithTokenSpan {
1010 item: Expression::Literal(int(1)),
1011 span: code.s1("1").token_span(),
1012 };
1013
1014 let two_expr = WithTokenSpan {
1015 item: Expression::Literal(int(2)),
1016 span: code.s1("2").token_span(),
1017 };
1018
1019 let three_expr = WithTokenSpan {
1020 item: Expression::Literal(int(3)),
1021 span: code.s1("3").token_span(),
1022 };
1023
1024 let assoc_list = vec![WithTokenSpan::new(
1025 ElementAssociation::Named(
1026 vec![
1027 one_expr.map_into(Choice::Expression),
1028 two_expr.map_into(Choice::Expression),
1029 ],
1030 three_expr,
1031 ),
1032 code.s1("1 | 2 => 3").token_span(),
1033 )];
1034 let expr = WithTokenSpan {
1035 item: Expression::Aggregate(assoc_list),
1036 span: code.token_span(),
1037 };
1038
1039 assert_eq!(code.with_stream(parse_expression), expr);
1040 }
1041
1042 #[test]
1043 fn parses_others_aggregate() {
1044 let code = Code::new("(others => 1)");
1045 let one_expr = WithTokenSpan {
1046 item: Expression::Literal(int(1)),
1047 span: code.s1("1").token_span(),
1048 };
1049
1050 let assoc_list = vec![WithTokenSpan::new(
1051 ElementAssociation::Named(
1052 vec![WithTokenSpan::new(
1053 Choice::Others,
1054 code.s1("others").token_span(),
1055 )],
1056 one_expr,
1057 ),
1058 code.s1("others => 1").token_span(),
1059 )];
1060 let expr = WithTokenSpan {
1061 item: Expression::Aggregate(assoc_list),
1062 span: code.token_span(),
1063 };
1064
1065 assert_eq!(code.with_stream(parse_expression), expr);
1066 }
1067
1068 #[test]
1069 fn parses_aggregate_range() {
1070 for direction in [Direction::Descending, Direction::Ascending].iter() {
1071 let (pos, code) = {
1072 if *direction == Direction::Descending {
1073 let code = Code::new("(1 downto 0 => 2)");
1074 (code.s1("1 downto 0").token_span(), code)
1075 } else {
1076 let code = Code::new("(1 to 0 => 2)");
1077 (code.s1("1 to 0").token_span(), code)
1078 }
1079 };
1080
1081 let one_expr = WithTokenSpan {
1082 item: Expression::Literal(int(1)),
1083 span: code.s1("1").token_span(),
1084 };
1085
1086 let zero_expr = WithTokenSpan {
1087 item: Expression::Literal(int(0)),
1088 span: code.s1("0").token_span(),
1089 };
1090
1091 let two_expr = WithTokenSpan {
1092 item: Expression::Literal(int(2)),
1093 span: code.s1("2").token_span(),
1094 };
1095
1096 let range = DiscreteRange::Range(ast::Range::Range(RangeConstraint {
1097 direction: *direction,
1098 left_expr: Box::new(one_expr),
1099 right_expr: Box::new(zero_expr),
1100 }));
1101
1102 let assoc_list = vec![WithTokenSpan::new(
1103 ElementAssociation::Named(
1104 vec![WithTokenSpan::new(Choice::DiscreteRange(range), pos)],
1105 two_expr,
1106 ),
1107 if *direction == Direction::Descending {
1108 code.s1("1 downto 0 => 2").token_span()
1109 } else {
1110 code.s1("1 to 0 => 2").token_span()
1111 },
1112 )];
1113 let expr = WithTokenSpan {
1114 item: Expression::Aggregate(assoc_list),
1115 span: code.token_span(),
1116 };
1117
1118 assert_eq!(code.with_stream(parse_expression), expr);
1119 }
1120 }
1121
1122 #[test]
1123 fn parses_multiple_others_aggregate() {
1124 let code = Code::new("(others => 1, others => 2)");
1125 let one_expr = WithTokenSpan {
1126 item: Expression::Literal(int(1)),
1127 span: code.s1("1").token_span(),
1128 };
1129
1130 let two_expr = WithTokenSpan {
1131 item: Expression::Literal(int(2)),
1132 span: code.s1("2").token_span(),
1133 };
1134
1135 let assoc_list = vec![
1136 WithTokenSpan::new(
1137 ElementAssociation::Named(
1138 vec![WithTokenSpan::new(
1139 Choice::Others,
1140 code.s("others", 1).token_span(),
1141 )],
1142 one_expr,
1143 ),
1144 code.s1("others => 1").token_span(),
1145 ),
1146 WithTokenSpan::new(
1147 ElementAssociation::Named(
1148 vec![WithTokenSpan::new(
1149 Choice::Others,
1150 code.s("others", 2).token_span(),
1151 )],
1152 two_expr,
1153 ),
1154 code.s1("others => 2").token_span(),
1155 ),
1156 ];
1157 let expr = WithTokenSpan {
1158 item: Expression::Aggregate(assoc_list),
1159 span: code.token_span(),
1160 };
1161
1162 assert_eq!(code.with_stream(parse_expression), expr);
1163 }
1164
1165 #[test]
1166 fn parses_mixed_aggregate() {
1167 let code = Code::new("(1 => 2, 3)");
1168 let one_expr = WithTokenSpan {
1169 item: Expression::Literal(int(1)),
1170 span: code.s1("1").token_span(),
1171 };
1172 let two_expr = WithTokenSpan {
1173 item: Expression::Literal(int(2)),
1174 span: code.s1("2").token_span(),
1175 };
1176 let three_expr = WithTokenSpan {
1177 item: Expression::Literal(int(3)),
1178 span: code.s1("3").token_span(),
1179 };
1180
1181 let assoc_list = vec![
1182 WithTokenSpan::new(
1183 ElementAssociation::Named(vec![one_expr.map_into(Choice::Expression)], two_expr),
1184 code.s1("1 => 2").token_span(),
1185 ),
1186 WithTokenSpan::new(
1187 ElementAssociation::Positional(three_expr),
1188 code.s1("3").token_span(),
1189 ),
1190 ];
1191 let expr = WithTokenSpan {
1192 item: Expression::Aggregate(assoc_list),
1193 span: code.token_span(),
1194 };
1195
1196 assert_eq!(code.with_stream(parse_expression), expr);
1197 }
1198
1199 #[test]
1200 fn parses_huge_aggregate() {
1201 let mut code = "(".to_string();
1203 for _ in 0..(1 << 13) {
1204 code.push_str("11123, ");
1205 }
1206 code.push_str("11123)");
1207 let code = Code::new(&code);
1208 assert_eq!(code.with_stream(parse_expression).span, code.token_span());
1209 }
1210
1211 #[test]
1212 fn parses_nested_expression_par_second() {
1213 let code = Code::new("1 + (2 + 3)");
1214
1215 let one = WithTokenSpan {
1216 item: Expression::Literal(int(1)),
1217 span: code.s1("1").token_span(),
1218 };
1219
1220 let two = WithTokenSpan {
1221 item: Expression::Literal(int(2)),
1222 span: code.s1("2").token_span(),
1223 };
1224
1225 let three = WithTokenSpan {
1226 item: Expression::Literal(int(3)),
1227 span: code.s1("3").token_span(),
1228 };
1229
1230 let expr_add0 = WithTokenSpan {
1231 item: Expression::Binary(
1232 WithToken::new(WithRef::new(Operator::Plus), code.s("+", 2).token()),
1233 Box::new(two),
1234 Box::new(three),
1235 ),
1236 span: code.s1("2 + 3").token_span(),
1237 };
1238
1239 let expr_add0_paren = WithTokenSpan::new(
1240 Expression::Parenthesized(Box::new(expr_add0)),
1241 code.s1("(2 + 3)").token_span(),
1242 );
1243
1244 let expr_add1 = WithTokenSpan {
1245 item: Expression::Binary(
1246 WithToken::new(WithRef::new(Operator::Plus), code.s("+", 1).token()),
1247 Box::new(one),
1248 Box::new(expr_add0_paren),
1249 ),
1250 span: code.token_span(),
1251 };
1252
1253 assert_eq!(code.with_stream(parse_expression), expr_add1);
1254 }
1255
1256 #[test]
1257 fn parses_nested_expression_par_first() {
1258 let code = Code::new("(1 + 2) + 3");
1259
1260 let one = WithTokenSpan {
1261 item: Expression::Literal(int(1)),
1262 span: code.s1("1").token_span(),
1263 };
1264
1265 let two = WithTokenSpan {
1266 item: Expression::Literal(int(2)),
1267 span: code.s1("2").token_span(),
1268 };
1269
1270 let three = WithTokenSpan {
1271 item: Expression::Literal(int(3)),
1272 span: code.s1("3").token_span(),
1273 };
1274
1275 let expr_add0 = WithTokenSpan {
1276 item: Expression::Binary(
1277 WithToken::new(WithRef::new(Operator::Plus), code.s("+", 1).token()),
1278 Box::new(one),
1279 Box::new(two),
1280 ),
1281 span: code.s1("1 + 2").token_span(),
1282 };
1283
1284 let expr_add0_paren = WithTokenSpan::new(
1285 Expression::Parenthesized(Box::new(expr_add0)),
1286 code.s1("(1 + 2)").token_span(),
1287 );
1288
1289 let expr_add1 = WithTokenSpan {
1290 item: Expression::Binary(
1291 WithToken::new(WithRef::new(Operator::Plus), code.s("+", 2).token()),
1292 Box::new(expr_add0_paren),
1293 Box::new(three),
1294 ),
1295 span: code.token_span(),
1296 };
1297
1298 assert_eq!(code.with_stream(parse_expression), expr_add1);
1299 }
1300
1301 fn fmt(ctx: &dyn TokenAccess, expr: &WithTokenSpan<Expression>) -> String {
1303 match expr.item {
1304 Expression::Binary(ref op, ref lhs, ref rhs) => {
1305 format!("({} {:?} {})", fmt(ctx, lhs), op.item.item, fmt(ctx, rhs))
1306 }
1307 Expression::Unary(ref op, ref rhs) => format!("({:?} {})", op.item.item, fmt(ctx, rhs)),
1308 Expression::Literal(ref lit) => match lit {
1309 Literal::Null => "null".to_string(),
1310 Literal::String(val) => val.to_string(),
1312 Literal::AbstractLiteral(val) => match val {
1313 AbstractLiteral::Integer(val) => format!("Integer({val})"),
1314 AbstractLiteral::Real(val) => format!("Real({val})"),
1315 },
1316 Literal::Character(val) => format!("'{}'", Latin1String::new(&[*val])),
1317 Literal::Physical(ref physical) => match physical.value {
1318 AbstractLiteral::Integer(val) => {
1319 format!("Physical(Integer({}), {})", val, physical.unit.item.name())
1320 }
1321 AbstractLiteral::Real(val) => {
1322 format!("Physical(Real({}), {})", val, physical.unit.item.name())
1323 }
1324 },
1325 _ => {
1326 println!("{}", expr.pos(ctx).code_context());
1327 panic!("Cannot format {lit:?}");
1328 }
1329 },
1330 Expression::Parenthesized(ref expr) => {
1331 format!("({})", fmt(ctx, expr))
1332 }
1333 _ => {
1334 println!("{}", expr.pos(ctx).code_context());
1335 panic!("Cannot format {expr:?}");
1336 }
1337 }
1338 }
1339
1340 fn assert_expression_is(code: &str, expr_str: &str) {
1341 let code = Code::new(code);
1342 let ctx = code.tokenize();
1343 assert_eq!(fmt(&ctx, &code.with_stream(parse_expression)), expr_str);
1344 }
1345
1346 #[test]
1347 fn parses_function_errors() {
1348 let code = Code::new("fun(,)");
1349 assert_eq!(
1350 code.with_partial_stream(parse_expression),
1351 Err(Diagnostic::syntax_error(
1352 code.s1(",").pos(),
1353 "Expected {expression}"
1354 ))
1355 );
1356
1357 let code = Code::new("fun(arg0,)");
1358 assert_eq!(
1359 code.with_partial_stream(parse_expression),
1360 Err(Diagnostic::syntax_error(
1361 code.s1(")").pos(),
1362 "Expected {expression}"
1363 ))
1364 );
1365 let code = Code::new("fun(arg0,,)");
1366 assert_eq!(
1367 code.with_partial_stream(parse_expression),
1368 Err(Diagnostic::syntax_error(
1369 code.s(",", 2).pos(),
1370 "Expected {expression}"
1371 ))
1372 );
1373 }
1374
1375 #[test]
1376 fn parses_nested_expression_precedence() {
1377 assert_expression_is("1 + 1 ns", "(Integer(1) Plus Physical(Integer(1), ns))");
1378
1379 assert_expression_is(
1380 "1 * 1 ns * 2",
1381 "((Integer(1) Times Physical(Integer(1), ns)) Times Integer(2))",
1382 );
1383
1384 assert_expression_is("1+2+3", "((Integer(1) Plus Integer(2)) Plus Integer(3))");
1385
1386 assert_expression_is("1-2-3", "((Integer(1) Minus Integer(2)) Minus Integer(3))");
1387
1388 assert_expression_is("1+2*3", "(Integer(1) Plus (Integer(2) Times Integer(3)))");
1389
1390 assert_expression_is(
1392 "(1+2)*3",
1393 "(((Integer(1) Plus Integer(2))) Times Integer(3))",
1394 );
1395
1396 assert_expression_is("-1 * 2", "(Minus (Integer(1) Times Integer(2)))");
1398
1399 assert_expression_is("not 1 + 2", "((Not Integer(1)) Plus Integer(2))");
1400
1401 assert_expression_is("abs not 1 + 2", "((Abs (Not Integer(1))) Plus Integer(2))");
1402
1403 assert_expression_is("not - 1", "(Not (Minus Integer(1)))");
1404
1405 assert_expression_is("not + 1", "(Not (Plus Integer(1)))");
1406
1407 assert_expression_is(
1408 "not + ?? 1 ** ?? 2",
1409 "(Not (Plus (QueQue (Integer(1) Pow (QueQue Integer(2))))))",
1410 );
1411
1412 assert_expression_is(
1413 "abs 1 sll 2 + 3 and -1",
1414 "(((Abs Integer(1)) SLL (Integer(2) Plus Integer(3))) And (Minus Integer(1)))",
1415 );
1416
1417 assert_expression_is(
1418 "1 + 2 and 3 + 4",
1419 "((Integer(1) Plus Integer(2)) And (Integer(3) Plus Integer(4)))",
1420 );
1421
1422 assert_expression_is("and 1 + 2", "((And Integer(1)) Plus Integer(2))");
1423 }
1424}