1#![allow(
27 clippy::type_complexity,
28 clippy::redundant_field_names,
29 clippy::ptr_arg,
30 clippy::redundant_closure_call,
31 clippy::enum_variant_names,
32 clippy::let_unit_value,
33 clippy::unused_unit )]
35
36use super::ast;
37use super::lexer::DCToken::*;
38use super::lexer::{DCToken, Span};
39use crate::dctype::DCTypeEnum;
40
41use plex::parser;
42use std::mem::discriminant;
43
44parser! {
45 fn parse_(DCToken, Span);
46
47 (a, b) {
49 Span {
50 min: a.min,
51 max: b.max,
52 line: a.line, }
54 }
55
56 dc_file: ast::Root {
59 epsilon => ast::Root {
60 type_declarations: vec![],
61 },
62 dc_file[mut root] type_decl[type_decl] => {
63 root.type_declarations.push(type_decl);
64 root
65 },
66 }
67
68 type_decl: ast::TypeDeclaration {
69 python_style_import[py_imports] => ast::TypeDeclaration::PythonImport(py_imports),
71 keyword_type[keyword] Semicolon => ast::TypeDeclaration::KeywordType(keyword),
72 struct_type[strct] Semicolon => ast::TypeDeclaration::StructType(strct),
73 distributed_class_type[dclass] Semicolon => ast::TypeDeclaration::DClassType(dclass),
74 type_definition[type_def] Semicolon => match type_def {
75 Some(td) => ast::TypeDeclaration::TypedefType(td),
76 None => ast::TypeDeclaration::Ignore,
77 },
78 }
79
80 python_style_import: ast::PythonImport {
83 py_module[module] dclass_import[class] => {
84 ast::PythonImport {
85 span: span!(),
86 module,
87 class,
88 }
89 },
90 }
91
92 py_module: ast::SymbolWithViews {
95 From modules[modules] view_suffixes[views] => {
96
97 let mut modules_string: String = String::new();
99
100 for (i, mod_) in modules.into_iter().enumerate() {
101 if i != 0 {
102 modules_string.push('.');
103 }
104 modules_string.push_str(&mod_);
105 }
106
107 ast::SymbolWithViews {
108 span: span!(),
109 symbol: modules_string,
110 symbol_views: views,
111 }
112 }
113 }
114
115 modules: Vec<String> {
117 legal_python_module_identifiers[module] => vec![module],
118 modules[mut vector] Period legal_python_module_identifiers[module] => {
119 vector.push(module);
120 vector
121 }
122 }
123
124 legal_python_module_identifiers: String {
130 Identifier(id) => id,
131 DCKeyword(id) => id,
132 CharT => "char".to_string(),
133 Int8T => "int8".to_string(),
134 Int16T => "int16".to_string(),
135 Int32T => "int32".to_string(),
136 Int64T => "int64".to_string(),
137 UInt8T => "uint8".to_string(),
138 UInt16T => "uint16".to_string(),
139 UInt32T => "uint32".to_string(),
140 UInt64T => "uint64".to_string(),
141 Float32T => "float32".to_string(),
142 Float64T => "float64".to_string(),
143 Int8ArrayT => "int8array".to_string(),
144 Int16ArrayT => "int16array".to_string(),
145 Int32ArrayT => "int32array".to_string(),
146 UInt8ArrayT => "uint8array".to_string(),
147 UInt16ArrayT => "uint16array".to_string(),
148 UInt32ArrayT => "uint32array".to_string(),
149 UInt32UInt8ArrayT => "uint32uint8array".to_string(),
150 StringT => "string".to_string(),
151 BlobT => "blob".to_string(),
152 Blob32T => "blob32".to_string(),
153 DClass => "dclass".to_string(),
154 Struct => "struct".to_string(),
155 Keyword => "keyword".to_string(),
156 Typedef => "typedef".to_string(),
157 Switch => "switch".to_string(),
158 Default => "default".to_string(),
159 Break => "break".to_string(),
160 }
161
162 dclass_import: ast::SymbolWithViews {
165 Import Identifier(c) view_suffixes[cs] => ast::SymbolWithViews {
166 span: span!(),
167 symbol: c,
168 symbol_views: cs,
169 },
170 Import Star => ast::SymbolWithViews {
171 span: span!(),
172 symbol: "*".into(),
173 symbol_views: vec![],
174 },
175 }
176
177 view_suffixes: ast::ViewSuffixes {
183 epsilon => vec![],
184 view_suffixes[mut si] ForwardSlash view_suffix[id] => {
185 si.push(id);
186 si
187 }
188 }
189
190 view_suffix: ast::ViewSuffix {
191 ViewSuffix(id) => ast::ViewSuffix {
192 span: span!(),
193 view: id,
194 },
195 }
196
197 type_definition: Option<ast::TypeDefinition> {
200 Typedef nonmethod_type_with_name[nmt] => {
201 Some(ast::TypeDefinition {
202 span: span!(),
203 deprecated: true,
204 data_type: nmt.data_type,
205 array_range: None,
206 alias_identifier: nmt.identifier,
207 })
208 },
209 Typedef UInt8T BoolT => {
213 println!("{}\n\n\"typedef uint8 bool;\" is deprecated!\n\n\
214 Cannot declare type alias for uint8 as 'bool', as it is a reserved identifier \
215 in the DC language.\nDonet introduces the 'bool' data type, which is an alias \
216 for uint8 under the hood.\n", span!());
217 None
218 },
219 type_definition[td] OpenBrackets array_range[ar] CloseBrackets => {
220 if td.is_none() {
221 return td;
222 }
223 let mut type_def = td.unwrap();
224
225 type_def.array_range = ar;
226
227 Some(type_def)
228 },
229 }
230
231 keyword_type: ast::KeywordDefinition {
234 Keyword Identifier(id) => {
235 ast::KeywordDefinition {
236 span: span!(),
237 identifier: id,
238 historical: false,
239 }
240 },
241 Keyword DCKeyword(historic) => {
242 ast::KeywordDefinition {
243 span: span!(),
244 identifier: historic,
245 historical: true,
246 }
247 }
248 }
249
250 distributed_class_type: ast::DClass {
253 DClass Identifier(id) optional_inheritance[parents] OpenBraces
254 optional_class_fields[fields] CloseBraces => {
255 ast::DClass {
256 span: span!(),
257 identifier: id,
258 parents,
259 fields,
260 }
261 }
262 }
263
264 optional_class_fields: ast::ClassFields {
265 epsilon => vec![],
266 optional_class_fields[mut vector] class_field[field] Semicolon => {
267 vector.push(field);
268 vector
269 },
270 }
271
272 class_field: ast::AtomicOrMolecular {
273 named_field[nf] dc_keyword_list[keywords] => {
276 ast::AtomicOrMolecular::Atomic(
277 ast::AtomicField::from_named_field(nf, keywords, span!())
278 )
279 },
280 molecular_field[molecular] => {
282 ast::AtomicOrMolecular::Molecular(molecular)
283 },
284 }
285
286 optional_inheritance: Vec<String> {
287 epsilon => vec![],
288 Colon Identifier(parent) class_parents[mut cp] => {
289 cp.insert(0, parent);
290 cp
291 },
292 }
293
294 class_parents: Vec<String> {
295 epsilon => vec![],
296 class_parents[mut cp] Comma Identifier(class) => {
297 cp.push(class);
298 cp
299 }
300 }
301
302 molecular_field: ast::MolecularField {
306 Identifier(id) Colon Identifier(first_atomic) molecular_atom_list[mut atomics] => {
310 ast::MolecularField {
311 span: span!(),
312 identifier: id,
313 atomic_field_identifiers: {
314 let mut vec: Vec<String> = vec![first_atomic];
315
316 vec.append(&mut atomics);
317 vec
318 }
319 }
320 },
321 }
322
323 molecular_atom_list: Vec<String> {
324 epsilon => vec![],
325 molecular_atom_list[mut atomics] Comma Identifier(atomic_name) => {
326 atomics.push(atomic_name);
327 atomics
328 },
329 }
330
331 struct_type: ast::Struct {
334 Struct Identifier(id) OpenBraces struct_fields[fields] CloseBraces => {
335 ast::Struct {
336 span: span!(),
337 identifier: id,
338 fields,
339 }
340 },
341 }
342
343 struct_fields: Vec<ast::StructField> {
344 epsilon => vec![],
345 struct_fields[mut vec] struct_field[field] Semicolon => {
346 vec.push(field);
347 vec
348 },
349 }
350
351 struct_field: ast::StructField {
352 switch_type[sw] => ast::StructField::Switch(sw),
353 unnamed_field[pf] => ast::StructField::ParameterField(pf),
354 named_field[nf] => nf.into(),
355 }
356
357 switch_type: ast::Switch {
360 Switch optional_name[id] OpenParenthesis parameter_field[field] CloseParenthesis
361 OpenBraces switch_cases[cases] CloseBraces => {
362 ast::Switch {
363 span: span!(),
364 identifier: id,
365 key_parameter: field,
366 cases: cases,
367 }
368 }
369 }
370
371 switch_cases: Vec<ast::Case> {
372 epsilon => vec![],
373 switch_cases[mut vec] switch_case[case] => {
374 vec.push(case);
375 vec
376 },
377 }
378
379 switch_case: ast::Case {
380 switch_case_body[mut case] optional_break[breaks] => {
381 case.span = span!(); case.breaks = breaks;
383 case
384 }
385 }
386
387 switch_case_body: ast::Case {
388 Default Colon => ast::Case {
389 span: span!(),
390 condition: None, fields: vec![],
392 breaks: false,
393 },
394 Case type_value[condition] Colon => ast::Case {
395 span: span!(),
396 condition: Some(condition),
397 fields: vec![],
398 breaks: false,
399 },
400 switch_case[mut case] switch_field[field] Semicolon => {
401 case.fields.push(field);
402 case
403 },
404 }
405
406 switch_field: ast::NamedField {
407 named_field[nf] => nf,
408 }
409
410 optional_break: bool {
411 epsilon => false,
412 Break Semicolon => true,
413 }
414
415 named_field: ast::NamedField {
418 method_as_field[mf] => ast::NamedField::MethodAsField(mf),
419 nonmethod_type_with_name[nmt] => {
420 let param: ast::Parameter = nmt.into();
421
422 ast::NamedField::ParameterField(param.into())
423 },
424 field_with_name_as_array[field] => ast::NamedField::ParameterField(field),
425 field_with_name_and_default[field] => ast::NamedField::ParameterField(field),
426 }
427
428 field_with_name_as_array: ast::ParameterField {
429 nonmethod_type_with_name[nmt]
430 OpenBrackets array_range[_] CloseBrackets => {
431 let param: ast::Parameter = nmt.into();
432
433 param.into()
435 },
436 field_with_name_as_array[pf]
437 OpenBrackets array_range[_] CloseBrackets => {
438 pf
440 },
441 }
442
443 field_with_name_and_default: ast::ParameterField {
444 nonmethod_type_with_name[nmt] Equals type_value[value] => {
445 let mut param: ast::Parameter = nmt.into();
446
447 param.default_value = Some(value);
448 param.into()
449 },
450 field_with_name_as_array[mut field] Equals type_value[value] => {
451 field.parameter.default_value = Some(value);
452 field
453 },
454 }
455
456 unnamed_field: ast::ParameterField {
457 nonmethod_type[nmt] => {
458 let param: ast::Parameter = nmt.into();
459 param.into()
460 },
461 nonmethod_type[nmt] Equals type_value[value] => {
462 let mut param: ast::Parameter = nmt.into();
463 param.default_value = Some(value);
464
465 param.into()
466 },
467 }
468
469 method_as_field: ast::MethodAsField {
471 Identifier(id) method_body[parameters] => {
472 ast::MethodAsField {
473 span: span!(),
474 identifier: id,
475 parameters,
476 }
477 },
478 }
479
480 method_body: ast::MethodBody {
482 OpenParenthesis parameters[params] CloseParenthesis => params,
483 }
484
485 parameter_fields: Vec<ast::ParameterField> {
488 epsilon => vec![],
489 parameter_fields[mut vec] Comma parameter_field[pf] => {
490 vec.push(pf);
491 vec
492 },
493 }
494
495 parameter_field: ast::ParameterField {
496 parameter[param] dc_keyword_list[kl] => {
497 let mut pf: ast::ParameterField = param.into();
498
499 pf.keywords = kl;
500 pf
501 },
502 }
503
504 dc_keyword_list: ast::KeywordList {
505 epsilon => vec![],
506 dc_keyword_list[mut vec] Identifier(keyword) => {
507 vec.push(keyword);
508 vec
509 }
510 dc_keyword_list[mut vec] DCKeyword(keyword) => {
511 vec.push(keyword);
512 vec
513 }
514 }
515
516 parameters: Vec<ast::Parameter> {
519 epsilon => vec![],
520 #[no_reduce(Comma)] parameters[mut vector] parameter[param] => {
522 vector.push(param);
523 vector
524 },
525 parameters[mut vector] parameter[param] Comma => {
526 vector.push(param);
527 vector
528 },
529 }
530
531 parameter: ast::Parameter {
532 nonmethod_type[nmt] => nmt.into(),
533 nonmethod_type[nmt] Equals type_value[value] => {
534 let mut param: ast::Parameter = nmt.into();
535
536 param.default_value = Some(value);
537 param
538 },
539 }
540
541 nonmethod_type_with_name: ast::NonMethodType {
544 nonmethod_type[mut nmt] Identifier(id) => {
545 nmt.identifier = Some(id);
546 nmt
547 },
548 }
549
550 nonmethod_type: ast::NonMethodType {
551 nonmethod_type_no_array[nmt] => nmt,
552 #[no_reduce(OpenBrackets)] type_with_array[twa] => ast::NonMethodType {
554 span: span!(),
555 identifier: None,
556 data_type: ast::NonMethodDataType::TypeWithArray(twa),
557 },
558 }
559
560 nonmethod_type_no_array: ast::NonMethodType {
561 #[no_reduce(OpenBrackets)]
562 Identifier(id) => ast::NonMethodType {
563 span: span!(),
564 identifier: None,
565 data_type: ast::NonMethodDataType::StructType(id),
566 },
567 #[no_reduce(OpenBrackets)]
568 numeric_type[nt] => ast::NonMethodType {
569 span: span!(),
570 identifier: None,
571 data_type: ast::NonMethodDataType::NumericType(nt),
572 },
573 #[no_reduce(OpenBrackets)]
574 builtin_array_type[twa] => ast::NonMethodType {
575 span: span!(),
576 identifier: None,
577 data_type: ast::NonMethodDataType::TypeWithArray(twa),
578 },
579 }
580
581 type_with_array: ast::TypeWithArray {
582 numeric_type[nt] OpenBrackets array_range[ar] CloseBrackets => {
583 ast::TypeWithArray {
584 span: span!(),
585 data_type: ast::ArrayableType::Numeric(nt),
586 array_ranges: match ar {
587 Some(range) => vec![range],
588 None => vec![],
589 },
590 }
591 },
592 Identifier(id) OpenBrackets array_range[ar] CloseBrackets => {
593 ast::TypeWithArray {
594 span: span!(),
595 data_type: ast::ArrayableType::Struct(id),
596 array_ranges: match ar {
597 Some(range) => vec![range],
598 None => vec![],
599 },
600 }
601 },
602 builtin_array_type[mut twa] OpenBrackets array_range[ar] CloseBrackets => {
603 if let Some(range) = ar {
604 twa.array_ranges.push(range);
605 }
606 twa
607 },
608 type_with_array[mut twa] OpenBrackets array_range[ar] CloseBrackets => {
609 if let Some(range) = ar {
610 twa.array_ranges.push(range);
611 }
612 twa
613 },
614 }
615
616 builtin_array_type: ast::TypeWithArray {
617 sized_type_token[st] => ast::TypeWithArray {
618 span: span!(),
619 data_type: ast::ArrayableType::Sized(st),
620 array_ranges: vec![],
621 },
622 sized_type_token[st] OpenParenthesis array_range[ar] CloseParenthesis => {
623 ast::TypeWithArray {
624 span: span!(),
625 data_type: ast::ArrayableType::Sized(st),
626 array_ranges: match ar {
627 Some(range) => vec![range],
628 None => vec![],
629 },
630 }
631 },
632 }
633
634 array_expansion: ast::ArrayExpansion {
636 type_value[tv] => (tv, 1_u32), signed_integer[i] Star unsigned_32_bit_int[f] => (ast::TypeValue::I64(i), f),
638 DecimalLiteral(i) Star unsigned_32_bit_int[f] => (ast::TypeValue::I64(i), f),
639 HexLiteral(hs) Star unsigned_32_bit_int[f] => (ast::TypeValue::String(hs), f),
640 StringLiteral(s) Star unsigned_32_bit_int[f] => (ast::TypeValue::String(s), f),
641 }
642
643 array_value: Vec<ast::ArrayExpansion> {
644 OpenBrackets CloseBrackets => vec![],
645 OpenBrackets element_values[ev] CloseBrackets => ev,
646 }
647
648 element_values: Vec<ast::ArrayExpansion> {
649 array_expansion[ae] => vec![ae],
650 element_values[mut ev] Comma array_expansion[ae] => {
651 ev.push(ae);
652 ev
653 },
654 }
655
656 parameter_values: ast::ParameterValues {
657 type_value[tv] => vec![tv],
658 parameter_values[mut vec] Comma type_value[tv] => {
659 vec.push(tv);
660 vec
661 },
662 }
663
664 type_or_sized_value: ast::TypeOrSizedValue {
665 type_value[tv] => ast::TypeOrSizedValue::TypeValue(tv),
666 sized_type_token[st] => ast::TypeOrSizedValue::SizedValue(st),
667 }
668
669 type_value: ast::TypeValue {
670 BooleanLiteral(b) => ast::TypeValue::I64(match b {
671 true => 1,
672 false => 0,
673 }),
674 DecimalLiteral(i) => ast::TypeValue::I64(i),
675 CharacterLiteral(c) => ast::TypeValue::Char(c),
676 StringLiteral(s) => ast::TypeValue::String(s),
677 HexLiteral(hs) => ast::TypeValue::String(hs),
678 signed_integer[i] => ast::TypeValue::I64(i),
679 array_value[av] => ast::TypeValue::ArrayValue(av),
680 }
681
682 numeric_type: ast::NumericType {
683 numeric_type_token[nt] => nt,
684 numeric_with_explicit_cast[nt] => nt,
685 numeric_with_modulus[nt] => nt,
686 numeric_with_divisor[nt] => nt,
687 numeric_with_range[nt] => nt,
688 }
689
690 numeric_with_range: ast::NumericType {
691 numeric_type_token[mut nt] OpenParenthesis numeric_range[nr] CloseParenthesis => {
692 nt.range = nr;
693 nt
694 },
695 numeric_with_explicit_cast[mut nt] OpenParenthesis numeric_range[nr] CloseParenthesis => {
696 nt.range = nr;
697 nt
698 },
699 numeric_with_modulus[mut nt] OpenParenthesis numeric_range[nr] CloseParenthesis => {
700 nt.range = nr;
701 nt
702 },
703 numeric_with_divisor[mut nt] OpenParenthesis numeric_range[nr] CloseParenthesis => {
704 nt.range = nr;
705 nt
706 },
707 }
708
709 numeric_with_divisor: ast::NumericType {
710 numeric_type_token[mut nt] ForwardSlash number[num] => {
711 nt.add_divisor(num);
712 nt
713 },
714 numeric_with_explicit_cast[mut nt] ForwardSlash number[num] => {
715 nt.add_divisor(num);
716 nt
717 },
718 numeric_with_modulus[mut nt] ForwardSlash number[num] => {
719 nt.add_divisor(num);
720 nt
721 },
722 }
723
724 numeric_with_modulus: ast::NumericType {
725 numeric_type_token[mut nt] Percent number[num] => {
726 nt.add_modulus(num);
727 nt
728 },
729 numeric_with_explicit_cast[mut nt] Percent number[num] => {
730 nt.add_modulus(num);
731 nt
732 },
733 }
734
735 numeric_with_explicit_cast: ast::NumericType {
743 numeric_type_token[mut nt]
749 OpenParenthesis signed_integer_type[dt] CloseParenthesis => {
750 nt.cast = Some(dt);
751 nt
752 },
753 numeric_type_token[mut nt]
754 OpenParenthesis unsigned_integer_type[dt] CloseParenthesis => {
755 nt.cast = Some(dt);
756 nt
757 },
758 numeric_type_token[mut nt]
759 OpenParenthesis floating_point_type[dt] CloseParenthesis => {
760 nt.cast = Some(dt);
761 nt
762 },
763 }
764
765 numeric_range: Option<ast::NumericRange> {
766 epsilon => None,
767
768 char_or_number[v] => match v {
769 ast::CharOrNumber::Char(c) => {
770 let min_max: f64 = f64::from(u32::from(c));
771 Some(min_max .. min_max)
772 },
773 ast::CharOrNumber::I64(i) => {
774 let min_max: f64 = i as f64;
775 Some(min_max .. min_max)
776 },
777 ast::CharOrNumber::F64(f) => Some(f .. f),
778 },
779
780 char_or_number[min] Hyphen char_or_number[max] => {
781 assert!(
782 discriminant(&min) == discriminant(&max),
783 "{}\nCannot define a numeric range with a min and max of different data types!",
784 span!()
785 );
786
787 match min {
788 ast::CharOrNumber::Char(min_c) => {
789 let min: f64 = f64::from(u32::from(min_c));
790 let max: f64 = match max {
791 ast::CharOrNumber::Char(max_c) => f64::from(u32::from(max_c)),
792 _ => unreachable!("Assertion makes this case impossible."),
793 };
794 Some(min .. max)
795 },
796 ast::CharOrNumber::I64(min_i) => {
797 Some(min_i as f64 .. match max {
798 ast::CharOrNumber::I64(max_i) => max_i as f64,
799 _ => unreachable!("Assertion makes this case impossible."),
800 })
801 },
802 ast::CharOrNumber::F64(min_f) => Some(min_f .. match max {
803 ast::CharOrNumber::F64(max_f) => max_f,
804 _ => unreachable!("Assertion makes this case impossible."),
805 }),
806 }
807 },
808 }
809
810 array_range: Option<ast::NumericRange> {
811 epsilon => None,
812 char_or_u16[v] => match v {
813 ast::CharOrU16::Char(c) => {
814 let min_max: f64 = f64::from(u32::from(c));
815 Some(min_max .. min_max)
816 },
817 ast::CharOrU16::U16(u) => {
818 let min_max: f64 = f64::from(u);
819 Some(min_max .. min_max)
820 },
821 },
822 char_or_u16[min] Hyphen char_or_u16[max] => {
823 let min_float: f64 = match min {
824 ast::CharOrU16::Char(c) => f64::from(u32::from(c)),
825 ast::CharOrU16::U16(u) => f64::from(u),
826 };
827 let max_float: f64 = match max {
828 ast::CharOrU16::Char(c) => f64::from(u32::from(c)),
829 ast::CharOrU16::U16(u) => f64::from(u),
830 };
831 Some(min_float .. max_float)
832 },
833 }
834
835 sized_type_token: ast::SizedTypeToken {
838 StringT => ast::SizedTypeToken::String,
839 BlobT => ast::SizedTypeToken::Blob,
840 Blob32T => ast::SizedTypeToken::Blob32,
841 array_data_type[dt] => match dt.token {
842 Int8ArrayT => ast::SizedTypeToken::Int8Array,
843 Int16ArrayT => ast::SizedTypeToken::Int16Array,
844 Int32ArrayT => ast::SizedTypeToken::Int32Array,
845 UInt8ArrayT => ast::SizedTypeToken::UInt8Array,
846 UInt16ArrayT => ast::SizedTypeToken::UInt16Array,
847 UInt32ArrayT => ast::SizedTypeToken::UInt32Array,
848 UInt32UInt8ArrayT => ast::SizedTypeToken::UInt32UInt8Array,
849 _ => unreachable!("Not possible due to production rules."),
850 },
851 }
852
853 numeric_type_token: ast::NumericType {
854 CharT => ast::NumericType::from_type(DCTypeEnum::TChar, span!()),
855 BoolT => ast::NumericType::from_type(DCTypeEnum::TUInt8, span!()),
857 signed_integer_type[dt] => ast::NumericType::from_type(dt.dctype, span!()),
858 unsigned_integer_type[dt] => ast::NumericType::from_type(dt.dctype, span!()),
859 floating_point_type[dt] => ast::NumericType::from_type(dt.dctype, span!()),
860 }
861
862 char_or_number: ast::CharOrNumber {
863 CharacterLiteral(c) => ast::CharOrNumber::Char(c),
864 signed_integer[v] => ast::CharOrNumber::I64(v),
865
866 number[num] => match num {
867 ast::Number::Decimal(dl) => ast::CharOrNumber::I64(dl),
868 ast::Number::Float(fl) => ast::CharOrNumber::F64(fl),
869 },
870 }
871
872 signed_integer: i64 {
873 Plus DecimalLiteral(dl) => dl,
874 Hyphen DecimalLiteral(dl) => -dl, }
876
877 number: ast::Number {
878 DecimalLiteral(dl) => ast::Number::Decimal(dl),
879 FloatLiteral(fl) => ast::Number::Float(fl),
880 }
881
882 char_or_u16: ast::CharOrU16 {
883 CharacterLiteral(cl) => ast::CharOrU16::Char(cl),
884 unsigned_32_bit_int[u] => ast::CharOrU16::U16(u as u16),
885 }
886
887 unsigned_32_bit_int: u32 {
892 DecimalLiteral(v) => {
893 match u32::try_from(v) {
894 Ok(n) => { n },
895 Err(err) => {
896 panic!("{}\nNumber out of range for u32.\n{}", span!(), err);
898 },
899 }
900 }
901 }
902
903 floating_point_type: ast::DataType {
904 Float32T => ast::DataType::from_token(Float32T, span!()),
905 Float64T => ast::DataType::from_token(Float64T, span!()),
906 }
907
908 signed_integer_type: ast::DataType {
909 Int8T => ast::DataType::from_token(Int8T, span!()),
910 Int16T => ast::DataType::from_token(Int16T, span!()),
911 Int32T => ast::DataType::from_token(Int32T, span!()),
912 Int64T => ast::DataType::from_token(Int64T, span!()),
913 }
914
915 unsigned_integer_type: ast::DataType {
916 UInt8T => ast::DataType::from_token(UInt8T, span!()),
917 UInt16T => ast::DataType::from_token(UInt16T, span!()),
918 UInt32T => ast::DataType::from_token(UInt32T, span!()),
919 UInt64T => ast::DataType::from_token(UInt64T, span!()),
920 }
921
922 array_data_type: ast::DataType {
923 Int8ArrayT => ast::DataType::from_token(Int8ArrayT, span!()),
924 Int16ArrayT => ast::DataType::from_token(Int16ArrayT, span!()),
925 Int32ArrayT => ast::DataType::from_token(Int32ArrayT, span!()),
926 UInt8ArrayT => ast::DataType::from_token(UInt8ArrayT, span!()),
927 UInt16ArrayT => ast::DataType::from_token(UInt16ArrayT, span!()),
928 UInt32ArrayT => ast::DataType::from_token(UInt32ArrayT, span!()),
929 UInt32UInt8ArrayT => ast::DataType::from_token(UInt32UInt8ArrayT, span!()),
930 }
931
932 optional_name: Option<String> {
933 epsilon => None,
934 Identifier(id) => Some(id)
935 }
936
937 epsilon: () {
938 => {}, }
940}
941
942pub fn parse<I: Iterator<Item = (DCToken, Span)>>(
944 i: I,
945) -> Result<ast::Root, (Option<(DCToken, Span)>, &'static str)> {
946 parse_(i)
947}
948
949#[cfg(test)]
950mod tests {
951 use super::ast;
952 use super::parse;
953 use crate::parser::lexer::Lexer;
954
955 fn parse_dcfile_string(input: &str) -> ast::Root {
956 let lexer = Lexer::new(input).inspect(|tok| eprintln!("token: {:?}", tok));
957 let dc_file_ast: ast::Root = parse(lexer).unwrap();
958
959 dc_file_ast
960 }
961
962 #[test]
963 fn python_module_imports() {
964 let dc_file: ast::Root = parse_dcfile_string(
965 "
966 from example_views import DistributedDonut
967 from views import DistributedDonut/AI/OV
968 from views/AI/OV/UD import DistributedDonut/AI/OV/UD
969 from views/AI import DistributedDonut
970 from game.views.Donut/AI import DistributedDonut/AI
971 from views import *
972
973 /* The next one tests handling legal python identifiers
974 * that may be lexed as tokens other than Id/Module.
975 */
976 from db.char import DistributedDonut
977 ",
978 );
979
980 assert_eq!(dc_file.type_declarations.len(), 7);
981 }
982
983 #[test]
984 fn legal_python_module_identifiers() {
985 #[rustfmt::skip]
987 let legal_identifiers: Vec<&str> = vec![
988 "char", "int8", "int16", "int32", "int64",
989 "uint8", "uint16", "uint32", "uint64", "float32", "float64",
990 "int8array", "int16array", "int32array",
991 "uint8array", "uint16array", "uint32array", "uint32uint8array",
992 "string", "blob", "blob32", "dclass", "struct", "keyword",
993 "typedef", "switch", "default", "break",
994 ];
995 let mut dc_file: String = String::new();
996
997 for module_name in &legal_identifiers {
998 let code: String = format!("from {} import DistributedClass\n", *module_name);
999 dc_file.push_str(code.as_str());
1000 }
1001 parse_dcfile_string(dc_file.as_str());
1002 }
1003
1004 #[test]
1005 fn keyword_definitions() {
1006 parse_dcfile_string(
1007 "
1008 keyword p2p;
1009 keyword monkey;
1010 keyword unreliable;
1011 keyword db;
1012 ",
1013 );
1014 }
1015
1016 #[test]
1017 fn struct_declarations() {
1018 parse_dcfile_string(
1019 "
1020 struct GiftItem {
1021 blob Item;
1022 string giftTag;
1023 };
1024
1025 struct Activity {
1026 string activityName;
1027 uint8 activityId;
1028 };
1029
1030 struct Party {
1031 activity activities[];
1032 uint8 status;
1033 };
1034
1035 struct Fixture {
1036 bool;
1037 int32/10 x;
1038 int32/10 y;
1039 int32/10 z;
1040 int16/10 h;
1041 int16/10 p;
1042 int16/10 r;
1043 string state;
1044 };
1045 ",
1046 );
1047 }
1048
1049 #[test]
1050 fn distributed_class() {
1051 parse_dcfile_string(
1052 "
1053 dclass Avatar {
1054 string name;
1055 uint16 health;
1056
1057 set_xyzh(int16 x, int16 y, int16 z, int16 h) broadcast required;
1058 indicate_intent(int16 / 10, int16 / 10) ownsend airecv;
1059 };
1060
1061 dclass OfflineShardManager : DistributedObject {
1062 clientSetZone(uint32) airecv clsend;
1063 requestZoneIdMessage(uint32, uint16) airecv clsend;
1064 requestZoneIdResponse(uint32, uint16);
1065 };
1066
1067 dclass ShardStats {
1068 setShardId(uint32) broadcast required ram;
1069 setAvatarCount(uint32) broadcast required ram;
1070 setNewAvatarCount(uint32) broadcast required ram;
1071 setStats : setAvatarCount, setNewAvatarCount;
1072 };
1073
1074 dclass DistributedChild : Parent, Parent2 {
1075 };
1076 ",
1077 );
1078 }
1079
1080 #[test]
1081 fn switch_fields() {
1082 parse_dcfile_string(
1083 "
1084 struct BuffData {
1085 switch (uint16) {
1086 case 0:
1087 break;
1088 case 1:
1089 uint8 val1;
1090 break;
1091 case 2:
1092 uint8 val1;
1093 uint8 val2;
1094 break;
1095 case 3:
1096 uint8 val1;
1097 break;
1098 case 4:
1099 int16/100 val1;
1100 break;
1101 };
1102 switch OptionalName (uint8) {
1103 case 0:
1104 break;
1105 default:
1106 uint8 value[0-5];
1107 uint32uint8array value2;
1108 SomeStruct value3;
1109 break;
1110 };
1111 switch WithDefault (char) {
1112 case 'a':
1113 break;
1114 case 'b':
1115 case 'c':
1116 case 'd':
1117 default:
1118 string val1;
1119 break;
1120 };
1121 };
1122 ",
1123 );
1124 }
1125
1126 #[test]
1127 #[should_panic]
1128 fn switch_redundant_break() {
1129 parse_dcfile_string(
1130 "
1131 struct BuffData {
1132 switch (uint16) {
1133 case 0:
1134 break;
1135 break;
1136 };
1137 };
1138 ",
1139 );
1140 }
1141
1142 #[test]
1143 fn atomic_fields() {
1144 parse_dcfile_string(
1145 "
1146 dclass AtomicFields {
1147 simple();
1148 keyw0rd() ram;
1149 keywords() db ownsend airecv;
1150 parameter(string);
1151 params(bool, char, float64);
1152 named_params(bool flag = true, string text);
1153 };
1154 ",
1155 );
1156 }
1157
1158 #[test]
1159 fn molecular_fields() {
1160 parse_dcfile_string(
1161 "
1162 dclass MolecularFields {
1163 setXYZ : setX, setY, setZ;
1164 setPos : setXYZ;
1165 setXY : setX, setY;
1166 setHPR : setH, setP, setR;
1167 };
1168 ",
1169 );
1170 }
1171
1172 #[test]
1173 fn field_data_types() {
1174 parse_dcfile_string(
1175 "
1176 struct MethodDataTypesTest {
1177 Char character;
1178 blob Item;
1179 blob32 pandaOnlyToken;
1180 float32 astronOnlyToken;
1181 string giftTag;
1182 int32(0-990999) testMethodValue;
1183 int8(-1-1) testNegativeValues;
1184 int8(-5--99) testNegativeValuesPartTwo;
1185 int8(+0-+9) plusForPositiveForSomeReason;
1186 int8array arrayDataTypeTest;
1187 int16array anotherArray;
1188 int32array evenMoreComplexArray;
1189 uint8array byteArray;
1190 uint16array unsignedIntegerArray;
1191 uint32array unsignedLongArray;
1192 uint32uint8array thisWeirdPandaArrayType;
1193 };
1194 ",
1195 );
1196 }
1197
1198 #[test]
1199 fn value_transforms() {
1200 parse_dcfile_string(
1201 "
1202 struct TransformedTypesTest {
1203 int32%360 angle;
1204 int32%360/1000 floatingPointAngle;
1205 int32/1000 efficientFloatIn32Bits;
1206 float32 waitIsntAstronsFloat32TheSame;
1207 int16(int32) forTheStaticallyTypedLanguages;
1208 int16(float64)(0.0-1.0) withRangeTest;
1209 int16(float32)%360/10.0 anotherTest;
1210 int16(uint32)/10 moreTests;
1211 bool thisIsLiterallyJustAn8BitInt;
1212 uint16/1000(0-1) youCanStackThemToo;
1213 int64/10000(+50-+999) [] thisIsValid;
1214 int8%10(0-10) anotherOne;
1215 int32('a'-'b') numericRangeWithChar;
1216 float32(0.1-0.99) floatingRange;
1217 float32%10.0 modulusWithFloat;
1218 float32(float64)%10.0 coverage;
1219 int16%100/10(-80-+100) lastTest;
1220 };
1221 ",
1222 );
1223 }
1224
1225 #[test]
1226 fn numeric_ranges() {
1227 parse_dcfile_string(
1228 "
1229 struct NumericRanges {
1230 int8(0-1) thisIsLiterallyABoolean;
1231 int64(-5) signedRange;
1232 int64(+50-+999) thisIsValid;
1233 int32('a') numericRangeWithChar;
1234 int32('a'-'z') rangeMinMaxWithChar;
1235 float32(0.1-0.99) floatingRange;
1236 float32(0.1) anotherFloatRange;
1237 int32() pandaSaysThisIsLegal;
1238 };
1239 ",
1240 );
1241 }
1242
1243 #[test]
1244 #[should_panic]
1245 fn invalid_numeric_ranges() {
1246 parse_dcfile_string(
1247 "
1248 struct InvalidNumericRange {
1249 uint64('a'-10);
1250 };
1251 ",
1252 );
1253 }
1254
1255 #[test]
1256 fn parameters_with_default() {
1257 parse_dcfile_string(
1258 "
1259 struct ParamsWithDefaultTest {
1260 string = \"\";
1261 MyStruct[] = [];
1262 MyStruct strukt[] = [];
1263 int32 = -99;
1264 string = \"VALUE\";
1265 string = 0xabcdef;
1266 uint16 accessLevel = 0;
1267 bool = false;
1268 };
1269 ",
1270 );
1271 }
1272
1273 #[test]
1274 fn array_ranges() {
1275 parse_dcfile_string(
1276 "
1277 struct ArrayRangesTest {
1278 uint8 test['a'];
1279 uint8 test2[9];
1280 uint32uint8array[0-1] test3;
1281 uint32uint8array[0-1][9-99] test4;
1282 uint8 test5['a'-'b'] [ ];
1283 string(5) test6; // builtin array type
1284 };
1285 ",
1286 );
1287 }
1288
1289 #[test]
1290 fn array_expansions() {
1291 parse_dcfile_string(
1292 "
1293 struct ArrayExpansionsTest {
1294 uint8array test = [0];
1295 uint8array test2 = [0 * 10];
1296 int8array test3 = [-1 * 10];
1297 int8array test4 = [5 * 5, 10 * 10, -2 * 4];
1298 uint8array test5 = [0xf * 10];
1299 uint8array test6 = [\"TEST\" * 2];
1300 };
1301 ",
1302 );
1303 }
1304
1305 #[test]
1306 #[should_panic]
1307 fn integer_literal_overflow() {
1308 parse_dcfile_string(
1309 "
1310 struct OverflowTest {
1311 test(uint8array = [0 * 4294967296]);
1312 };
1313 ",
1314 );
1315 }
1316
1317 #[test]
1318 fn developer_defined_keywords() {
1319 parse_dcfile_string(
1320 "
1321 keyword f6f7;
1322
1323 dclass DistributedDonut {
1324 testingField() f6f7;
1325 };
1326 ",
1327 );
1328 }
1329
1330 #[test]
1331 fn handle_deprecated_bool_alias() {
1332 parse_dcfile_string(
1336 "
1337 typedef uint8 bool;
1338 ",
1339 );
1340 }
1341}