1use std::fmt::{Display, Formatter, Write as _};
2use std::mem;
3use crate::lexer::CodePosition;
4use crate::parser::ast::AST;
5use crate::parser::ParsingError;
6
7#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
8pub enum OperatorType {
9 All,
10 General,
11 Math,
12 Condition,
13}
14
15impl OperatorType {
16 pub fn is_compatible_with(&self, operator_type: OperatorType) -> bool {
17 *self == OperatorType::All || operator_type == OperatorType::General || *self == operator_type
18 }
19}
20
21impl Display for OperatorType {
22 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
23 f.write_str(match self {
24 OperatorType::All => "ALL",
25 OperatorType::General => "GENERAL",
26 OperatorType::Math => "MATH",
27 OperatorType::Condition => "CONDITION",
28 })
29 }
30}
31
32#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
33pub enum Operator {
34 Non,
36 Len,
37 DeepCopy,
38 Concat,
39 Spaceship,
40 Elvis,
41 NullCoalescing,
42 InlineIf,
43
44 MathNon,
46 Pow,
47 Pos,
48 Inv,
49 BitwiseNot,
50 Inc,
51 Dec,
52 Mul,
53 Div,
54 TruncDiv,
55 FloorDiv,
56 CeilDiv,
57 Mod,
58 Add,
59 Sub,
60 Lshift,
61 Rshift,
62 Rzshift,
63 BitwiseAnd,
64 BitwiseXor,
65 BitwiseOr,
66
67 ConditionalNon,
69 Not,
70 InstanceOf,
71 Equals,
72 NotEquals,
73 Matches,
74 NotMatches,
75 StrictEquals,
76 StrictNotEquals,
77 LessThan,
78 GreaterThan,
79 LessThanOrEquals,
80 GreaterThanOrEquals,
81 And,
82 Or,
83
84 Comma,
87 GetItem,
88 OptionalGetItem,
89 Slice,
90 OptionalSlice,
91 MemberAccess,
92 MemberAccessThis,
94 OptionalMemberAccess,
95 MemberAccessPointer,
96}
97
98impl Operator {
99 pub fn symbol(&self) -> &'static str {
100 match self {
101 Operator::Non => "",
103 Operator::Len => "@",
104 Operator::DeepCopy => "^",
105 Operator::Concat => "|||",
106 Operator::Spaceship => "<=>",
107 Operator::Elvis => "?:",
108 Operator::NullCoalescing => "??",
109 Operator::InlineIf => "?...:",
110
111 Operator::MathNon => "",
113 Operator::Pow => "**",
114 Operator::Pos => "+",
115 Operator::Inv => "-",
116 Operator::BitwiseNot => "~",
117 Operator::Inc => "+|",
118 Operator::Dec => "-|",
119 Operator::Mul => "*",
120 Operator::Div => "/",
121 Operator::TruncDiv => "~/",
122 Operator::FloorDiv => "//",
123 Operator::CeilDiv => "^/",
124 Operator::Mod => "%",
125 Operator::Add => "+",
126 Operator::Sub => "-",
127 Operator::Lshift => "<<",
128 Operator::Rshift => ">>",
129 Operator::Rzshift => ">>>",
130 Operator::BitwiseAnd => "&",
131 Operator::BitwiseXor => "^",
132 Operator::BitwiseOr => "|",
133
134 Operator::ConditionalNon => "",
136 Operator::Not => "!",
137 Operator::InstanceOf => "~~",
138 Operator::Equals => "==",
139 Operator::NotEquals => "!=",
140 Operator::Matches => "=~",
141 Operator::NotMatches => "!=~",
142 Operator::StrictEquals => "===",
143 Operator::StrictNotEquals => "!==",
144 Operator::LessThan => "<",
145 Operator::GreaterThan => ">",
146 Operator::LessThanOrEquals => "<=",
147 Operator::GreaterThanOrEquals => ">=",
148 Operator::And => "&&",
149 Operator::Or => "||",
150
151 Operator::Comma => ",",
153 Operator::GetItem => "[...]",
154 Operator::OptionalGetItem => "?.[...]",
155 Operator::Slice => "[...:...]",
156 Operator::OptionalSlice => "?.[...:...]",
157 Operator::MemberAccess => "::",
158 Operator::MemberAccessThis => "::",
159 Operator::OptionalMemberAccess => "?::",
160 Operator::MemberAccessPointer => "->",
161 }
162 }
163
164 pub fn arity(&self) -> usize {
165 match self {
166 Operator::Non => 1,
168 Operator::Len => 1,
169 Operator::DeepCopy => 1,
170 Operator::Concat => 2,
171 Operator::Spaceship => 2,
172 Operator::Elvis => 2,
173 Operator::NullCoalescing => 2,
174 Operator::InlineIf => 3,
175
176 Operator::MathNon => 1,
178 Operator::Pow => 2,
179 Operator::Pos => 1,
180 Operator::Inv => 1,
181 Operator::BitwiseNot => 1,
182 Operator::Inc => 1,
183 Operator::Dec => 1,
184 Operator::Mul => 2,
185 Operator::Div => 2,
186 Operator::TruncDiv => 2,
187 Operator::FloorDiv => 2,
188 Operator::CeilDiv => 2,
189 Operator::Mod => 2,
190 Operator::Add => 2,
191 Operator::Sub => 2,
192 Operator::Lshift => 2,
193 Operator::Rshift => 2,
194 Operator::Rzshift => 2,
195 Operator::BitwiseAnd => 2,
196 Operator::BitwiseXor => 2,
197 Operator::BitwiseOr => 2,
198
199 Operator::ConditionalNon => 1,
201 Operator::Not => 1,
202 Operator::InstanceOf => 2,
203 Operator::Equals => 2,
204 Operator::NotEquals => 2,
205 Operator::Matches => 2,
206 Operator::NotMatches => 2,
207 Operator::StrictEquals => 2,
208 Operator::StrictNotEquals => 2,
209 Operator::LessThan => 2,
210 Operator::GreaterThan => 2,
211 Operator::LessThanOrEquals => 2,
212 Operator::GreaterThanOrEquals => 2,
213 Operator::And => 2,
214 Operator::Or => 2,
215
216 Operator::Comma => 2,
218 Operator::GetItem => 2,
219 Operator::OptionalGetItem => 2,
220 Operator::Slice => 3,
221 Operator::OptionalSlice => 3,
222 Operator::MemberAccess => 2,
223 Operator::MemberAccessThis => 1,
224 Operator::OptionalMemberAccess => 2,
225 Operator::MemberAccessPointer => 2,
226 }
227 }
228
229 pub fn is_unary(&self) -> bool {
230 self.arity() == 1
231 }
232
233 pub fn is_binary(&self) -> bool {
234 self.arity() == 2
235 }
236
237 pub fn is_ternary(&self) -> bool {
238 self.arity() == 3
239 }
240
241 pub fn precedence(&self) -> isize {
242 match self {
243 Operator::Non => -1,
245 Operator::Len => 1,
246 Operator::DeepCopy => 1,
247 Operator::Concat => 5,
248 Operator::Spaceship => 10,
249 Operator::Elvis => 13,
250 Operator::NullCoalescing => 13,
251 Operator::InlineIf => 14,
252
253 Operator::MathNon => -1,
255 Operator::Pow => 2,
256 Operator::Pos => 3,
257 Operator::Inv => 3,
258 Operator::BitwiseNot => 3,
259 Operator::Inc => 3,
260 Operator::Dec => 3,
261 Operator::Mul => 4,
262 Operator::Div => 4,
263 Operator::TruncDiv => 4,
264 Operator::FloorDiv => 4,
265 Operator::CeilDiv => 4,
266 Operator::Mod => 4,
267 Operator::Add => 5,
268 Operator::Sub => 5,
269 Operator::Lshift => 6,
270 Operator::Rshift => 6,
271 Operator::Rzshift => 6,
272 Operator::BitwiseAnd => 7,
273 Operator::BitwiseXor => 8,
274 Operator::BitwiseOr => 9,
275
276 Operator::ConditionalNon => -1,
278 Operator::Not => 3,
279 Operator::InstanceOf => 10,
280 Operator::Equals => 10,
281 Operator::NotEquals => 10,
282 Operator::Matches => 10,
283 Operator::NotMatches => 10,
284 Operator::StrictEquals => 10,
285 Operator::StrictNotEquals => 10,
286 Operator::LessThan => 10,
287 Operator::GreaterThan => 10,
288 Operator::LessThanOrEquals => 10,
289 Operator::GreaterThanOrEquals => 10,
290 Operator::And => 11,
291 Operator::Or => 12,
292
293 Operator::Comma => 15,
295 Operator::GetItem => 0,
296 Operator::OptionalGetItem => 0,
297 Operator::Slice => 0,
298 Operator::OptionalSlice => 0,
299 Operator::MemberAccess => 0,
300 Operator::MemberAccessThis => 0,
301 Operator::OptionalMemberAccess => 0,
302 Operator::MemberAccessPointer => 0,
303 }
304 }
305
306 pub fn lazy_evaluation(&self) -> bool {
307 matches!(
308 self,
309
310 Operator::Elvis |
312 Operator::NullCoalescing |
313 Operator::InlineIf |
314
315 Operator::And |
317 Operator::Or |
318
319 Operator::MemberAccess |
321 Operator::MemberAccessThis |
322 Operator::OptionalMemberAccess |
323 Operator::MemberAccessPointer
324 )
325 }
326
327 pub fn operator_type(&self) -> OperatorType {
328 match self {
329 Operator::Non |
331 Operator::Len |
332 Operator::DeepCopy |
333 Operator::Concat |
334 Operator::Spaceship |
335 Operator::Elvis |
336 Operator::NullCoalescing |
337 Operator::InlineIf => OperatorType::General,
338
339 Operator::MathNon |
341 Operator::Pow |
342 Operator::Pos |
343 Operator::Inv |
344 Operator::BitwiseNot |
345 Operator::Inc |
346 Operator::Dec |
347 Operator::Mul |
348 Operator::Div |
349 Operator::TruncDiv |
350 Operator::FloorDiv |
351 Operator::CeilDiv |
352 Operator::Mod |
353 Operator::Add |
354 Operator::Sub |
355 Operator::Lshift |
356 Operator::Rshift |
357 Operator::Rzshift |
358 Operator::BitwiseAnd |
359 Operator::BitwiseXor |
360 Operator::BitwiseOr => OperatorType::Math,
361
362 Operator::ConditionalNon |
364 Operator::Not |
365 Operator::InstanceOf |
366 Operator::Equals |
367 Operator::NotEquals |
368 Operator::Matches |
369 Operator::NotMatches |
370 Operator::StrictEquals |
371 Operator::StrictNotEquals |
372 Operator::LessThan |
373 Operator::GreaterThan |
374 Operator::LessThanOrEquals |
375 Operator::GreaterThanOrEquals |
376 Operator::And |
377 Operator::Or => OperatorType::Condition,
378
379 Operator::Comma |
381 Operator::GetItem |
382 Operator::OptionalGetItem |
383 Operator::Slice |
384 Operator::OptionalSlice |
385 Operator::MemberAccess |
386 Operator::MemberAccessThis |
387 Operator::OptionalMemberAccess |
388 Operator::MemberAccessPointer => OperatorType::All,
389 }
390 }
391}
392
393impl Display for Operator {
394 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
395 f.write_str(match self {
396 Operator::Non => "NON",
398 Operator::Len => "LEN",
399 Operator::DeepCopy => "DEEP_COPY",
400 Operator::Concat => "CONCAT",
401 Operator::Spaceship => "SPACESHIP",
402 Operator::Elvis => "ELVIS",
403 Operator::NullCoalescing => "NULL_COALESCING",
404 Operator::InlineIf => "INLINE_IF",
405
406 Operator::MathNon => "MATH_NON",
408 Operator::Pow => "POW",
409 Operator::Pos => "POS",
410 Operator::Inv => "INV",
411 Operator::BitwiseNot => "BITWISE_NOT",
412 Operator::Inc => "INC",
413 Operator::Dec => "DEC",
414 Operator::Mul => "MUL",
415 Operator::Div => "DIV",
416 Operator::TruncDiv => "TRUNC_DIV",
417 Operator::FloorDiv => "FLOOR_DIV",
418 Operator::CeilDiv => "CEIL_DIV",
419 Operator::Mod => "MOD",
420 Operator::Add => "ADD",
421 Operator::Sub => "SUB",
422 Operator::Lshift => "LSHIFT",
423 Operator::Rshift => "RSHIFT",
424 Operator::Rzshift => "RZSHIFT",
425 Operator::BitwiseAnd => "BITWISE_AND",
426 Operator::BitwiseXor => "BITWISE_XOR",
427 Operator::BitwiseOr => "BITWISE_OR",
428
429 Operator::ConditionalNon => "CONDITIONAL_NON",
431 Operator::Not => "NOT",
432 Operator::InstanceOf => "INSTANCE_OF",
433 Operator::Equals => "EQUALS",
434 Operator::NotEquals => "NOT_EQUALS",
435 Operator::Matches => "MATCHES",
436 Operator::NotMatches => "NOT_MATCHES",
437 Operator::StrictEquals => "STRICT_EQUALS",
438 Operator::StrictNotEquals => "STRICT_NOT_EQUALS",
439 Operator::LessThan => "LESS_THAN",
440 Operator::GreaterThan => "GREATER_THAN",
441 Operator::LessThanOrEquals => "LESS_THAN_OR_EQUALS",
442 Operator::GreaterThanOrEquals => "GREATER_THAN_OR_EQUALS",
443 Operator::And => "AND",
444 Operator::Or => "OR",
445
446 Operator::Comma => "COMMA",
448 Operator::GetItem => "GET_ITEM",
449 Operator::OptionalGetItem => "OPTIONAL_GET_ITEM",
450 Operator::Slice => "SLICE",
451 Operator::OptionalSlice => "OPTIONAL_SLICE",
452 Operator::MemberAccess => "MEMBER_ACCESS",
453 Operator::MemberAccessThis => "MEMBER_ACCESS_THIS",
454 Operator::OptionalMemberAccess => "OPTIONAL_MEMBER_ACCESS",
455 Operator::MemberAccessPointer => "MEMBER_ACCESS_POINTER",
456 })
457 }
458}
459
460#[derive(Debug, Clone, PartialEq)]
461pub struct FunctionDefinition {
462 function_name: Option<Box<str>>,
463 overloaded: bool,
464 combinator: bool,
465 doc_comment: Option<Box<str>>,
466 return_value_type_constraint: Option<Box<str>>,
467 function_body: AST,
468}
469
470impl FunctionDefinition {
471 pub fn new(function_name: Option<Box<str>>, overloaded: bool, combinator: bool, doc_comment: Option<Box<str>>, return_value_type_constraint: Option<Box<str>>, function_body: AST) -> Self {
472 Self { function_name, overloaded, combinator, doc_comment, return_value_type_constraint, function_body }
473 }
474
475 pub fn function_name(&self) -> Option<&str> {
476 self.function_name.as_deref()
477 }
478
479 pub fn overloaded(&self) -> bool {
480 self.overloaded
481 }
482
483 pub fn combinator(&self) -> bool {
484 self.combinator
485 }
486
487 pub fn doc_comment(&self) -> Option<&str> {
488 self.doc_comment.as_deref()
489 }
490
491 pub fn return_value_type_constraint(&self) -> Option<&str> {
492 self.return_value_type_constraint.as_deref()
493 }
494
495 pub fn function_body(&self) -> &AST {
496 &self.function_body
497 }
498}
499
500#[derive(Debug, Clone, PartialEq)]
501pub struct StructMember {
502 name: Box<str>,
503 type_constraint: Option<Box<str>>,
504}
505
506impl StructMember {
507 pub fn new(name: Box<str>, type_constraint: Option<Box<str>>) -> Self {
508 Self { name, type_constraint }
509 }
510
511 pub fn name(&self) -> &str {
512 &self.name
513 }
514
515 pub fn type_constraint(&self) -> Option<&str> {
516 self.type_constraint.as_deref()
517 }
518}
519
520#[derive(Debug, Clone, PartialEq)]
521pub struct StructDefinition {
522 struct_name: Option<Box<str>>,
523
524 members: Vec<StructMember>,
525}
526
527impl StructDefinition {
528 pub fn new(struct_name: Option<Box<str>>, members: Vec<StructMember>) -> Self {
529 Self { struct_name, members }
530 }
531
532 pub fn struct_name(&self) -> Option<&str> {
533 self.struct_name.as_deref()
534 }
535
536 pub fn members(&self) -> &[StructMember] {
537 &self.members
538 }
539}
540
541#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
542pub enum Visibility {
543 Private,
544 Protected,
545 Public,
546}
547
548impl Visibility {
549 pub fn from_symbol(symbol: u8) -> Option<Visibility> {
550 match symbol {
551 b'-' => Some(Visibility::Private),
552 b'~' => Some(Visibility::Protected),
553 b'+' => Some(Visibility::Public),
554
555 _ => None,
556 }
557 }
558
559 pub fn from_keyword(keyword: &str) -> Option<Visibility> {
560 match keyword {
561 "private" => Some(Visibility::Private),
562 "protected" => Some(Visibility::Protected),
563 "public" => Some(Visibility::Public),
564
565 _ => None,
566 }
567 }
568
569 pub fn symbol(&self) -> &'static str {
570 match self {
571 Visibility::Private => "-",
572 Visibility::Protected => "~",
573 Visibility::Public => "+",
574 }
575 }
576}
577
578#[derive(Debug, Clone, PartialEq)]
579pub struct ClassMember {
580 name: Box<str>,
581 type_constraint: Option<Box<str>>,
582 value: Option<Node>,
583 final_flag: bool,
584 visibility: Visibility,
585}
586
587impl ClassMember {
588 pub fn new(name: Box<str>, type_constraint: Option<Box<str>>, value: Option<Node>, final_flag: bool, visibility: Visibility) -> Self {
589 Self { name, type_constraint, value, final_flag, visibility }
590 }
591
592 pub fn name(&self) -> &str {
593 &self.name
594 }
595
596 pub fn type_constraint(&self) -> Option<&str> {
597 self.type_constraint.as_deref()
598 }
599
600 pub fn value(&self) -> Option<&Node> {
601 self.value.as_ref()
602 }
603
604 pub fn final_flag(&self) -> bool {
605 self.final_flag
606 }
607
608 pub fn visibility(&self) -> Visibility {
609 self.visibility
610 }
611}
612
613#[derive(Debug, Clone, PartialEq)]
614pub struct Method {
615 name: Box<str>,
616 body: Node,
617 override_flag: bool,
618 visibility: Visibility,
619}
620
621impl Method {
622 pub fn new(name: Box<str>, definition: Node, override_flag: bool, visibility: Visibility) -> Self {
623 Self { name, body: definition, override_flag, visibility }
624 }
625
626 pub fn name(&self) -> &str {
627 &self.name
628 }
629
630 pub fn body(&self) -> &Node {
631 &self.body
632 }
633
634 pub fn override_flag(&self) -> bool {
635 self.override_flag
636 }
637
638 pub fn visibility(&self) -> Visibility {
639 self.visibility
640 }
641}
642
643#[derive(Debug, Clone, PartialEq)]
644pub struct Constructor {
645 body: Node,
646 visibility: Visibility,
647}
648
649impl Constructor {
650 pub fn new(definition: Node, visibility: Visibility) -> Self {
651 Self { body: definition, visibility }
652 }
653
654 pub fn body(&self) -> &Node {
655 &self.body
656 }
657
658 pub fn visibility(&self) -> Visibility {
659 self.visibility
660 }
661}
662
663#[derive(Debug, Clone, PartialEq)]
664pub struct ClassDefinition {
665 class_name: Option<Box<str>>,
666
667 static_members: Vec<ClassMember>,
668
669 members: Vec<ClassMember>,
670
671 methods: Vec<Method>,
673
674 constructors: Vec<Constructor>,
675
676 parent_classes: Vec<Node>,
678}
679
680impl ClassDefinition {
681 pub fn new(
682 class_name: Option<Box<str>>,
683 static_members: Vec<ClassMember>,
684 members: Vec<ClassMember>,
685 methods: Vec<Method>,
686 constructors: Vec<Constructor>,
687 parent_classes: Vec<Node>,
688 ) -> Self {
689 if members.iter().any(|member| member.value.is_some()) {
690 panic!("Non-static class members can not have a default value");
691 }
692
693 Self {
694 class_name,
695 static_members,
696 members,
697 methods,
698 constructors,
699 parent_classes,
700 }
701 }
702
703 pub fn class_name(&self) -> Option<&str> {
704 self.class_name.as_deref()
705 }
706
707 pub fn static_members(&self) -> &[ClassMember] {
708 &self.static_members
709 }
710
711 pub fn members(&self) -> &[ClassMember] {
712 &self.members
713 }
714
715 pub fn methods(&self) -> &[Method] {
716 &self.methods
717 }
718
719 pub fn constructors(&self) -> &[Constructor] {
720 &self.constructors
721 }
722
723 pub fn parent_classes(&self) -> &[Node] {
724 &self.parent_classes
725 }
726}
727
728#[derive(Debug, Clone, PartialEq)]
729pub struct OperationExpression {
730 left_side_operand: Option<Box<Node>>,
731 middle_operand: Option<Box<Node>>,
732 right_side_operand: Option<Box<Node>>,
733 operator: Operator,
734 operator_type: OperatorType,
735}
736
737impl OperationExpression {
738 pub fn new(
739 left_side_operand: Option<Box<Node>>,
740 middle_operand: Option<Box<Node>>,
741 right_side_operand: Option<Box<Node>>,
742 operator: Operator,
743 operator_type: OperatorType,
744 ) -> Self {
745 let arity = operator.arity();
746 if matches!(
747 arity,
748
749 1 if left_side_operand.is_none() || middle_operand.is_some() || right_side_operand.is_some(),
750 ) {
751 panic!("Invalid operand count for unary operator");
752 }
753
754 if matches!(
755 arity,
756
757 2 if left_side_operand.is_none() || middle_operand.is_some() || right_side_operand.is_none(),
758 ) {
759 panic!("Invalid operand count for binary operator");
760 }
761
762 if matches!(
763 arity,
764
765 3 if left_side_operand.is_none() || middle_operand.is_none() || right_side_operand.is_none(),
766 ) {
767 panic!("Invalid operand count for ternary operator");
768 }
769
770 if !operator.operator_type().is_compatible_with(operator_type) {
771 panic!("Node type is not compatible with the operator");
772 }
773
774 Self {
775 left_side_operand,
776 middle_operand,
777 right_side_operand,
778 operator,
779 operator_type,
780 }
781 }
782
783 pub fn left_side_operand(&self) -> Option<&Node> {
784 self.left_side_operand.as_deref()
785 }
786
787 pub fn middle_operand(&self) -> Option<&Node> {
788 self.middle_operand.as_deref()
789 }
790
791 pub fn right_side_operand(&self) -> Option<&Node> {
792 self.right_side_operand.as_deref()
793 }
794
795 pub fn operator(&self) -> Operator {
796 self.operator
797 }
798
799 pub fn operator_type(&self) -> OperatorType {
800 self.operator.operator_type()
801 }
802}
803
804#[derive(Debug, Clone, PartialEq)]
805pub struct ConditionalNode {
806 node: Node,
807}
808
809impl ConditionalNode {
810 pub fn new(node: Node) -> Self {
811 if !matches!(node.node_data, NodeData::Condition{..}) {
812 panic!("Node type is not compatible with this node");
813 }
814
815 Self { node }
816 }
817
818 pub fn node(&self) -> &Node {
819 &self.node
820 }
821}
822
823#[derive(Debug, Clone, PartialEq)]
824pub enum NodeData {
825 List,
826
827 ParsingError {
828 error: ParsingError,
829 message: Box<str>,
830 },
831
832 Assignment,
833
834 EscapeSequence(char),
835 UnicodeEscapeSequence(Box<str>),
836
837 UnprocessedVariableName(Box<str>),
838 VariableName {
839 variable_name: Box<str>,
840 type_constraint: Option<Box<str>>,
841 },
842
843 ArgumentSeparator(Box<str>),
844
845 FunctionCall(Box<str>),
846 FunctionCallPreviousNodeValue {
847 leading_whitespace: Box<str>,
848 trailing_whitespace: Box<str>,
849 },
850
851 FunctionDefinition(Box<FunctionDefinition>),
852
853 IfStatementPartIf {
854 if_body: AST,
855 condition: Box<ConditionalNode>,
856 },
857 IfStatementPartElse(AST),
858 IfStatement,
859
860 LoopStatementPartLoop(AST),
861 LoopStatementPartWhile {
862 loop_body: AST,
863 condition: Box<ConditionalNode>,
864 },
865 LoopStatementPartUntil {
866 loop_body: AST,
867 condition: Box<ConditionalNode>,
868 },
869 LoopStatementPartRepeat {
870 loop_body: AST,
871 var_pointer_node: Box<Node>,
872 repeat_count_node: Box<Node>,
873 },
874 LoopStatementPartForEach {
875 loop_body: AST,
876 var_pointer_node: Box<Node>,
877 composite_or_text_node: Box<Node>,
878 },
879 LoopStatementPartElse(AST),
880 LoopStatement,
881
882 TryStatementPartTry(AST),
883 TryStatementPartSoftTry(AST),
884 TryStatementPartNonTry(AST),
885 TryStatementPartCatch {
886 try_body: AST,
887 errors: Option<Vec<Node>>,
888 },
889 TryStatementPartElse(AST),
890 TryStatementPartFinally(AST),
891 TryStatement,
892
893 ContinueBreakStatement {
894 number_node: Option<Box<Node>>,
895 continue_node: bool,
896 },
897
898 Operation(OperationExpression),
899 Math(OperationExpression),
900 Condition(OperationExpression),
901
902 Return,
903 Throw,
904
905 IntValue(i32),
906 LongValue(i64),
907 FloatValue(f32),
908 DoubleValue(f64),
909 CharValue(char),
910 TextValue(Box<str>),
911 NullValue,
912 VoidValue,
913 ArrayValue,
914
915 StructDefinition(Box<StructDefinition>),
916
917 ClassDefinition(Box<ClassDefinition>),
918}
919
920#[derive(Debug, Clone)]
921pub struct Node {
922 pos: CodePosition,
923 child_nodes: Vec<Node>,
924 node_data: NodeData,
925}
926
927impl Node {
928 pub fn new_list_node(child_nodes: Vec<Node>) -> Node {
929 let pos = if child_nodes.is_empty() {
930 CodePosition::EMPTY
931 }else {
932 child_nodes.first().unwrap().pos().combine(&child_nodes.last().unwrap().pos())
933 };
934
935 Self {
936 pos,
937 child_nodes,
938 node_data: NodeData::List,
939 }
940 }
941
942 pub fn new_parsing_error_node(pos: CodePosition, error: ParsingError, message: impl Into<Box<str>>) -> Node {
943 Self {
944 pos,
945 child_nodes: Default::default(),
946 node_data: NodeData::ParsingError {
947 error,
948 message: message.into(),
949 },
950 }
951 }
952
953 pub fn new_assignment_node(lvalue: Node, rvalue: Node) -> Node {
954 let pos = lvalue.pos.combine(&rvalue.pos);
955
956 let child_nodes = vec![lvalue, rvalue];
957
958 Self {
959 pos,
960 child_nodes,
961 node_data: NodeData::Assignment,
962 }
963 }
964
965 pub fn new_escape_sequence_node(pos: CodePosition, char: char) -> Node {
966 Self {
967 pos,
968 child_nodes: Default::default(),
969 node_data: NodeData::EscapeSequence(char),
970 }
971 }
972
973 pub fn new_unicode_escape_sequence_node(pos: CodePosition, hex_codepoint: impl Into<Box<str>>) -> Node {
974 Self {
975 pos,
976 child_nodes: Default::default(),
977 node_data: NodeData::UnicodeEscapeSequence(hex_codepoint.into()),
978 }
979 }
980
981 pub fn new_unprocessed_variable_name_node(pos: CodePosition, variable_name: impl Into<Box<str>>) -> Node {
982 Self {
983 pos,
984 child_nodes: Default::default(),
985 node_data: NodeData::UnprocessedVariableName(variable_name.into()),
986 }
987 }
988
989 pub fn new_variable_name_node(pos: CodePosition, variable_name: impl Into<Box<str>>, type_constraint: Option<Box<str>>) -> Node {
990 Self {
991 pos,
992 child_nodes: Default::default(),
993 node_data: NodeData::VariableName {
994 variable_name: variable_name.into(),
995 type_constraint,
996 },
997 }
998 }
999
1000 pub fn new_argument_separator_node(pos: CodePosition, original_text: impl Into<Box<str>>) -> Node {
1001 Self {
1002 pos,
1003 child_nodes: Default::default(),
1004 node_data: NodeData::ArgumentSeparator(original_text.into()),
1005 }
1006 }
1007
1008 pub fn new_function_call_node(pos: CodePosition, argument_list: Vec<Node>, function_name: impl Into<Box<str>>) -> Node {
1009 Self {
1010 pos,
1011 child_nodes: argument_list,
1012 node_data: NodeData::FunctionCall(function_name.into()),
1013 }
1014 }
1015
1016 pub fn new_function_call_previous_node_value_node(
1017 pos: CodePosition,
1018 leading_whitespace: impl Into<Box<str>>,
1019 trailing_whitespace: impl Into<Box<str>>,
1020 argument_list: Vec<Node>,
1021 ) -> Node {
1022 Self {
1023 pos,
1024 child_nodes: argument_list,
1025 node_data: NodeData::FunctionCallPreviousNodeValue {
1026 leading_whitespace: leading_whitespace.into(),
1027 trailing_whitespace: trailing_whitespace.into(),
1028 },
1029 }
1030 }
1031
1032 pub fn new_function_definition_node(pos: CodePosition, function_definition: FunctionDefinition, parameter_list: Vec<Node>) -> Node {
1033 Self {
1034 pos,
1035 child_nodes: parameter_list,
1036 node_data: NodeData::FunctionDefinition(Box::new(function_definition)),
1037 }
1038 }
1039
1040 pub fn new_if_statement_part_if_node(pos: CodePosition, if_body: AST, condition: ConditionalNode) -> Node {
1041 Self {
1042 pos,
1043 child_nodes: Default::default(),
1044 node_data: NodeData::IfStatementPartIf {
1045 if_body,
1046 condition: Box::new(condition),
1047 },
1048 }
1049 }
1050
1051 pub fn new_if_statement_part_else_node(pos: CodePosition, if_body: AST) -> Node {
1052 Self {
1053 pos,
1054 child_nodes: Default::default(),
1055 node_data: NodeData::IfStatementPartElse(if_body),
1056 }
1057 }
1058
1059 pub fn new_if_statement_node(pos: CodePosition, nodes: Vec<Node>) -> Node {
1060 if nodes.iter().any(|node| {
1061 !matches!(node.node_data, NodeData::IfStatementPartIf{..}) &&
1062 !matches!(node.node_data, NodeData::IfStatementPartElse(..))
1063 }) {
1064 panic!("Node type is not compatible with this node");
1065 }
1066
1067 Self {
1068 pos,
1069 child_nodes: nodes,
1070 node_data: NodeData::IfStatement,
1071 }
1072 }
1073
1074 pub fn new_loop_statement_part_loop_node(pos: CodePosition, loop_body: AST) -> Node {
1075 Self {
1076 pos,
1077 child_nodes: Default::default(),
1078 node_data: NodeData::LoopStatementPartLoop(loop_body),
1079 }
1080 }
1081
1082 pub fn new_loop_statement_part_while_node(pos: CodePosition, loop_body: AST, condition: ConditionalNode) -> Node {
1083 Self {
1084 pos,
1085 child_nodes: Default::default(),
1086 node_data: NodeData::LoopStatementPartWhile {
1087 loop_body,
1088 condition: Box::new(condition),
1089 },
1090 }
1091 }
1092
1093 pub fn new_loop_statement_part_until_node(pos: CodePosition, loop_body: AST, condition: ConditionalNode) -> Node {
1094 Self {
1095 pos,
1096 child_nodes: Default::default(),
1097 node_data: NodeData::LoopStatementPartUntil {
1098 loop_body,
1099 condition: Box::new(condition),
1100 },
1101 }
1102 }
1103
1104 pub fn new_loop_statement_part_repeat_node(pos: CodePosition, loop_body: AST, var_pointer_node: Node, repeat_count_node: Node) -> Node {
1105 Self {
1106 pos,
1107 child_nodes: Default::default(),
1108 node_data: NodeData::LoopStatementPartRepeat {
1109 loop_body,
1110 var_pointer_node: Box::new(var_pointer_node),
1111 repeat_count_node: Box::new(repeat_count_node),
1112 },
1113 }
1114 }
1115
1116 pub fn new_loop_statement_part_for_each_node(pos: CodePosition, loop_body: AST, var_pointer_node: Node, composite_or_text_node: Node) -> Node {
1117 Self {
1118 pos,
1119 child_nodes: Default::default(),
1120 node_data: NodeData::LoopStatementPartForEach {
1121 loop_body,
1122 var_pointer_node: Box::new(var_pointer_node),
1123 composite_or_text_node: Box::new(composite_or_text_node),
1124 },
1125 }
1126 }
1127
1128 pub fn new_loop_statement_part_else_node(pos: CodePosition, loop_body: AST) -> Node {
1129 Self {
1130 pos,
1131 child_nodes: Default::default(),
1132 node_data: NodeData::LoopStatementPartElse(loop_body),
1133 }
1134 }
1135
1136 pub fn new_loop_statement_node(pos: CodePosition, nodes: Vec<Node>) -> Node {
1137 if nodes.iter().any(|node| {
1138 !matches!(node.node_data, NodeData::LoopStatementPartLoop(..)) &&
1139 !matches!(node.node_data, NodeData::LoopStatementPartWhile{..}) &&
1140 !matches!(node.node_data, NodeData::LoopStatementPartUntil{..}) &&
1141 !matches!(node.node_data, NodeData::LoopStatementPartRepeat{..}) &&
1142 !matches!(node.node_data, NodeData::LoopStatementPartForEach{..}) &&
1143 !matches!(node.node_data, NodeData::LoopStatementPartElse(..))
1144 }) {
1145 panic!("Node type is not compatible with this node");
1146 }
1147
1148 Self {
1149 pos,
1150 child_nodes: nodes,
1151 node_data: NodeData::LoopStatement,
1152 }
1153 }
1154
1155 pub fn new_continue_break_statement_node(pos: CodePosition, number_node: Option<Box<Node>>, continue_node: bool) -> Node {
1156 Self {
1157 pos,
1158 child_nodes: Default::default(),
1159 node_data: NodeData::ContinueBreakStatement {
1160 number_node,
1161 continue_node,
1162 },
1163 }
1164 }
1165
1166 pub fn new_try_statement_part_try_node(pos: CodePosition, try_body: AST) -> Node {
1167 Self {
1168 pos,
1169 child_nodes: Default::default(),
1170 node_data: NodeData::TryStatementPartTry(try_body),
1171 }
1172 }
1173
1174 pub fn new_try_statement_part_soft_try_node(pos: CodePosition, try_body: AST) -> Node {
1175 Self {
1176 pos,
1177 child_nodes: Default::default(),
1178 node_data: NodeData::TryStatementPartSoftTry(try_body),
1179 }
1180 }
1181
1182 pub fn new_try_statement_part_non_try_node(pos: CodePosition, try_body: AST) -> Node {
1183 Self {
1184 pos,
1185 child_nodes: Default::default(),
1186 node_data: NodeData::TryStatementPartNonTry(try_body),
1187 }
1188 }
1189
1190 pub fn new_try_statement_part_catch_node(pos: CodePosition, try_body: AST, errors: Option<Vec<Node>>) -> Node {
1191 Self {
1192 pos,
1193 child_nodes: Default::default(),
1194 node_data: NodeData::TryStatementPartCatch {
1195 try_body,
1196 errors,
1197 },
1198 }
1199 }
1200
1201 pub fn new_try_statement_part_else_node(pos: CodePosition, try_body: AST) -> Node {
1202 Self {
1203 pos,
1204 child_nodes: Default::default(),
1205 node_data: NodeData::TryStatementPartElse(try_body),
1206 }
1207 }
1208
1209 pub fn new_try_statement_part_finally_node(pos: CodePosition, try_body: AST) -> Node {
1210 Self {
1211 pos,
1212 child_nodes: Default::default(),
1213 node_data: NodeData::TryStatementPartFinally(try_body),
1214 }
1215 }
1216
1217 pub fn new_try_statement_node(pos: CodePosition, nodes: Vec<Node>) -> Node {
1218 if nodes.iter().any(|node| {
1219 !matches!(node.node_data, NodeData::TryStatementPartTry(..)) &&
1220 !matches!(node.node_data, NodeData::TryStatementPartSoftTry{..}) &&
1221 !matches!(node.node_data, NodeData::TryStatementPartNonTry{..}) &&
1222 !matches!(node.node_data, NodeData::TryStatementPartCatch{..}) &&
1223 !matches!(node.node_data, NodeData::TryStatementPartElse(..)) &&
1224 !matches!(node.node_data, NodeData::TryStatementPartFinally(..))
1225 }) {
1226 panic!("Node type is not compatible with this node");
1227 }
1228
1229 Self {
1230 pos,
1231 child_nodes: nodes,
1232 node_data: NodeData::TryStatement,
1233 }
1234 }
1235
1236 pub fn new_operation_statement_node(
1237 pos: CodePosition,
1238 operation_expression: OperationExpression,
1239 ) -> Node {
1240 Self {
1241 pos,
1242 child_nodes: Default::default(),
1243 node_data: match operation_expression.operator_type {
1244 OperatorType::All | OperatorType::General => NodeData::Operation(operation_expression),
1245 OperatorType::Math => NodeData::Math(operation_expression),
1246 OperatorType::Condition => NodeData::Condition(operation_expression),
1247 },
1248 }
1249 }
1250
1251 pub fn new_return_statement_node(pos: CodePosition, return_value: Option<Node>) -> Node {
1252 Self {
1253 pos,
1254 child_nodes: match return_value {
1255 Some(return_value) => vec![return_value],
1256 None => vec![],
1257 },
1258 node_data: NodeData::Return,
1259 }
1260 }
1261
1262 pub fn new_throw_statement_node(pos: CodePosition, throw_value: Node, message_value: Option<Node>) -> Node {
1263 Self {
1264 pos,
1265 child_nodes: match message_value {
1266 Some(message_value) => vec![throw_value, message_value],
1267 None => vec![throw_value],
1268 },
1269 node_data: NodeData::Throw,
1270 }
1271 }
1272
1273 pub fn new_int_value_node(pos: CodePosition, value: i32) -> Node {
1274 Self {
1275 pos,
1276 child_nodes: Default::default(),
1277 node_data: NodeData::IntValue(value),
1278 }
1279 }
1280
1281 pub fn new_long_value_node(pos: CodePosition, value: i64) -> Node {
1282 Self {
1283 pos,
1284 child_nodes: Default::default(),
1285 node_data: NodeData::LongValue(value),
1286 }
1287 }
1288
1289 pub fn new_float_value_node(pos: CodePosition, value: f32) -> Node {
1290 Self {
1291 pos,
1292 child_nodes: Default::default(),
1293 node_data: NodeData::FloatValue(value),
1294 }
1295 }
1296
1297 pub fn new_double_value_node(pos: CodePosition, value: f64) -> Node {
1298 Self {
1299 pos,
1300 child_nodes: Default::default(),
1301 node_data: NodeData::DoubleValue(value),
1302 }
1303 }
1304
1305 pub fn new_char_value_node(pos: CodePosition, value: char) -> Node {
1306 Self {
1307 pos,
1308 child_nodes: Default::default(),
1309 node_data: NodeData::CharValue(value),
1310 }
1311 }
1312
1313 pub fn new_text_value_node(pos: CodePosition, value: impl Into<Box<str>>) -> Node {
1314 Self {
1315 pos,
1316 child_nodes: Default::default(),
1317 node_data: NodeData::TextValue(value.into()),
1318 }
1319 }
1320
1321 pub fn new_null_value_node(pos: CodePosition) -> Node {
1322 Self {
1323 pos,
1324 child_nodes: Default::default(),
1325 node_data: NodeData::NullValue,
1326 }
1327 }
1328
1329 pub fn new_void_value_node(pos: CodePosition) -> Node {
1330 Self {
1331 pos,
1332 child_nodes: Default::default(),
1333 node_data: NodeData::VoidValue,
1334 }
1335 }
1336
1337 pub fn new_array_value_node(pos: CodePosition, child_nodes: Vec<Node>) -> Node {
1338 Self {
1339 pos,
1340 child_nodes,
1341 node_data: NodeData::ArrayValue,
1342 }
1343 }
1344
1345 pub fn new_struct_definition_node(pos: CodePosition, struct_definition: StructDefinition) -> Node {
1346 Self {
1347 pos,
1348 child_nodes: Default::default(),
1349 node_data: NodeData::StructDefinition(Box::new(struct_definition)),
1350 }
1351 }
1352
1353 pub fn new_class_definition_node(pos: CodePosition, class_definition: ClassDefinition) -> Node {
1354 Self {
1355 pos,
1356 child_nodes: Default::default(),
1357 node_data: NodeData::ClassDefinition(Box::new(class_definition)),
1358 }
1359 }
1360
1361 pub fn pos(&self) -> CodePosition {
1362 self.pos
1363 }
1364
1365 pub fn child_nodes(&self) -> &[Node] {
1366 &self.child_nodes
1367 }
1368
1369 pub fn node_data(&self) -> &NodeData {
1370 &self.node_data
1371 }
1372
1373 pub fn operator(&self) -> Option<Operator> {
1374 match &self.node_data {
1375 NodeData::Operation(operation_expression) |
1376 NodeData::Math(operation_expression) |
1377 NodeData::Condition(operation_expression) =>
1378 Some(operation_expression.operator),
1379
1380 _ => None,
1381 }
1382 }
1383
1384 pub fn left_side_operand(&self) -> Option<&Node> {
1385 match &self.node_data {
1386 NodeData::Operation(operation_expression) |
1387 NodeData::Math(operation_expression) |
1388 NodeData::Condition(operation_expression) =>
1389 operation_expression.left_side_operand.as_deref(),
1390
1391 _ => None,
1392 }
1393 }
1394
1395 pub fn into_left_side_operand(self) -> Option<Node> {
1396 match self.node_data {
1397 NodeData::Operation(operation_expression) |
1398 NodeData::Math(operation_expression) |
1399 NodeData::Condition(operation_expression) =>
1400 operation_expression.left_side_operand.map(|node| *node),
1401
1402 _ => None,
1403 }
1404 }
1405
1406 pub fn middle_operand(&self) -> Option<&Node> {
1407 match &self.node_data {
1408 NodeData::Operation(operation_expression) |
1409 NodeData::Math(operation_expression) |
1410 NodeData::Condition(operation_expression) =>
1411 operation_expression.middle_operand.as_deref(),
1412
1413 _ => None,
1414 }
1415 }
1416
1417 pub fn into_middle_operand(self) -> Option<Node> {
1418 match self.node_data {
1419 NodeData::Operation(operation_expression) |
1420 NodeData::Math(operation_expression) |
1421 NodeData::Condition(operation_expression) =>
1422 operation_expression.middle_operand.map(|node| *node),
1423
1424 _ => None,
1425 }
1426 }
1427
1428 pub fn right_side_operand(&self) -> Option<&Node> {
1429 match &self.node_data {
1430 NodeData::Operation(operation_expression) |
1431 NodeData::Math(operation_expression) |
1432 NodeData::Condition(operation_expression) =>
1433 operation_expression.right_side_operand.as_deref(),
1434
1435 _ => None,
1436 }
1437 }
1438
1439 pub fn into_right_side_operand(self) -> Option<Node> {
1440 match self.node_data {
1441 NodeData::Operation(operation_expression) |
1442 NodeData::Math(operation_expression) |
1443 NodeData::Condition(operation_expression) =>
1444 operation_expression.right_side_operand.map(|node| *node),
1445
1446 _ => None,
1447 }
1448 }
1449
1450 pub fn operands(&self) -> (Option<&Node>, Option<&Node>, Option<&Node>) {
1451 match &self.node_data {
1452 NodeData::Operation(operation_expression) |
1453 NodeData::Math(operation_expression) |
1454 NodeData::Condition(operation_expression) =>
1455 (
1456 operation_expression.left_side_operand.as_deref(),
1457 operation_expression.middle_operand.as_deref(),
1458 operation_expression.right_side_operand.as_deref(),
1459 ),
1460
1461 _ => (None, None, None),
1462 }
1463 }
1464
1465 pub fn into_operands(self) -> (Option<Node>, Option<Node>, Option<Node>) {
1466 match self.node_data {
1467 NodeData::Operation(operation_expression) |
1468 NodeData::Math(operation_expression) |
1469 NodeData::Condition(operation_expression) =>
1470 (
1471 operation_expression.left_side_operand.map(|node| *node),
1472 operation_expression.middle_operand.map(|node| *node),
1473 operation_expression.right_side_operand.map(|node| *node),
1474 ),
1475
1476 _ => (None, None, None),
1477 }
1478 }
1479
1480 fn try_evaluate_escape_sequence(char: char) -> Option<String> {
1481 match char {
1482 '0' => Some("\0".to_string()),
1483 'n' => Some("\n".to_string()),
1484 'r' => Some("\r".to_string()),
1485 'f' => Some("\u{000C}".to_string()),
1486 's' => Some(" ".to_string()),
1487 'e' => Some(String::new()),
1488 'E' => Some("\u{001B}".to_string()),
1489 'b' => Some("\u{0008}".to_string()),
1490 't' => Some("\t".to_string()),
1491
1492 '$' | '&' | '#' | ',' | '.' | '(' | ')' | '[' | ']' | '{' | '}' | '=' | '<' | '>' |
1493 '+' | '-' | '/' | '*' | '%' | '|' | '~' | '^' | '?' | ':' | '@' | '\u{25b2}' |
1494 '\u{25bc}' | '\"' | '\\' => Some(char.to_string()),
1495
1496 _ => None,
1497 }
1498 }
1499
1500 pub(super) fn optimize_nodes(nodes: &mut Vec<Node>) {
1501 let mut i = 0;
1502 while i < nodes.len() {
1503 nodes[i].optimize_node();
1504
1505 let mut builder = None;
1506 if let NodeData::EscapeSequence(char) = nodes[i].node_data() {
1507 builder = Self::try_evaluate_escape_sequence(*char);
1508 }else if let NodeData::TextValue(str) = nodes[i].node_data() {
1509 builder = Some(str.to_string());
1510 }else if let NodeData::CharValue(char) = nodes[i].node_data() {
1511 builder = Some(char.to_string());
1512 }
1513
1514 if let Some(mut builder) = builder {
1515 let mut pos = nodes[i].pos();
1516
1517 let mut changed = false;
1518 let index = i + 1;
1519 while index < nodes.len() {
1520 match nodes[index].node_data() {
1521 NodeData::EscapeSequence(char) => {
1522 if let Some(str) = Self::try_evaluate_escape_sequence(*char) {
1523 changed = true;
1524
1525 builder += &str;
1526 pos = pos.combine(&nodes[index].pos());
1527
1528 nodes.remove(index);
1529 continue;
1530 }
1531
1532 break;
1533 },
1534
1535 NodeData::TextValue(str) => {
1536 changed = true;
1537
1538 builder += str;
1539 pos = pos.combine(&nodes[index].pos());
1540
1541 nodes.remove(index);
1542 continue;
1543 },
1544
1545 NodeData::CharValue(char) => {
1546 changed = true;
1547
1548 builder += &char.to_string();
1549 pos = pos.combine(&nodes[index].pos());
1550
1551 nodes.remove(index);
1552 continue;
1553 },
1554
1555 _ => break,
1556 }
1557 }
1558
1559 if changed {
1560 nodes[i] = Node::new_text_value_node(pos, builder);
1561 }
1562 }
1563
1564 i += 1;
1565 }
1566 }
1567
1568 pub(super) fn optimize_node(&mut self) {
1569 if matches!(self.node_data, NodeData::List | NodeData::FunctionCall(..) |
1570 NodeData::FunctionCallPreviousNodeValue { .. } | NodeData::IfStatement |
1571 NodeData::LoopStatement | NodeData::TryStatement) {
1572 Self::optimize_nodes(&mut self.child_nodes);
1573 }else {
1574 for node in &mut self.child_nodes {
1575 node.optimize_node();
1576 }
1577 }
1578
1579 match &mut self.node_data {
1580 NodeData::List if self.child_nodes.len() == 1 => {
1581 let _ = mem::replace(self, self.child_nodes[0].clone());
1582 },
1583
1584 NodeData::FunctionDefinition(function_definition) => {
1585 function_definition.function_body.optimize_ast();
1586 },
1587
1588 NodeData::IfStatementPartIf { if_body, condition } => {
1589 if_body.optimize_ast();
1590
1591 Self::optimize_node(&mut condition.node);
1592 },
1593
1594 NodeData::IfStatementPartElse(if_body) => {
1595 if_body.optimize_ast();
1596 },
1597
1598 NodeData::LoopStatementPartLoop(loop_body) |
1599 NodeData::LoopStatementPartElse(loop_body) => {
1600 loop_body.optimize_ast();
1601 },
1602
1603 NodeData::LoopStatementPartWhile { loop_body, condition } |
1604 NodeData::LoopStatementPartUntil { loop_body, condition } => {
1605 loop_body.optimize_ast();
1606
1607 Self::optimize_node(&mut condition.node);
1608 },
1609
1610 NodeData::LoopStatementPartRepeat {
1611 loop_body,
1612 var_pointer_node,
1613 repeat_count_node,
1614 } => {
1615 loop_body.optimize_ast();
1616
1617 Self::optimize_node(var_pointer_node);
1618 Self::optimize_node(repeat_count_node);
1619 },
1620
1621 NodeData::LoopStatementPartForEach {
1622 loop_body,
1623 var_pointer_node,
1624 composite_or_text_node,
1625 } => {
1626 loop_body.optimize_ast();
1627
1628 Self::optimize_node(var_pointer_node);
1629 Self::optimize_node(composite_or_text_node);
1630 },
1631
1632 NodeData::TryStatementPartTry(try_body) |
1633 NodeData::TryStatementPartSoftTry(try_body) |
1634 NodeData::TryStatementPartNonTry(try_body) |
1635 NodeData::TryStatementPartElse(try_body) |
1636 NodeData::TryStatementPartFinally(try_body) => {
1637 try_body.optimize_ast();
1638 },
1639
1640 NodeData::TryStatementPartCatch { try_body, errors } => {
1641 try_body.optimize_ast();
1642
1643 if let Some(errors) = errors {
1644 Self::optimize_nodes(errors);
1645 }
1646 },
1647
1648 NodeData::ContinueBreakStatement { number_node: Some(number_node), .. } => {
1649 Self::optimize_node(number_node);
1650 },
1651
1652 NodeData::Operation(operation_expression) |
1653 NodeData::Math(operation_expression) |
1654 NodeData::Condition(operation_expression) => {
1655 if let Some(node) = &mut operation_expression.left_side_operand {
1656 Self::optimize_node(node);
1657 }
1658
1659 if let Some(node) = &mut operation_expression.middle_operand {
1660 Self::optimize_node(node);
1661 }
1662
1663 if let Some(node) = &mut operation_expression.right_side_operand {
1664 Self::optimize_node(node);
1665 }
1666
1667 if matches!(operation_expression.operator(), Operator::Non | Operator::MathNon |
1668 Operator::ConditionalNon) {
1669 let mut inner_non_value = None;
1670
1671 if let Some(node) = operation_expression.left_side_operand.as_deref() {
1672 if let
1673 NodeData::Operation(inner_operation_expression) |
1674 NodeData::Math(inner_operation_expression) |
1675 NodeData::Condition(inner_operation_expression) = &node.node_data {
1676 if matches!(inner_operation_expression.operator(), Operator::Non) ||
1677 mem::discriminant(&operation_expression.operator) ==
1678 mem::discriminant(&inner_operation_expression.operator) {
1679 inner_non_value.clone_from(&inner_operation_expression.left_side_operand);
1680 }
1681 }
1682 }
1683
1684 if inner_non_value.is_some() {
1685 operation_expression.left_side_operand = inner_non_value;
1686 }
1687 }
1688 },
1689
1690 NodeData::ClassDefinition(class_definition) => {
1691 for member in &mut class_definition.static_members {
1692 if let Some(value) = &mut member.value {
1693 Self::optimize_node(value);
1694 }
1695 }
1696
1697 for member in &mut class_definition.members {
1698 if let Some(value) = &mut member.value {
1699 Self::optimize_node(value);
1700 }
1701 }
1702
1703 for method in &mut class_definition.methods {
1704 Self::optimize_node(&mut method.body);
1705 }
1706
1707 for constructor in &mut class_definition.constructors {
1708 Self::optimize_node(&mut constructor.body);
1709 }
1710 },
1711
1712 _ => {},
1713 }
1714 }
1715}
1716
1717impl PartialEq for Node {
1718 fn eq(&self, other: &Self) -> bool {
1719 self.child_nodes == other.child_nodes && self.node_data == other.node_data
1720 }
1721}
1722
1723impl Display for Node {
1724 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1725 let mut builder = String::new();
1726
1727 match &self.node_data {
1728 NodeData::List => {
1729 let _ = write!(builder, "ListNode: Position: {}", self.pos.to_compact_string());
1730 builder += ", Children: {\n";
1731 for node in self.child_nodes.iter() {
1732 for token in node.to_string().split("\n") {
1733 let _ = writeln!(builder, "\t{token}");
1734 }
1735 }
1736 builder += "}";
1737 },
1738
1739 NodeData::ParsingError { error, message } => {
1740 let _ = write!(builder, "ParsingErrorNode: Position: {}", self.pos.to_compact_string());
1741 let _ = write!(builder, ", Error: \"{error}\"");
1742 let _ = write!(builder, ", Message: \"{message}\"");
1743 },
1744
1745 NodeData::Assignment => {
1746 let _ = write!(builder, "AssignmentNode: Position: {}", self.pos.to_compact_string());
1747 builder += ", lvalue: {\n";
1748 for token in format!("{}", self.child_nodes[0]).split("\n") {
1749 let _ = writeln!(builder, "\t{token}");
1750 }
1751 builder += "}, rvalue: {\n";
1752 for token in format!("{}", self.child_nodes[1]).split("\n") {
1753 let _ = writeln!(builder, "\t{token}");
1754 }
1755 builder += "}";
1756 },
1757
1758 NodeData::EscapeSequence(char) => {
1759 let _ = write!(builder, "EscapeSequenceNode: Position: {}", self.pos.to_compact_string());
1760 let _ = write!(builder, ", Char: \"{char}\"");
1761 },
1762
1763 NodeData::UnicodeEscapeSequence(hex_code_point) => {
1764 let _ = write!(builder, "UnicodeEscapeSequenceNode: Position: {}", self.pos.to_compact_string());
1765 let _ = write!(builder, ", hexCodePoint: \"{hex_code_point}\"");
1766 },
1767
1768 NodeData::UnprocessedVariableName(variable_name) => {
1769 let _ = write!(builder, "UnprocessedVariableNameNode: Position: {}", self.pos.to_compact_string());
1770 let _ = write!(builder, ", Variable Name: \"{variable_name}\"");
1771 },
1772
1773 NodeData::VariableName { variable_name, type_constraint } => {
1774 let _ = write!(builder, "VariableNameNode: Position: {}", self.pos.to_compact_string());
1775 let _ = write!(builder, ", Variable Name: \"{variable_name}\"");
1776 let _ = write!(builder, ", TypeConstraint: \"{}\"", type_constraint.as_deref().unwrap_or("null"));
1777 },
1778
1779 NodeData::ArgumentSeparator(original_text) => {
1780 let _ = write!(builder, "ArgumentSeparatorNode: Position: {}", self.pos.to_compact_string());
1781 let _ = write!(builder, ", OriginalText: \"{original_text}\"");
1782 },
1783
1784 NodeData::FunctionCall(function_name) => {
1785 let _ = write!(builder, "FunctionCallNode: Position: {}", self.pos.to_compact_string());
1786 let _ = write!(builder, ", FunctionName: \"{function_name}\"");
1787 builder += ", ParameterList: {\n";
1788 for node in self.child_nodes.iter() {
1789 for token in node.to_string().split("\n") {
1790 let _ = writeln!(builder, "\t{token}");
1791 }
1792 }
1793 builder += "}";
1794 },
1795
1796 NodeData::FunctionCallPreviousNodeValue { leading_whitespace, trailing_whitespace } => {
1797 let _ = write!(builder, "FunctionCallNode: Position: {}", self.pos.to_compact_string());
1798 builder += ", ArgumentList: {\n";
1799 for node in self.child_nodes.iter() {
1800 for token in node.to_string().split("\n") {
1801 let _ = writeln!(builder, "\t{token}");
1802 }
1803 }
1804 let _ = write!(builder, "}}, LeadingWhitespace: \"{leading_whitespace}\"");
1805 let _ = write!(builder, ", TrailingWhitespace: \"{trailing_whitespace}\"");
1806 },
1807
1808 NodeData::FunctionDefinition(function_definition) => {
1809 let _ = write!(builder, "FunctionDefinitionNode: Position: {}", self.pos.to_compact_string());
1810 let _ = write!(builder, ", FunctionName: \"{}\"", function_definition.function_name.as_deref().unwrap_or("null"));
1811 let _ = write!(builder, ", Overloaded: \"{}\"", function_definition.overloaded);
1812 let _ = write!(builder, ", Combinator: \"{}\"", function_definition.combinator);
1813 let _ = write!(builder, ", Doc Comment: \"{}\"", function_definition.doc_comment.as_deref().unwrap_or("null"));
1814 builder += ", ParameterList: {\n";
1815 for node in self.child_nodes.iter() {
1816 for token in node.to_string().split("\n") {
1817 let _ = writeln!(builder, "\t{token}");
1818 }
1819 }
1820 let _ = write!(builder,
1821 "}}, ReturnValueTypeConstraint: \"{}\"",
1822 function_definition.return_value_type_constraint.as_deref().unwrap_or("null"),
1823 );
1824 builder += ", FunctionBody: {\n";
1825 for token in function_definition.function_body.to_string().split("\n") {
1826 let _ = writeln!(builder, "\t{token}");
1827 }
1828 builder += "}";
1829 },
1830
1831 NodeData::IfStatementPartIf { if_body, condition } => {
1832 let _ = write!(builder, "IfStatementPartIfNode: Position: {}", self.pos.to_compact_string());
1833 builder += ", Condition: {\n";
1834 for token in condition.node.to_string().split("\n") {
1835 let _ = writeln!(builder, "\t{token}");
1836 }
1837 builder += "}, IfBody: {\n";
1838 for token in if_body.to_string().split("\n") {
1839 let _ = writeln!(builder, "\t{token}");
1840 }
1841 builder += "}";
1842 },
1843
1844 NodeData::IfStatementPartElse(if_body) => {
1845 let _ = write!(builder, "IfStatementPartElseNode: Position: {}", self.pos.to_compact_string());
1846 builder += ", IfBody: {\n";
1847 for token in if_body.to_string().split("\n") {
1848 let _ = writeln!(builder, "\t{token}");
1849 }
1850 builder += "}";
1851 },
1852
1853 NodeData::IfStatement => {
1854 let _ = write!(builder, "IfStatementNode: Position: {}", self.pos.to_compact_string());
1855 builder += ", Children: {\n";
1856 for node in self.child_nodes.iter() {
1857 for token in node.to_string().split("\n") {
1858 let _ = writeln!(builder, "\t{token}");
1859 }
1860 }
1861 builder += "}";
1862 },
1863
1864 NodeData::LoopStatementPartLoop(loop_body) => {
1865 let _ = write!(builder, "LoopStatementPartLoopNode: Position: {}", self.pos.to_compact_string());
1866 builder += ", LoopBody: {\n";
1867 for token in loop_body.to_string().split("\n") {
1868 let _ = writeln!(builder, "\t{token}");
1869 }
1870 builder += "}";
1871 },
1872
1873 NodeData::LoopStatementPartWhile { loop_body, condition } => {
1874 let _ = write!(builder, "LoopStatementPartWhileNode: Position: {}", self.pos.to_compact_string());
1875 builder += ", Condition: {\n";
1876 for token in condition.node.to_string().split("\n") {
1877 let _ = writeln!(builder, "\t{token}");
1878 }
1879 builder += "}, LoopBody: {\n";
1880 for token in loop_body.to_string().split("\n") {
1881 let _ = writeln!(builder, "\t{token}");
1882 }
1883 builder += "}";
1884 },
1885
1886 NodeData::LoopStatementPartUntil { loop_body, condition } => {
1887 let _ = write!(builder, "LoopStatementPartUntilNode: Position: {}", self.pos.to_compact_string());
1888 builder += ", Condition: {\n";
1889 for token in condition.node.to_string().split("\n") {
1890 let _ = writeln!(builder, "\t{token}");
1891 }
1892 builder += "}, LoopBody: {\n";
1893 for token in loop_body.to_string().split("\n") {
1894 let _ = writeln!(builder, "\t{token}");
1895 }
1896 builder += "}";
1897 },
1898
1899 NodeData::LoopStatementPartRepeat {
1900 loop_body,
1901 var_pointer_node,
1902 repeat_count_node,
1903 } => {
1904 let _ = write!(builder, "LoopStatementPartRepeatNode: Position: {}", self.pos.to_compact_string());
1905 builder += ", varPointer: {\n";
1906 for token in var_pointer_node.to_string().split("\n") {
1907 let _ = writeln!(builder, "\t{token}");
1908 }
1909 builder += "}, repeatCount: {\n";
1910 for token in repeat_count_node.to_string().split("\n") {
1911 let _ = writeln!(builder, "\t{token}");
1912 }
1913 builder += "}, LoopBody: {\n";
1914 for token in loop_body.to_string().split("\n") {
1915 let _ = writeln!(builder, "\t{token}");
1916 }
1917 builder += "}";
1918 },
1919
1920 NodeData::LoopStatementPartForEach {
1921 loop_body,
1922 var_pointer_node,
1923 composite_or_text_node,
1924 } => {
1925 let _ = write!(builder, "LoopStatementPartForEachNode: Position: {}", self.pos.to_compact_string());
1926 builder += ", Condition: {\n";
1927 for token in var_pointer_node.to_string().split("\n") {
1928 let _ = writeln!(builder, "\t{token}");
1929 }
1930 builder += "}, compositeOrTextNode: {\n";
1931 for token in composite_or_text_node.to_string().split("\n") {
1932 let _ = writeln!(builder, "\t{token}");
1933 }
1934 builder += "}, LoopBody: {\n";
1935 for token in loop_body.to_string().split("\n") {
1936 let _ = writeln!(builder, "\t{token}");
1937 }
1938 builder += "}";
1939 },
1940
1941 NodeData::LoopStatementPartElse(loop_body) => {
1942 let _ = write!(builder, "LoopStatementPartElseNode: Position: {}", self.pos.to_compact_string());
1943 builder += ", LoopBody: {\n";
1944 for token in loop_body.to_string().split("\n") {
1945 let _ = writeln!(builder, "\t{token}");
1946 }
1947 builder += "}";
1948 },
1949
1950 NodeData::LoopStatement => {
1951 let _ = write!(builder, "LoopStatementNode: Position: {}", self.pos.to_compact_string());
1952 builder += ", Children: {\n";
1953 for node in self.child_nodes.iter() {
1954 for token in node.to_string().split("\n") {
1955 let _ = writeln!(builder, "\t{token}");
1956 }
1957 }
1958 builder += "}";
1959 },
1960
1961 NodeData::TryStatementPartTry(try_body) => {
1962 let _ = write!(builder, "TryStatementPartTryNode: Position: {}", self.pos.to_compact_string());
1963 builder += ", TryBody: {\n";
1964 for token in try_body.to_string().split("\n") {
1965 let _ = writeln!(builder, "\t{token}");
1966 }
1967 builder += "}";
1968 },
1969
1970 NodeData::TryStatementPartSoftTry(try_body) => {
1971 let _ = write!(builder, "TryStatementPartSoftTryNode: Position: {}", self.pos.to_compact_string());
1972 builder += ", TryBody: {\n";
1973 for token in try_body.to_string().split("\n") {
1974 let _ = writeln!(builder, "\t{token}");
1975 }
1976 builder += "}";
1977 },
1978
1979 NodeData::TryStatementPartNonTry(try_body) => {
1980 let _ = write!(builder, "TryStatementPartNonTryNode: Position: {}", self.pos.to_compact_string());
1981 builder += ", TryBody: {\n";
1982 for token in try_body.to_string().split("\n") {
1983 let _ = writeln!(builder, "\t{token}");
1984 }
1985 builder += "}";
1986 },
1987
1988 NodeData::TryStatementPartCatch { try_body, errors } => {
1989 let _ = write!(builder, "TryStatementPartCatchNode: Position: {}", self.pos.to_compact_string());
1990 builder += ", Errors: {\n";
1991 if let Some(errors) = errors {
1992 for node in errors.iter() {
1993 for token in node.to_string().split("\n") {
1994 let _ = writeln!(builder, "\t{token}");
1995 }
1996 }
1997 }else {
1998 builder += "\tnull\n";
1999 }
2000 builder += "}, TryBody: {\n";
2001 for token in try_body.to_string().split("\n") {
2002 let _ = writeln!(builder, "\t{token}");
2003 }
2004 builder += "}";
2005 },
2006
2007 NodeData::TryStatementPartElse(try_body) => {
2008 let _ = write!(builder, "TryStatementPartElseNode: Position: {}", self.pos.to_compact_string());
2009 builder += ", TryBody: {\n";
2010 for token in try_body.to_string().split("\n") {
2011 let _ = writeln!(builder, "\t{token}");
2012 }
2013 builder += "}";
2014 },
2015
2016 NodeData::TryStatementPartFinally(try_body) => {
2017 let _ = write!(builder, "TryStatementPartFinallyNode: Position: {}", self.pos.to_compact_string());
2018 builder += ", TryBody: {\n";
2019 for token in try_body.to_string().split("\n") {
2020 let _ = writeln!(builder, "\t{token}");
2021 }
2022 builder += "}";
2023 },
2024
2025 NodeData::TryStatement => {
2026 let _ = write!(builder, "TryStatementNode: Position: {}", self.pos.to_compact_string());
2027 builder += ", Children: {\n";
2028 for node in self.child_nodes.iter() {
2029 for token in node.to_string().split("\n") {
2030 let _ = writeln!(builder, "\t{token}");
2031 }
2032 }
2033 builder += "}";
2034 },
2035
2036 NodeData::ContinueBreakStatement { number_node, continue_node } => {
2037 let _ = write!(builder, "LoopStatementContinueBreakStatementNode: Position: {}", self.pos.to_compact_string());
2038 builder += ", numberNode: {\n";
2039 if let Some(number_node) = number_node {
2040 for token in number_node.to_string().split("\n") {
2041 let _ = writeln!(builder, "\t{token}");
2042 }
2043 }else {
2044 builder += "\tnull\n";
2045 }
2046 let _ = write!(builder, "}}, continueNode: \"{}\"", continue_node);
2047 },
2048
2049 NodeData::Operation(operation_expression) |
2050 NodeData::Math(operation_expression) |
2051 NodeData::Condition(operation_expression) => {
2052 let _ = write!(builder, "OperationNode: Position: {}", self.pos.to_compact_string());
2053 let _ = write!(builder, ", NodeType: \"{}\"", operation_expression.operator_type);
2054 let _ = write!(builder, ", Operator: \"{}\"", operation_expression.operator);
2055 let _ = write!(builder, ", OperatorType: \"{}\"", operation_expression.operator.operator_type());
2056 builder += ", Operands: {\n";
2057 for node in operation_expression.left_side_operand.iter().
2058 chain(operation_expression.middle_operand.iter()).
2059 chain(operation_expression.right_side_operand.iter()) {
2060 for token in node.to_string().split("\n") {
2061 let _ = writeln!(builder, "\t{token}");
2062 }
2063 }
2064 builder += "}";
2065 },
2066
2067 NodeData::Return => {
2068 let _ = write!(builder, "ReturnNode: Position: {}", self.pos.to_compact_string());
2069 builder += ", Children: {\n";
2070 for node in self.child_nodes.iter() {
2071 for token in node.to_string().split("\n") {
2072 let _ = writeln!(builder, "\t{token}");
2073 }
2074 }
2075 builder += "}";
2076 },
2077
2078 NodeData::Throw => {
2079 let _ = write!(builder, "ThrowNode: Position: {}", self.pos.to_compact_string());
2080 builder += ", ThrowValue: {\n";
2081 for token in self.child_nodes[0].to_string().split("\n") {
2082 let _ = writeln!(builder, "\t{token}");
2083 }
2084 builder += "}, Message: ";
2085 if let Some(message) = self.child_nodes.get(1) {
2086 builder += "{\n";
2087 for token in message.to_string().split("\n") {
2088 let _ = writeln!(builder, "\t{token}");
2089 }
2090 builder += "}";
2091 }else {
2092 builder += "null";
2093 }
2094 },
2095
2096 NodeData::IntValue(value) => {
2097 let _ = write!(builder, "IntValueNode: Position: {}", self.pos.to_compact_string());
2098 let _ = write!(builder, ", Value: \"{value}\"");
2099 },
2100
2101 NodeData::LongValue(value) => {
2102 let _ = write!(builder, "LongValueNode: Position: {}", self.pos.to_compact_string());
2103 let _ = write!(builder, ", Value: \"{value}\"");
2104 },
2105
2106 NodeData::FloatValue(value) => {
2107 let _ = write!(builder, "FloatValueNode: Position: {}", self.pos.to_compact_string());
2108 let _ = write!(builder, ", Value: \"{value}\"");
2109 },
2110
2111 NodeData::DoubleValue(value) => {
2112 let _ = write!(builder, "DoubleValueNode: Position: {}", self.pos.to_compact_string());
2113 let _ = write!(builder, ", Value: \"{value}\"");
2114 },
2115
2116 NodeData::CharValue(value) => {
2117 let _ = write!(builder, "CharValueNode: Position: {}", self.pos.to_compact_string());
2118 let _ = write!(builder, ", Value: \"{value}\"");
2119 },
2120
2121 NodeData::TextValue(value) => {
2122 let _ = write!(builder, "TextValueNode: Position: {}", self.pos.to_compact_string());
2123 let _ = write!(builder, ", Value: \"{value}\"");
2124 },
2125
2126 NodeData::NullValue => {
2127 let _ = write!(builder, "NullValueNode: Position: {}", self.pos.to_compact_string());
2128 },
2129
2130 NodeData::VoidValue => {
2131 let _ = write!(builder, "VoidValueNode: Position: {}", self.pos.to_compact_string());
2132 },
2133
2134 NodeData::ArrayValue => {
2135 let _ = write!(builder, "ArrayNode: Position: {}", self.pos.to_compact_string());
2136 builder += ", Elements: {\n";
2137 for node in self.child_nodes.iter() {
2138 for token in node.to_string().split("\n") {
2139 let _ = writeln!(builder, "\t{token}");
2140 }
2141 }
2142 builder += "}";
2143 },
2144
2145 NodeData::StructDefinition(struct_definition) => {
2146 let _ = write!(builder, "StructDefinitionNode: Position: {}", self.pos.to_compact_string());
2147 let _ = write!(builder, ", StructName: \"{}\"", struct_definition.struct_name.as_deref().unwrap_or("null"));
2148 builder += ", Members{TypeConstraints}: {\n";
2149 for member in struct_definition.members.iter() {
2150 let _ = write!(builder, "\t{}", member.name);
2151 if let Some(type_constraint) = &member.type_constraint {
2152 let _ = write!(builder, "{{{type_constraint}}}");
2153 }
2154 builder += "\n";
2155 }
2156 builder += "}";
2157 },
2158
2159 NodeData::ClassDefinition(class_definition) => {
2160 let _ = write!(builder, "ClassDefinitionNode: Position: {}", self.pos.to_compact_string());
2161 let _ = write!(builder, ", ClassName: \"{}\"", class_definition.class_name.as_deref().unwrap_or("null"));
2162 builder += ", StaticMembers{TypeConstraints} = <value>: {\n";
2163 for member in class_definition.static_members.iter() {
2164 let _ = write!(builder, "\t{}{}{}", member.visibility.symbol(), if member.final_flag {
2165 "final:"
2166 } else {
2167 ""
2168 }, member.name);
2169 if let Some(type_constraint) = &member.type_constraint {
2170 let _ = write!(builder, "{{{type_constraint}}}");
2171 }
2172 if let Some(value) = &member.value {
2173 builder += "= {\n";
2174 for token in value.to_string().split("\n") {
2175 let _ = writeln!(builder, "\t\t{token}");
2176 }
2177 builder += "\t}";
2178 }
2179 builder += "\n";
2180 }
2181 builder += "}, Members{TypeConstraints}: {\n";
2182 for member in class_definition.members.iter() {
2183 let _ = write!(builder, "\t{}{}{}", member.visibility.symbol(), if member.final_flag {
2184 "final:"
2185 } else {
2186 ""
2187 }, member.name);
2188 if let Some(type_constraint) = &member.type_constraint {
2189 let _ = write!(builder, "{{{type_constraint}}}");
2190 }
2191 builder += "\n";
2192 }
2193 builder += "}, MethodName = <definition>: {\n";
2194 for method in class_definition.methods.iter() {
2195 let _ = writeln!(builder, "\t{}{}{} = {{", method.visibility.symbol(), if method.override_flag {
2196 "override:"
2197 } else {
2198 ""
2199 }, method.name);
2200 for token in method.body.to_string().split("\n") {
2201 let _ = writeln!(builder, "\t\t{token}");
2202 }
2203 builder += "\t}\n";
2204 }
2205 builder += "}, Constructors: {\n";
2206 for constructor in class_definition.constructors.iter() {
2207 let _ = writeln!(builder, "\t{}construct = {{", constructor.visibility.symbol());
2208 for token in constructor.body.to_string().split("\n") {
2209 let _ = writeln!(builder, "\t\t{token}");
2210 }
2211 builder += "\t}\n";
2212 }
2213 builder += "}, ParentClasses: {\n";
2214 for node in class_definition.parent_classes.iter() {
2215 for token in node.to_string().split("\n") {
2216 let _ = writeln!(builder, "\t{token}");
2217 }
2218 }
2219 builder += "}";
2220 },
2221 }
2222
2223 f.write_str(builder.as_str())
2224 }
2225}