1use super::common::error_on_end_identifier_mismatch;
8use super::common::ParseResult;
9use super::declarative_part::parse_declarative_part;
10use super::names::{parse_identifier_list, parse_selected_name};
11use super::range::{parse_array_index_constraint, parse_range};
12use super::subprogram::parse_subprogram_declaration;
13use super::subtype_indication::parse_subtype_indication;
14use super::tokens::{Kind::*, TokenStream};
15use crate::ast::*;
16use crate::ast::{AbstractLiteral, Range};
17use crate::data::{push_some, DiagnosticHandler};
18
19fn parse_enumeration_type_definition(stream: &mut TokenStream) -> ParseResult<TypeDefinition> {
21 let mut enum_literals = Vec::new();
22 loop {
23 let literal_token = stream.expect()?;
24
25 try_token_kind!(
26 literal_token,
27 Identifier | Character => {
28 let enum_literal = try_token_kind!(
29 literal_token,
30 Identifier => literal_token.expect_ident()?.map_into(EnumerationLiteral::Identifier),
31 Character => literal_token.expect_character()?.map_into(EnumerationLiteral::Character)
32 );
33 enum_literals.push(enum_literal);
34
35 try_token_kind!(
36 stream.expect()?,
37 RightPar => {
38 stream.expect_kind(SemiColon)?;
39 break;
40 },
41 Comma => {}
42 );
43 }
44 );
45 }
46
47 Ok(TypeDefinition::Enumeration(enum_literals))
48}
49
50fn parse_array_index_constraints(stream: &mut TokenStream) -> ParseResult<Vec<ArrayIndex>> {
51 stream.expect_kind(LeftPar)?;
52 let mut indexes = Vec::new();
53 loop {
54 indexes.push(parse_array_index_constraint(stream)?);
55
56 try_token_kind!(
57 stream.expect()?,
58 RightPar => {
59 return Ok(indexes);
60 },
61 Comma => {}
62 )
63 }
64}
65
66fn parse_array_type_definition(stream: &mut TokenStream) -> ParseResult<TypeDefinition> {
68 let index_constraints = parse_array_index_constraints(stream)?;
69 stream.expect_kind(Of)?;
70 let element_subtype = parse_subtype_indication(stream)?;
71 stream.expect_kind(SemiColon)?;
72 Ok(TypeDefinition::Array(index_constraints, element_subtype))
73}
74
75fn parse_record_type_definition(
77 stream: &mut TokenStream,
78) -> ParseResult<(TypeDefinition, Option<Ident>)> {
79 let mut elem_decls = Vec::new();
80
81 loop {
82 let token = stream.peek_expect()?;
83 if token.kind == End {
84 stream.move_after(&token); stream.pop_if_kind(Record)?;
86 let end_ident = stream.pop_optional_ident()?;
87 stream.expect_kind(SemiColon)?;
88 return Ok((TypeDefinition::Record(elem_decls), end_ident));
89 };
90
91 let idents = parse_identifier_list(stream)?;
92 stream.expect_kind(Colon)?;
93 let subtype = parse_subtype_indication(stream)?;
94 for ident in idents {
95 elem_decls.push(ElementDeclaration {
96 ident,
97 subtype: subtype.clone(),
98 });
99 }
100 stream.expect_kind(SemiColon)?;
101 }
102}
103
104pub fn parse_subtype_declaration(stream: &mut TokenStream) -> ParseResult<TypeDeclaration> {
105 stream.expect_kind(Subtype)?;
106 let ident = stream.expect_ident()?;
107 stream.expect_kind(Is)?;
108 let subtype_indication = parse_subtype_indication(stream)?;
109 stream.expect_kind(SemiColon)?;
110 Ok(TypeDeclaration {
111 ident,
112 def: TypeDefinition::Subtype(subtype_indication),
113 })
114}
115
116pub fn parse_protected_type_declaration(
118 stream: &mut TokenStream,
119 diagnostics: &mut dyn DiagnosticHandler,
120) -> ParseResult<(ProtectedTypeDeclaration, Option<Ident>)> {
121 let mut items = Vec::new();
122
123 loop {
124 let token = stream.peek_expect()?;
125
126 try_token_kind!(
127 token,
128 Impure | Function | Procedure => items.push(ProtectedTypeDeclarativeItem::Subprogram(
129 parse_subprogram_declaration(stream, diagnostics)?,
130 )),
131 End => {
132 stream.move_after(&token);
133 break;
134 }
135 );
136 }
137 stream.expect_kind(Protected)?;
138 let end_ident = stream.pop_optional_ident()?;
139 Ok((ProtectedTypeDeclaration { items }, end_ident))
140}
141
142fn parse_physical_type_definition(
144 stream: &mut TokenStream,
145 range: Range,
146) -> ParseResult<(TypeDefinition, Option<Ident>)> {
147 let primary_unit = stream.expect_ident()?;
148 stream.expect_kind(SemiColon)?;
149
150 let mut secondary_units = Vec::new();
151
152 loop {
153 let token = stream.peek_expect()?;
154 try_token_kind!(
155 token,
156 End => {
157 break;
158 },
159 Identifier => {
160 stream.move_after(&token);
161 let ident = token.expect_ident()?;
162 stream.expect_kind(EQ)?;
163 let literal = {
164 let value_token = stream.expect()?;
165 try_token_kind!(
166 value_token,
167 AbstractLiteral => {
168 let value = value_token.expect_abstract_literal()?.item;
169 let unit = stream.expect_ident()?;
170 Literal::Physical(value, unit.item)
171 },
172 Identifier => {
173 let unit = value_token.expect_ident()?;
174 Literal::Physical(AbstractLiteral::Integer(1), unit.item)
175 }
176 )
177 };
178
179 secondary_units.push((ident, literal));
180 stream.expect_kind(SemiColon)?;
181 }
182 )
183 }
184
185 stream.expect_kind(End)?;
186 stream.expect_kind(Units)?;
187 let end_ident = stream.pop_optional_ident()?;
188 stream.expect_kind(SemiColon)?;
189
190 Ok((
191 TypeDefinition::Physical(PhysicalTypeDeclaration {
192 range,
193 primary_unit,
194 secondary_units,
195 }),
196 end_ident,
197 ))
198}
199
200pub fn parse_type_declaration(
202 stream: &mut TokenStream,
203 diagnostics: &mut dyn DiagnosticHandler,
204) -> ParseResult<TypeDeclaration> {
205 let token = stream.peek_expect()?;
206 try_token_kind!(
207 token,
208 Subtype => {
209 return parse_subtype_declaration(stream);
210 },
211 Type => {
212 stream.move_after(&token);
213 }
214 );
215
216 let ident = stream.expect_ident()?;
217
218 try_token_kind!(
219 stream.expect()?,
220 Is => {},
221 SemiColon => {
222 return Ok(TypeDeclaration {
223 ident,
224 def: TypeDefinition::Incomplete,
225 });
226 }
227 );
228
229 let def = try_token_kind!(
230 stream.expect()?,
231 Range => {
233 let constraint = parse_range(stream)?.item;
234 try_token_kind!(
235 stream.expect()?,
236 SemiColon => TypeDefinition::Integer(constraint),
237 Units => {
238 let (def, end_ident) = parse_physical_type_definition(stream, constraint)?;
239 push_some(diagnostics, error_on_end_identifier_mismatch(&ident, &end_ident));
240 def
241 }
242 )
243 },
244
245 Access => {
246 let subtype_indication = parse_subtype_indication(stream)?;
247 stream.expect_kind(SemiColon)?;
248 TypeDefinition::Access(subtype_indication)
249 },
250
251 Protected => {
252 if stream.skip_if_kind(Body)? {
253 let decl = parse_declarative_part(stream, diagnostics, false)?;
254 stream.expect_kind(Protected)?;
255 stream.expect_kind(Body)?;
256 stream.pop_if_kind(Identifier)?;
258 stream.expect_kind(SemiColon)?;
259 TypeDefinition::ProtectedBody(ProtectedTypeBody {name: WithRef::new(ident.clone()), decl})
260 } else {
261 let (protected_type_decl, end_ident) = parse_protected_type_declaration(stream, diagnostics)?;
262 push_some(diagnostics, error_on_end_identifier_mismatch(&ident, &end_ident));
263 stream.expect_kind(SemiColon)?;
264 TypeDefinition::Protected(protected_type_decl)
265 }
266 },
267 File => {
268 stream.expect_kind(Of)?;
269 let selected_name = parse_selected_name(stream)?;
270 stream.expect_kind(SemiColon)?;
271 TypeDefinition::File(selected_name)
272 },
273 Array => parse_array_type_definition(stream)?,
274 Record => {
275 let (def, end_ident) = parse_record_type_definition(stream)?;
276 push_some(diagnostics, error_on_end_identifier_mismatch(&ident, &end_ident));
277 def
278 },
279 LeftPar => parse_enumeration_type_definition(stream)?
281 );
282
283 Ok(TypeDeclaration { ident, def })
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289
290 use crate::ast::{DiscreteRange, Ident};
291 use crate::syntax::test::Code;
292
293 #[test]
294 fn parse_integer_scalar_type_definition() {
295 let code = Code::new("type foo is range 0 to 1;");
296
297 let type_decl = TypeDeclaration {
298 ident: code.s1("foo").ident(),
299 def: TypeDefinition::Integer(code.s1("0 to 1").range()),
300 };
301 assert_eq!(
302 code.with_stream_no_diagnostics(parse_type_declaration),
303 type_decl
304 );
305 }
306
307 #[test]
308 fn parse_enumeration_scalar_type_definition() {
309 let code = Code::new("type foo is (alpha, beta);");
310
311 let type_decl = TypeDeclaration {
312 ident: code.s1("foo").ident(),
313 def: TypeDefinition::Enumeration(vec![
314 code.s1("alpha")
315 .ident()
316 .map_into(EnumerationLiteral::Identifier),
317 code.s1("beta")
318 .ident()
319 .map_into(EnumerationLiteral::Identifier),
320 ]),
321 };
322 assert_eq!(
323 code.with_stream_no_diagnostics(parse_type_declaration),
324 type_decl
325 );
326 }
327
328 #[test]
329 fn parse_enumeration_scalar_type_definition_character() {
330 let code = Code::new("type foo is ('a', 'b');");
331
332 let type_decl = TypeDeclaration {
333 ident: code.s1("foo").ident(),
334 def: TypeDefinition::Enumeration(vec![
335 code.s1("'a'")
336 .character()
337 .map_into(EnumerationLiteral::Character),
338 code.s1("'b'")
339 .character()
340 .map_into(EnumerationLiteral::Character),
341 ]),
342 };
343 assert_eq!(
344 code.with_stream_no_diagnostics(parse_type_declaration),
345 type_decl
346 );
347 }
348
349 #[test]
350 fn mixing_identifier_and_scalar_in_enumerations() {
351 let code = Code::new("type foo is (ident, 'b');");
352
353 let type_decl = TypeDeclaration {
354 ident: code.s1("foo").ident(),
355 def: TypeDefinition::Enumeration(vec![
356 code.s1("ident")
357 .ident()
358 .map_into(EnumerationLiteral::Identifier),
359 code.s1("'b'")
360 .character()
361 .map_into(EnumerationLiteral::Character),
362 ]),
363 };
364 assert_eq!(
365 code.with_stream_no_diagnostics(parse_type_declaration),
366 type_decl
367 );
368 }
369
370 #[test]
371 fn parse_array_type_definition_with_index_subtype_definition() {
372 let code = Code::new("type foo is array (natural range <>) of boolean;");
373
374 let type_decl = TypeDeclaration {
375 ident: code.s1("foo").ident(),
376 def: TypeDefinition::Array(
377 vec![ArrayIndex::IndexSubtypeDefintion(
378 code.s1("natural").selected_name(),
379 )],
380 code.s1("boolean").subtype_indication(),
381 ),
382 };
383
384 assert_eq!(
385 code.with_stream_no_diagnostics(parse_type_declaration),
386 type_decl
387 );
388 }
389
390 #[test]
391 fn parse_array_type_definition_with_discrete_subtype_definition() {
392 let code = Code::new("type foo is array (natural) of boolean;");
393
394 let type_decl = TypeDeclaration {
395 ident: code.s1("foo").ident(),
396 def: TypeDefinition::Array(
397 vec![ArrayIndex::Discrete(DiscreteRange::Discrete(
398 code.s1("natural").selected_name(),
399 None,
400 ))],
401 code.s1("boolean").subtype_indication(),
402 ),
403 };
404
405 assert_eq!(
406 code.with_stream_no_diagnostics(parse_type_declaration),
407 type_decl
408 );
409 }
410
411 #[test]
412 fn parse_array_type_definition_with_selected_name() {
413 let code = Code::new("type foo is array (lib.pkg.foo) of boolean;");
414
415 let type_decl = TypeDeclaration {
416 ident: code.s1("foo").ident(),
417 def: TypeDefinition::Array(
418 vec![ArrayIndex::Discrete(DiscreteRange::Discrete(
419 code.s1("lib.pkg.foo").selected_name(),
420 None,
421 ))],
422 code.s1("boolean").subtype_indication(),
423 ),
424 };
425
426 assert_eq!(
427 code.with_stream_no_diagnostics(parse_type_declaration),
428 type_decl
429 );
430 }
431
432 #[test]
433 fn parse_array_type_definition_with_range_attribute_name() {
434 let code = Code::new("type foo is array (arr_t'range) of boolean;");
435
436 let type_decl = TypeDeclaration {
437 ident: code.s1("foo").ident(),
438 def: TypeDefinition::Array(
439 vec![ArrayIndex::Discrete(DiscreteRange::Range(
440 code.s1("arr_t'range").range(),
441 ))],
442 code.s1("boolean").subtype_indication(),
443 ),
444 };
445
446 assert_eq!(
447 code.with_stream_no_diagnostics(parse_type_declaration),
448 type_decl
449 );
450 }
451
452 #[test]
453 fn parse_array_type_definition_with_constraint() {
454 let code = Code::new("type foo is array (2-1 downto 0) of boolean;");
455
456 let index = ArrayIndex::Discrete(DiscreteRange::Range(code.s1("2-1 downto 0").range()));
457
458 let type_decl = TypeDeclaration {
459 ident: code.s1("foo").ident(),
460 def: TypeDefinition::Array(vec![index], code.s1("boolean").subtype_indication()),
461 };
462
463 assert_eq!(
464 code.with_stream_no_diagnostics(parse_type_declaration),
465 type_decl
466 );
467 }
468
469 #[test]
470 fn parse_array_type_definition_mixed() {
471 let code = Code::new("type foo is array (2-1 downto 0, integer range <>) of boolean;");
472
473 let index0 = ArrayIndex::Discrete(DiscreteRange::Range(code.s1("2-1 downto 0").range()));
474
475 let index1 = ArrayIndex::IndexSubtypeDefintion(code.s1("integer").selected_name());
476
477 let type_decl = TypeDeclaration {
478 ident: code.s1("foo").ident(),
479 def: TypeDefinition::Array(
480 vec![index0, index1],
481 code.s1("boolean").subtype_indication(),
482 ),
483 };
484
485 assert_eq!(
486 code.with_stream_no_diagnostics(parse_type_declaration),
487 type_decl
488 );
489 }
490
491 #[test]
492 fn parse_record_type_definition() {
493 let code = Code::new(
494 "\
495 type foo is record
496 element : boolean;
497end record;",
498 );
499
500 let elem_decl = ElementDeclaration {
501 ident: code.s1("element").ident(),
502 subtype: code.s1("boolean").subtype_indication(),
503 };
504
505 let type_decl = TypeDeclaration {
506 ident: code.s1("foo").ident(),
507 def: TypeDefinition::Record(vec![elem_decl]),
508 };
509
510 assert_eq!(
511 code.with_stream_no_diagnostics(parse_type_declaration),
512 type_decl
513 );
514 }
515
516 #[test]
517 fn parse_record_type_definition_many() {
518 let code = Code::new(
519 "\
520 type foo is record
521 element, field : boolean;
522 other_element : std_logic_vector(0 to 1);
523end foo;",
524 );
525
526 let elem_decl0a = ElementDeclaration {
527 ident: code.s1("element").ident(),
528 subtype: code.s1("boolean").subtype_indication(),
529 };
530
531 let elem_decl0b = ElementDeclaration {
532 ident: code.s1("field").ident(),
533 subtype: code.s1("boolean").subtype_indication(),
534 };
535
536 let elem_decl1 = ElementDeclaration {
537 ident: code.s1("other_element").ident(),
538 subtype: code.s1("std_logic_vector(0 to 1)").subtype_indication(),
539 };
540
541 let type_decl = TypeDeclaration {
542 ident: code.s1("foo").ident(),
543 def: TypeDefinition::Record(vec![elem_decl0a, elem_decl0b, elem_decl1]),
544 };
545
546 assert_eq!(
547 code.with_stream_no_diagnostics(parse_type_declaration),
548 type_decl
549 );
550 }
551
552 #[test]
553 fn test_parse_subtype_declaration() {
554 let code = Code::new("subtype vec_t is integer_vector(2-1 downto 0);");
555
556 assert_eq!(
557 code.with_stream_no_diagnostics(parse_type_declaration),
558 TypeDeclaration {
559 ident: code.s1("vec_t").ident(),
560 def: TypeDefinition::Subtype(
561 code.s1("integer_vector(2-1 downto 0)").subtype_indication()
562 )
563 }
564 );
565 }
566
567 #[test]
568 fn test_parse_access_type_declaration() {
569 let code = Code::new("type ptr_t is access integer_vector(2-1 downto 0);");
570
571 assert_eq!(
572 code.with_stream_no_diagnostics(parse_type_declaration),
573 TypeDeclaration {
574 ident: code.s1("ptr_t").ident(),
575 def: TypeDefinition::Access(
576 code.s1("integer_vector(2-1 downto 0)").subtype_indication()
577 )
578 }
579 );
580 }
581
582 #[test]
583 fn test_incomplete_type_declaration() {
584 let code = Code::new("type incomplete;");
585
586 assert_eq!(
587 code.with_stream_no_diagnostics(parse_type_declaration),
588 TypeDeclaration {
589 ident: code.s1("incomplete").ident(),
590 def: TypeDefinition::Incomplete
591 }
592 );
593 }
594
595 #[test]
596 fn test_file_type_declaration() {
597 let code = Code::new("type foo is file of character;");
598
599 assert_eq!(
600 code.with_stream_no_diagnostics(parse_type_declaration),
601 TypeDeclaration {
602 ident: code.s1("foo").ident(),
603 def: TypeDefinition::File(code.s1("character").selected_name())
604 }
605 );
606 }
607
608 fn protected_decl(ident: Ident, items: Vec<ProtectedTypeDeclarativeItem>) -> TypeDeclaration {
609 TypeDeclaration {
610 ident,
611 def: TypeDefinition::Protected(ProtectedTypeDeclaration { items }),
612 }
613 }
614
615 #[test]
616 fn test_protected_type_declaration() {
617 let code = Code::new(
618 "\
619type foo is protected
620end protected;
621",
622 );
623 assert_eq!(
624 code.with_stream_no_diagnostics(parse_type_declaration),
625 protected_decl(code.s1("foo").ident(), vec![])
626 )
627 }
628
629 #[test]
630 fn test_protected_type_declaration_simple_name_suffix() {
631 let code = Code::new(
632 "\
633type foo is protected
634end protected foo;
635",
636 );
637 assert_eq!(
638 code.with_stream_no_diagnostics(parse_type_declaration),
639 protected_decl(code.s1("foo").ident(), vec![])
640 )
641 }
642
643 #[test]
644 fn test_protected_type_declaration_with_subprograms() {
645 let code = Code::new(
646 "\
647type foo is protected
648 procedure proc;
649 function fun return ret;
650end protected;
651",
652 );
653 let items = vec![
654 ProtectedTypeDeclarativeItem::Subprogram(code.s1("procedure proc").subprogram_decl()),
655 ProtectedTypeDeclarativeItem::Subprogram(
656 code.s1("function fun return ret").subprogram_decl(),
657 ),
658 ];
659
660 assert_eq!(
661 code.with_stream_no_diagnostics(parse_type_declaration),
662 protected_decl(code.s1("foo").ident(), items)
663 )
664 }
665
666 #[test]
667 fn test_protected_type_body() {
668 let code = Code::new(
669 "\
670type foo is protected body
671 variable foo : natural;
672 procedure proc is
673 begin
674 end;
675end protected body;
676",
677 );
678
679 let decl = code
680 .s1("\
681 variable foo : natural;
682 procedure proc is
683 begin
684 end;")
685 .declarative_part();
686
687 let ident = code.s1("foo").ident();
688 assert_eq!(
689 code.with_stream_no_diagnostics(parse_type_declaration),
690 TypeDeclaration {
691 ident: ident.clone(),
692 def: TypeDefinition::ProtectedBody(ProtectedTypeBody {
693 name: WithRef::new(ident),
694 decl
695 }),
696 }
697 )
698 }
699
700 #[test]
701 fn test_physical_type_declaration() {
702 let code = Code::new(
703 "\
704type phys is range 0 to 15 units
705 primary_unit;
706end units phys;
707",
708 );
709
710 assert_eq!(
711 code.with_stream_no_diagnostics(parse_type_declaration),
712 TypeDeclaration {
713 ident: code.s1("phys").ident(),
714 def: TypeDefinition::Physical(PhysicalTypeDeclaration {
715 range: code.s1("0 to 15").range(),
716 primary_unit: code.s1("primary_unit").ident(),
717 secondary_units: vec![]
718 })
719 }
720 )
721 }
722
723 #[test]
724 fn test_physical_type_declaration_secondary_units() {
725 let code = Code::new(
726 "\
727type phys is range 0 to 15 units
728 primary_unit;
729 secondary_unit = 5 primary_unit;
730end units;
731",
732 );
733
734 assert_eq!(
735 code.with_stream_no_diagnostics(parse_type_declaration),
736 TypeDeclaration {
737 ident: code.s1("phys").ident(),
738 def: TypeDefinition::Physical(PhysicalTypeDeclaration {
739 range: code.s1("0 to 15").range(),
740 primary_unit: code.s1("primary_unit").ident(),
741 secondary_units: vec![(
742 code.s1("secondary_unit").ident(),
743 Literal::Physical(AbstractLiteral::Integer(5), code.symbol("primary_unit"))
744 ),]
745 })
746 }
747 )
748 }
749
750 #[test]
751 fn test_physical_type_declaration_implicit_secondary_units() {
752 let code = Code::new(
753 "\
754type phys is range 0 to 15 units
755 primary_unit;
756 secondary_unit = primary_unit;
757end units;
758",
759 );
760
761 assert_eq!(
762 code.with_stream_no_diagnostics(parse_type_declaration),
763 TypeDeclaration {
764 ident: code.s1("phys").ident(),
765 def: TypeDefinition::Physical(PhysicalTypeDeclaration {
766 range: code.s1("0 to 15").range(),
767 primary_unit: code.s1("primary_unit").ident(),
768 secondary_units: vec![(
769 code.s1("secondary_unit").ident(),
770 Literal::Physical(AbstractLiteral::Integer(1), code.symbol("primary_unit"))
771 ),]
772 })
773 }
774 )
775 }
776}