1use std::fmt::Formatter;
2use std::{borrow::Cow, fmt};
3
4use derive_more::Display;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8use full_moon_derive::{Node, Visit};
9#[cfg(any(feature = "lua52", feature = "luajit"))]
10use lua52::*;
11#[cfg(feature = "lua54")]
12use lua54::*;
13
14#[cfg(feature = "luau")]
15use luau::*;
16
17#[cfg(any(feature = "luau", feature = "cfxlua"))]
18mod compound;
19#[cfg(any(feature = "luau", feature = "cfxlua"))]
20pub use compound::*;
21
22pub use parser_structs::AstResult;
23use punctuated::{Pair, Punctuated};
24use span::ContainedSpan;
25pub use versions::*;
26
27use crate::{
28 tokenizer::{Position, Symbol, Token, TokenReference, TokenType},
29 util::*,
30};
31
32mod parser_structs;
33#[macro_use]
34mod parser_util;
35mod parsers;
36pub mod punctuated;
37pub mod span;
38mod update_positions;
39mod visitors;
40
41#[cfg(feature = "luau")]
42pub mod luau;
43#[cfg(feature = "luau")]
44mod luau_visitors;
45mod versions;
46
47#[cfg(any(feature = "lua52", feature = "luajit"))]
48pub mod lua52;
49#[cfg(feature = "lua54")]
50pub mod lua54;
51#[derive(Clone, Debug, Default, Display, PartialEq, Node, Visit)]
53#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
54#[display(
55 "{}{}",
56 display_optional_punctuated_vec(stmts),
57 display_option(last_stmt.as_ref().map(display_optional_punctuated))
58)]
59pub struct Block {
60 stmts: Vec<(Stmt, Option<TokenReference>)>,
61 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
62 last_stmt: Option<(LastStmt, Option<TokenReference>)>,
63}
64
65impl Block {
66 pub fn new() -> Self {
68 Self {
69 stmts: Vec::new(),
70 last_stmt: None,
71 }
72 }
73
74 pub fn stmts(&self) -> impl Iterator<Item = &Stmt> {
79 self.stmts.iter().map(|(stmt, _)| stmt)
80 }
81
82 pub fn stmts_with_semicolon(&self) -> impl Iterator<Item = &(Stmt, Option<TokenReference>)> {
85 self.stmts.iter()
86 }
87
88 pub fn last_stmt(&self) -> Option<&LastStmt> {
90 Some(&self.last_stmt.as_ref()?.0)
91 }
92
93 pub fn last_stmt_with_semicolon(&self) -> Option<&(LastStmt, Option<TokenReference>)> {
95 self.last_stmt.as_ref()
96 }
97
98 pub fn with_stmts(self, stmts: Vec<(Stmt, Option<TokenReference>)>) -> Self {
101 Self { stmts, ..self }
102 }
103
104 pub fn with_last_stmt(self, last_stmt: Option<(LastStmt, Option<TokenReference>)>) -> Self {
107 Self { last_stmt, ..self }
108 }
109
110 pub(crate) fn merge_blocks(&mut self, other: Self) {
111 self.stmts.extend(other.stmts);
112
113 if self.last_stmt.is_none() {
114 self.last_stmt = other.last_stmt;
115 }
116 }
117}
118
119#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
121#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
122#[non_exhaustive]
123pub enum LastStmt {
124 Break(TokenReference),
126 #[cfg(feature = "luau")]
129 Continue(TokenReference),
130 Return(Return),
132}
133
134#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
136#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
137#[display("{token}{returns}")]
138pub struct Return {
139 token: TokenReference,
140 returns: Punctuated<Expression>,
141}
142
143impl Return {
144 pub fn new() -> Self {
147 Self {
148 token: TokenReference::basic_symbol("return "),
149 returns: Punctuated::new(),
150 }
151 }
152
153 pub fn token(&self) -> &TokenReference {
155 &self.token
156 }
157
158 pub fn returns(&self) -> &Punctuated<Expression> {
160 &self.returns
161 }
162
163 pub fn with_token(self, token: TokenReference) -> Self {
165 Self { token, ..self }
166 }
167
168 pub fn with_returns(self, returns: Punctuated<Expression>) -> Self {
170 Self { returns, ..self }
171 }
172}
173
174impl Default for Return {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180#[derive(Clone, Debug, Display, PartialEq, Node)]
182#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
183#[non_exhaustive]
184pub enum Field {
185 #[display(
187 "{}{}{}{}{}",
188 brackets.tokens().0,
189 key,
190 brackets.tokens().1,
191 equal,
192 value
193 )]
194 ExpressionKey {
195 brackets: ContainedSpan,
197 key: Expression,
199 equal: TokenReference,
201 value: Expression,
203 },
204
205 #[display("{key}{equal}{value}")]
207 NameKey {
208 key: TokenReference,
210 equal: TokenReference,
212 value: Expression,
214 },
215
216 #[display("{dot}{name}")]
218 #[cfg(feature = "cfxlua")]
219 SetConstructor {
220 dot: TokenReference,
222 name: TokenReference,
224 },
225
226 #[display("{_0}")]
228 NoKey(Expression),
229}
230
231#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
233#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
234#[display("{}{}{}", braces.tokens().0, fields, braces.tokens().1)]
235pub struct TableConstructor {
236 #[node(full_range)]
237 #[visit(contains = "fields")]
238 braces: ContainedSpan,
239 fields: Punctuated<Field>,
240}
241
242impl TableConstructor {
243 pub fn new() -> Self {
246 Self {
247 braces: ContainedSpan::new(
248 TokenReference::basic_symbol("{ "),
249 TokenReference::basic_symbol(" }"),
250 ),
251 fields: Punctuated::new(),
252 }
253 }
254
255 pub fn braces(&self) -> &ContainedSpan {
257 &self.braces
258 }
259
260 pub fn fields(&self) -> &Punctuated<Field> {
262 &self.fields
263 }
264
265 pub fn with_braces(self, braces: ContainedSpan) -> Self {
267 Self { braces, ..self }
268 }
269
270 pub fn with_fields(self, fields: Punctuated<Field>) -> Self {
272 Self { fields, ..self }
273 }
274}
275
276impl Default for TableConstructor {
277 fn default() -> Self {
278 Self::new()
279 }
280}
281
282#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
284#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
285#[cfg_attr(not(feature = "luau"), display("{function_token}{body}"))]
286#[cfg_attr(
287 feature = "luau",
288 display("{}{}{}", join_vec(attributes), function_token, body)
289)]
290pub struct AnonymousFunction {
291 #[cfg(feature = "luau")]
292 attributes: Vec<LuauAttribute>,
293 function_token: TokenReference,
294 body: FunctionBody,
295}
296
297impl AnonymousFunction {
298 pub fn new() -> Self {
300 AnonymousFunction {
301 #[cfg(feature = "luau")]
302 attributes: Vec::new(),
303 function_token: TokenReference::basic_symbol("function"),
304 body: FunctionBody::new(),
305 }
306 }
307
308 #[cfg(feature = "luau")]
310 pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
311 self.attributes.iter()
312 }
313
314 pub fn function_token(&self) -> &TokenReference {
316 &self.function_token
317 }
318
319 pub fn body(&self) -> &FunctionBody {
321 &self.body
322 }
323
324 #[cfg(feature = "luau")]
326 pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
327 Self { attributes, ..self }
328 }
329
330 pub fn with_function_token(self, function_token: TokenReference) -> Self {
332 Self {
333 function_token,
334 ..self
335 }
336 }
337
338 pub fn with_body(self, body: FunctionBody) -> Self {
340 Self { body, ..self }
341 }
342}
343
344impl Default for AnonymousFunction {
345 fn default() -> Self {
346 Self::new()
347 }
348}
349
350#[derive(Clone, Debug, Display, PartialEq, Node)]
352#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
353#[non_exhaustive]
354pub enum Expression {
355 #[display("{lhs}{binop}{rhs}")]
357 BinaryOperator {
358 lhs: Box<Expression>,
360 binop: BinOp,
362 rhs: Box<Expression>,
364 },
365
366 #[display("{}{}{}", contained.tokens().0, expression, contained.tokens().1)]
368 Parentheses {
369 #[node(full_range)]
371 contained: ContainedSpan,
372 expression: Box<Expression>,
374 },
375
376 #[display("{unop}{expression}")]
378 UnaryOperator {
379 unop: UnOp,
381 expression: Box<Expression>,
383 },
384
385 #[display("{_0}")]
387 Function(Box<AnonymousFunction>),
388
389 #[display("{_0}")]
391 FunctionCall(FunctionCall),
392
393 #[cfg(feature = "luau")]
396 #[display("{_0}")]
397 IfExpression(IfExpression),
398
399 #[cfg(feature = "luau")]
402 #[display("{_0}")]
403 InterpolatedString(InterpolatedString),
404
405 #[display("{_0}")]
407 TableConstructor(TableConstructor),
408
409 #[display("{_0}")]
411 Number(TokenReference),
412
413 #[display("{_0}")]
415 String(TokenReference),
416
417 #[display("{_0}")]
419 Symbol(TokenReference),
420
421 #[cfg(feature = "luau")]
424 #[display("{expression}{type_assertion}")]
425 TypeAssertion {
426 expression: Box<Expression>,
428
429 type_assertion: TypeAssertion,
431 },
432
433 #[display("{_0}")]
435 Var(Var),
436}
437
438#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
440#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
441#[non_exhaustive]
442pub enum Stmt {
443 #[display("{_0}")]
445 Assignment(Assignment),
446 #[display("{_0}")]
448 Do(Do),
449 #[display("{_0}")]
451 FunctionCall(FunctionCall),
452 #[display("{_0}")]
454 FunctionDeclaration(FunctionDeclaration),
455 #[display("{_0}")]
457 GenericFor(GenericFor),
458 #[display("{_0}")]
460 If(If),
461 #[display("{_0}")]
463 LocalAssignment(LocalAssignment),
464 #[display("{_0}")]
466 LocalFunction(LocalFunction),
467 #[display("{_0}")]
469 NumericFor(NumericFor),
470 #[display("{_0}")]
472 Repeat(Repeat),
473 #[display("{_0}")]
475 While(While),
476
477 #[cfg(any(feature = "luau", feature = "cfxlua"))]
480 #[display("{_0}")]
481 CompoundAssignment(CompoundAssignment),
482 #[cfg(feature = "luau")]
485 #[display("{_0}")]
486 ConstAssignment(ConstAssignment),
487 #[cfg(feature = "luau")]
490 #[display("{_0}")]
491 ConstFunction(ConstFunction),
492 #[cfg(feature = "luau")]
495 ExportedTypeDeclaration(ExportedTypeDeclaration),
496 #[cfg(feature = "luau")]
499 TypeDeclaration(TypeDeclaration),
500 #[cfg(feature = "luau")]
503 ExportedTypeFunction(ExportedTypeFunction),
504 #[cfg(feature = "luau")]
507 TypeFunction(TypeFunction),
508
509 #[cfg(any(feature = "lua52", feature = "luajit"))]
512 Goto(Goto),
513 #[cfg(any(feature = "lua52", feature = "luajit"))]
516 Label(Label),
517}
518
519#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
522#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
523#[non_exhaustive]
524pub enum Prefix {
525 #[display("{_0}")]
526 Expression(Box<Expression>),
528 #[display("{_0}")]
529 Name(TokenReference),
531}
532
533#[derive(Clone, Debug, Display, PartialEq, Node)]
536#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
537#[non_exhaustive]
538pub enum Index {
539 #[display("{}{}{}", brackets.tokens().0, expression, brackets.tokens().1)]
541 Brackets {
542 brackets: ContainedSpan,
544 expression: Expression,
546 },
547
548 #[display("{dot}{name}")]
550 Dot {
551 dot: TokenReference,
553 name: TokenReference,
555 },
556}
557
558#[derive(Clone, Debug, Display, PartialEq, Node)]
560#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
561#[non_exhaustive]
562pub enum FunctionArgs {
563 #[display(
565 "{}{}{}",
566 parentheses.tokens().0,
567 arguments,
568 parentheses.tokens().1
569 )]
570 Parentheses {
571 #[node(full_range)]
573 parentheses: ContainedSpan,
574 arguments: Punctuated<Expression>,
576 },
577 #[display("{_0}")]
579 String(TokenReference),
580 #[display("{_0}")]
582 TableConstructor(TableConstructor),
583}
584
585impl FunctionArgs {
586 pub(crate) fn empty() -> Self {
587 FunctionArgs::Parentheses {
588 parentheses: ContainedSpan::new(
589 TokenReference::basic_symbol("("),
590 TokenReference::basic_symbol(")"),
591 ),
592
593 arguments: Punctuated::new(),
594 }
595 }
596}
597
598#[derive(Clone, Debug, PartialEq, Node)]
600#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
601pub struct NumericFor {
602 for_token: TokenReference,
603 index_variable: TokenReference,
604 equal_token: TokenReference,
605 start: Expression,
606 start_end_comma: TokenReference,
607 end: Expression,
608 end_step_comma: Option<TokenReference>,
609 step: Option<Expression>,
610 do_token: TokenReference,
611 block: Block,
612 end_token: TokenReference,
613 #[cfg(feature = "luau")]
614 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
615 type_specifier: Option<TypeSpecifier>,
616}
617
618impl NumericFor {
619 pub fn new(index_variable: TokenReference, start: Expression, end: Expression) -> Self {
621 Self {
622 for_token: TokenReference::basic_symbol("for "),
623 index_variable,
624 equal_token: TokenReference::basic_symbol(" = "),
625 start,
626 start_end_comma: TokenReference::basic_symbol(", "),
627 end,
628 end_step_comma: None,
629 step: None,
630 do_token: TokenReference::basic_symbol(" do\n"),
631 block: Block::new(),
632 end_token: TokenReference::basic_symbol("\nend"),
633 #[cfg(feature = "luau")]
634 type_specifier: None,
635 }
636 }
637
638 pub fn for_token(&self) -> &TokenReference {
640 &self.for_token
641 }
642
643 pub fn index_variable(&self) -> &TokenReference {
645 &self.index_variable
646 }
647
648 pub fn equal_token(&self) -> &TokenReference {
650 &self.equal_token
651 }
652
653 pub fn start(&self) -> &Expression {
655 &self.start
656 }
657
658 pub fn start_end_comma(&self) -> &TokenReference {
662 &self.start_end_comma
663 }
664
665 pub fn end(&self) -> &Expression {
667 &self.end
668 }
669
670 pub fn end_step_comma(&self) -> Option<&TokenReference> {
674 self.end_step_comma.as_ref()
675 }
676
677 pub fn step(&self) -> Option<&Expression> {
679 self.step.as_ref()
680 }
681
682 pub fn do_token(&self) -> &TokenReference {
684 &self.do_token
685 }
686
687 pub fn block(&self) -> &Block {
689 &self.block
690 }
691
692 pub fn end_token(&self) -> &TokenReference {
694 &self.end_token
695 }
696
697 #[cfg(feature = "luau")]
702 pub fn type_specifier(&self) -> Option<&TypeSpecifier> {
703 self.type_specifier.as_ref()
704 }
705
706 pub fn with_for_token(self, for_token: TokenReference) -> Self {
708 Self { for_token, ..self }
709 }
710
711 pub fn with_index_variable(self, index_variable: TokenReference) -> Self {
713 Self {
714 index_variable,
715 ..self
716 }
717 }
718
719 pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
721 Self {
722 equal_token,
723 ..self
724 }
725 }
726
727 pub fn with_start(self, start: Expression) -> Self {
729 Self { start, ..self }
730 }
731
732 pub fn with_start_end_comma(self, start_end_comma: TokenReference) -> Self {
734 Self {
735 start_end_comma,
736 ..self
737 }
738 }
739
740 pub fn with_end(self, end: Expression) -> Self {
742 Self { end, ..self }
743 }
744
745 pub fn with_end_step_comma(self, end_step_comma: Option<TokenReference>) -> Self {
747 Self {
748 end_step_comma,
749 ..self
750 }
751 }
752
753 pub fn with_step(self, step: Option<Expression>) -> Self {
755 Self { step, ..self }
756 }
757
758 pub fn with_do_token(self, do_token: TokenReference) -> Self {
760 Self { do_token, ..self }
761 }
762
763 pub fn with_block(self, block: Block) -> Self {
765 Self { block, ..self }
766 }
767
768 pub fn with_end_token(self, end_token: TokenReference) -> Self {
770 Self { end_token, ..self }
771 }
772
773 #[cfg(feature = "luau")]
776 pub fn with_type_specifier(self, type_specifier: Option<TypeSpecifier>) -> Self {
777 Self {
778 type_specifier,
779 ..self
780 }
781 }
782}
783
784impl fmt::Display for NumericFor {
785 #[cfg(feature = "luau")]
786 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
787 write!(
788 formatter,
789 "{}{}{}{}{}{}{}{}{}{}{}{}",
790 self.for_token,
791 self.index_variable,
792 display_option(self.type_specifier()),
793 self.equal_token,
794 self.start,
795 self.start_end_comma,
796 self.end,
797 display_option(self.end_step_comma()),
798 display_option(self.step()),
799 self.do_token,
800 self.block,
801 self.end_token,
802 )
803 }
804
805 #[cfg(not(feature = "luau"))]
806 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
807 write!(
808 formatter,
809 "{}{}{}{}{}{}{}{}{}{}{}",
810 self.for_token,
811 self.index_variable,
812 self.equal_token,
813 self.start,
814 self.start_end_comma,
815 self.end,
816 display_option(self.end_step_comma()),
817 display_option(self.step()),
818 self.do_token,
819 self.block,
820 self.end_token,
821 )
822 }
823}
824
825#[derive(Clone, Debug, PartialEq, Node)]
827#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
828pub struct GenericFor {
829 for_token: TokenReference,
830 names: Punctuated<TokenReference>,
831 in_token: TokenReference,
832 expr_list: Punctuated<Expression>,
833 do_token: TokenReference,
834 block: Block,
835 end_token: TokenReference,
836 #[cfg(feature = "luau")]
837 #[cfg_attr(
838 feature = "serde",
839 serde(skip_serializing_if = "vec_empty_or_all_none")
840 )]
841 type_specifiers: Vec<Option<TypeSpecifier>>,
842}
843
844impl GenericFor {
845 pub fn new(names: Punctuated<TokenReference>, expr_list: Punctuated<Expression>) -> Self {
847 Self {
848 for_token: TokenReference::basic_symbol("for "),
849 names,
850 in_token: TokenReference::basic_symbol(" in "),
851 expr_list,
852 do_token: TokenReference::basic_symbol(" do\n"),
853 block: Block::new(),
854 end_token: TokenReference::basic_symbol("\nend"),
855 #[cfg(feature = "luau")]
856 type_specifiers: Vec::new(),
857 }
858 }
859
860 pub fn for_token(&self) -> &TokenReference {
862 &self.for_token
863 }
864
865 pub fn names(&self) -> &Punctuated<TokenReference> {
868 &self.names
869 }
870
871 pub fn in_token(&self) -> &TokenReference {
873 &self.in_token
874 }
875
876 pub fn expressions(&self) -> &Punctuated<Expression> {
879 &self.expr_list
880 }
881
882 pub fn do_token(&self) -> &TokenReference {
884 &self.do_token
885 }
886
887 pub fn block(&self) -> &Block {
889 &self.block
890 }
891
892 pub fn end_token(&self) -> &TokenReference {
894 &self.end_token
895 }
896
897 #[cfg(feature = "luau")]
902 pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
903 self.type_specifiers.iter().map(Option::as_ref)
904 }
905
906 pub fn with_for_token(self, for_token: TokenReference) -> Self {
908 Self { for_token, ..self }
909 }
910
911 pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
913 Self { names, ..self }
914 }
915
916 pub fn with_in_token(self, in_token: TokenReference) -> Self {
918 Self { in_token, ..self }
919 }
920
921 pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
923 Self { expr_list, ..self }
924 }
925
926 pub fn with_do_token(self, do_token: TokenReference) -> Self {
928 Self { do_token, ..self }
929 }
930
931 pub fn with_block(self, block: Block) -> Self {
933 Self { block, ..self }
934 }
935
936 pub fn with_end_token(self, end_token: TokenReference) -> Self {
938 Self { end_token, ..self }
939 }
940
941 #[cfg(feature = "luau")]
944 pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
945 Self {
946 type_specifiers,
947 ..self
948 }
949 }
950}
951
952impl fmt::Display for GenericFor {
953 #[cfg(feature = "luau")]
954 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
955 write!(
956 formatter,
957 "{}{}{}{}{}{}{}",
958 self.for_token,
959 join_type_specifiers(&self.names, self.type_specifiers()),
960 self.in_token,
961 self.expr_list,
962 self.do_token,
963 self.block,
964 self.end_token
965 )
966 }
967
968 #[cfg(not(feature = "luau"))]
969 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
970 write!(
971 formatter,
972 "{}{}{}{}{}{}{}",
973 self.for_token,
974 self.names,
975 self.in_token,
976 self.expr_list,
977 self.do_token,
978 self.block,
979 self.end_token
980 )
981 }
982}
983
984#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
986#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
987#[display(
988 "{}{}{}{}{}{}{}{}",
989 if_token,
990 condition,
991 then_token,
992 block,
993 display_option(else_if.as_ref().map(join_vec)),
994 display_option(else_token),
995 display_option(r#else),
996 end_token
997)]
998pub struct If {
999 if_token: TokenReference,
1000 condition: Expression,
1001 then_token: TokenReference,
1002 block: Block,
1003 else_if: Option<Vec<ElseIf>>,
1004 else_token: Option<TokenReference>,
1005 #[cfg_attr(feature = "serde", serde(rename = "else"))]
1006 r#else: Option<Block>,
1007 end_token: TokenReference,
1008}
1009
1010impl If {
1011 pub fn new(condition: Expression) -> Self {
1013 Self {
1014 if_token: TokenReference::basic_symbol("if "),
1015 condition,
1016 then_token: TokenReference::basic_symbol(" then"),
1017 block: Block::new(),
1018 else_if: None,
1019 else_token: None,
1020 r#else: None,
1021 end_token: TokenReference::basic_symbol("\nend"),
1022 }
1023 }
1024
1025 pub fn if_token(&self) -> &TokenReference {
1027 &self.if_token
1028 }
1029
1030 pub fn condition(&self) -> &Expression {
1032 &self.condition
1033 }
1034
1035 pub fn then_token(&self) -> &TokenReference {
1037 &self.then_token
1038 }
1039
1040 pub fn block(&self) -> &Block {
1042 &self.block
1043 }
1044
1045 pub fn else_token(&self) -> Option<&TokenReference> {
1047 self.else_token.as_ref()
1048 }
1049
1050 pub fn else_if(&self) -> Option<&Vec<ElseIf>> {
1054 self.else_if.as_ref()
1055 }
1056
1057 pub fn else_block(&self) -> Option<&Block> {
1059 self.r#else.as_ref()
1060 }
1061
1062 pub fn end_token(&self) -> &TokenReference {
1064 &self.end_token
1065 }
1066
1067 pub fn with_if_token(self, if_token: TokenReference) -> Self {
1069 Self { if_token, ..self }
1070 }
1071
1072 pub fn with_condition(self, condition: Expression) -> Self {
1074 Self { condition, ..self }
1075 }
1076
1077 pub fn with_then_token(self, then_token: TokenReference) -> Self {
1079 Self { then_token, ..self }
1080 }
1081
1082 pub fn with_block(self, block: Block) -> Self {
1084 Self { block, ..self }
1085 }
1086
1087 pub fn with_else_if(self, else_if: Option<Vec<ElseIf>>) -> Self {
1089 Self { else_if, ..self }
1090 }
1091
1092 pub fn with_else_token(self, else_token: Option<TokenReference>) -> Self {
1094 Self { else_token, ..self }
1095 }
1096
1097 pub fn with_else(self, r#else: Option<Block>) -> Self {
1099 Self { r#else, ..self }
1100 }
1101
1102 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1104 Self { end_token, ..self }
1105 }
1106}
1107
1108#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1110#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1111#[display("{else_if_token}{condition}{then_token}{block}")]
1112pub struct ElseIf {
1113 else_if_token: TokenReference,
1114 condition: Expression,
1115 then_token: TokenReference,
1116 block: Block,
1117}
1118
1119impl ElseIf {
1120 pub fn new(condition: Expression) -> Self {
1122 Self {
1123 else_if_token: TokenReference::basic_symbol("elseif "),
1124 condition,
1125 then_token: TokenReference::basic_symbol(" then\n"),
1126 block: Block::new(),
1127 }
1128 }
1129
1130 pub fn else_if_token(&self) -> &TokenReference {
1132 &self.else_if_token
1133 }
1134
1135 pub fn condition(&self) -> &Expression {
1137 &self.condition
1138 }
1139
1140 pub fn then_token(&self) -> &TokenReference {
1142 &self.then_token
1143 }
1144
1145 pub fn block(&self) -> &Block {
1147 &self.block
1148 }
1149
1150 pub fn with_else_if_token(self, else_if_token: TokenReference) -> Self {
1152 Self {
1153 else_if_token,
1154 ..self
1155 }
1156 }
1157
1158 pub fn with_condition(self, condition: Expression) -> Self {
1160 Self { condition, ..self }
1161 }
1162
1163 pub fn with_then_token(self, then_token: TokenReference) -> Self {
1165 Self { then_token, ..self }
1166 }
1167
1168 pub fn with_block(self, block: Block) -> Self {
1170 Self { block, ..self }
1171 }
1172}
1173
1174#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1176#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1177#[display("{while_token}{condition}{do_token}{block}{end_token}")]
1178pub struct While {
1179 while_token: TokenReference,
1180 condition: Expression,
1181 do_token: TokenReference,
1182 block: Block,
1183 end_token: TokenReference,
1184}
1185
1186impl While {
1187 pub fn new(condition: Expression) -> Self {
1189 Self {
1190 while_token: TokenReference::basic_symbol("while "),
1191 condition,
1192 do_token: TokenReference::basic_symbol(" do\n"),
1193 block: Block::new(),
1194 end_token: TokenReference::basic_symbol("end\n"),
1195 }
1196 }
1197
1198 pub fn while_token(&self) -> &TokenReference {
1200 &self.while_token
1201 }
1202
1203 pub fn condition(&self) -> &Expression {
1205 &self.condition
1206 }
1207
1208 pub fn do_token(&self) -> &TokenReference {
1210 &self.do_token
1211 }
1212
1213 pub fn block(&self) -> &Block {
1215 &self.block
1216 }
1217
1218 pub fn end_token(&self) -> &TokenReference {
1220 &self.end_token
1221 }
1222
1223 pub fn with_while_token(self, while_token: TokenReference) -> Self {
1225 Self {
1226 while_token,
1227 ..self
1228 }
1229 }
1230
1231 pub fn with_condition(self, condition: Expression) -> Self {
1233 Self { condition, ..self }
1234 }
1235
1236 pub fn with_do_token(self, do_token: TokenReference) -> Self {
1238 Self { do_token, ..self }
1239 }
1240
1241 pub fn with_block(self, block: Block) -> Self {
1243 Self { block, ..self }
1244 }
1245
1246 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1248 Self { end_token, ..self }
1249 }
1250}
1251
1252#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1254#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1255#[display("{repeat_token}{block}{until_token}{until}")]
1256pub struct Repeat {
1257 repeat_token: TokenReference,
1258 block: Block,
1259 until_token: TokenReference,
1260 until: Expression,
1261}
1262
1263impl Repeat {
1264 pub fn new(until: Expression) -> Self {
1266 Self {
1267 repeat_token: TokenReference::basic_symbol("repeat\n"),
1268 block: Block::new(),
1269 until_token: TokenReference::basic_symbol("\nuntil "),
1270 until,
1271 }
1272 }
1273
1274 pub fn repeat_token(&self) -> &TokenReference {
1276 &self.repeat_token
1277 }
1278
1279 pub fn block(&self) -> &Block {
1281 &self.block
1282 }
1283
1284 pub fn until_token(&self) -> &TokenReference {
1286 &self.until_token
1287 }
1288
1289 pub fn until(&self) -> &Expression {
1291 &self.until
1292 }
1293
1294 pub fn with_repeat_token(self, repeat_token: TokenReference) -> Self {
1296 Self {
1297 repeat_token,
1298 ..self
1299 }
1300 }
1301
1302 pub fn with_block(self, block: Block) -> Self {
1304 Self { block, ..self }
1305 }
1306
1307 pub fn with_until_token(self, until_token: TokenReference) -> Self {
1309 Self {
1310 until_token,
1311 ..self
1312 }
1313 }
1314
1315 pub fn with_until(self, until: Expression) -> Self {
1317 Self { until, ..self }
1318 }
1319}
1320
1321#[derive(Clone, Debug, PartialEq, Node, Visit)]
1323#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1324pub struct MethodCall {
1325 colon_token: TokenReference,
1326 name: TokenReference,
1327
1328 #[cfg(feature = "luau")]
1329 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1330 type_instantiation: Option<TypeInstantiation>,
1331
1332 args: FunctionArgs,
1333}
1334
1335impl MethodCall {
1336 pub fn new(name: TokenReference, args: FunctionArgs) -> Self {
1338 Self {
1339 colon_token: TokenReference::basic_symbol(":"),
1340 name,
1341 args,
1342 #[cfg(feature = "luau")]
1343 type_instantiation: None,
1344 }
1345 }
1346
1347 pub fn colon_token(&self) -> &TokenReference {
1349 &self.colon_token
1350 }
1351
1352 pub fn args(&self) -> &FunctionArgs {
1354 &self.args
1355 }
1356
1357 pub fn name(&self) -> &TokenReference {
1359 &self.name
1360 }
1361
1362 #[cfg(feature = "luau")]
1366 pub fn type_instantiation(&self) -> Option<&TypeInstantiation> {
1367 self.type_instantiation.as_ref()
1368 }
1369
1370 pub fn with_colon_token(self, colon_token: TokenReference) -> Self {
1372 Self {
1373 colon_token,
1374 ..self
1375 }
1376 }
1377
1378 pub fn with_name(self, name: TokenReference) -> Self {
1380 Self { name, ..self }
1381 }
1382
1383 pub fn with_args(self, args: FunctionArgs) -> Self {
1385 Self { args, ..self }
1386 }
1387
1388 #[cfg(feature = "luau")]
1390 pub fn with_type_instanation(self, type_instantiation: Option<TypeInstantiation>) -> Self {
1391 Self {
1392 type_instantiation,
1393 ..self
1394 }
1395 }
1396}
1397
1398impl fmt::Display for MethodCall {
1399 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
1400 write!(formatter, "{}{}", self.colon_token, self.name)?;
1401
1402 #[cfg(feature = "luau")]
1403 if let Some(type_instantiation) = self.type_instantiation.as_ref() {
1404 write!(formatter, "{type_instantiation}")?;
1405 }
1406
1407 write!(formatter, "{}", self.args)?;
1408
1409 Ok(())
1410 }
1411}
1412
1413#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1415#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1416#[non_exhaustive]
1417pub enum Call {
1418 #[display("{_0}")]
1419 AnonymousCall(FunctionArgs),
1421 #[display("{_0}")]
1422 MethodCall(MethodCall),
1424}
1425
1426#[derive(Clone, Debug, PartialEq, Node)]
1428#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1429pub struct FunctionBody {
1430 #[cfg(feature = "luau")]
1431 generics: Option<GenericDeclaration>,
1432
1433 parameters_parentheses: ContainedSpan,
1434 parameters: Punctuated<Parameter>,
1435
1436 #[cfg(feature = "luau")]
1437 type_specifiers: Vec<Option<TypeSpecifier>>,
1438
1439 #[cfg(feature = "luau")]
1440 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1441 return_type: Option<TypeSpecifier>,
1442
1443 block: Block,
1444 end_token: TokenReference,
1445}
1446
1447impl FunctionBody {
1448 pub fn new() -> Self {
1450 Self {
1451 #[cfg(feature = "luau")]
1452 generics: None,
1453
1454 parameters_parentheses: ContainedSpan::new(
1455 TokenReference::basic_symbol("("),
1456 TokenReference::basic_symbol(")"),
1457 ),
1458 parameters: Punctuated::new(),
1459
1460 #[cfg(feature = "luau")]
1461 type_specifiers: Vec::new(),
1462
1463 #[cfg(feature = "luau")]
1464 return_type: None,
1465
1466 block: Block::new(),
1467 end_token: TokenReference::basic_symbol("\nend"),
1468 }
1469 }
1470
1471 pub fn parameters_parentheses(&self) -> &ContainedSpan {
1473 &self.parameters_parentheses
1474 }
1475
1476 pub fn parameters(&self) -> &Punctuated<Parameter> {
1478 &self.parameters
1479 }
1480
1481 pub fn block(&self) -> &Block {
1483 &self.block
1484 }
1485
1486 pub fn end_token(&self) -> &TokenReference {
1488 &self.end_token
1489 }
1490
1491 #[cfg(feature = "luau")]
1495 pub fn generics(&self) -> Option<&GenericDeclaration> {
1496 self.generics.as_ref()
1497 }
1498
1499 #[cfg(feature = "luau")]
1504 pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1505 self.type_specifiers.iter().map(Option::as_ref)
1506 }
1507
1508 #[cfg(feature = "luau")]
1511 pub fn return_type(&self) -> Option<&TypeSpecifier> {
1512 self.return_type.as_ref()
1513 }
1514
1515 pub fn with_parameters_parentheses(self, parameters_parentheses: ContainedSpan) -> Self {
1517 Self {
1518 parameters_parentheses,
1519 ..self
1520 }
1521 }
1522
1523 pub fn with_parameters(self, parameters: Punctuated<Parameter>) -> Self {
1525 Self { parameters, ..self }
1526 }
1527
1528 #[cfg(feature = "luau")]
1530 pub fn with_generics(self, generics: Option<GenericDeclaration>) -> Self {
1531 Self { generics, ..self }
1532 }
1533
1534 #[cfg(feature = "luau")]
1536 pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1537 Self {
1538 type_specifiers,
1539 ..self
1540 }
1541 }
1542
1543 #[cfg(feature = "luau")]
1545 pub fn with_return_type(self, return_type: Option<TypeSpecifier>) -> Self {
1546 Self {
1547 return_type,
1548 ..self
1549 }
1550 }
1551
1552 pub fn with_block(self, block: Block) -> Self {
1554 Self { block, ..self }
1555 }
1556
1557 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1559 Self { end_token, ..self }
1560 }
1561}
1562
1563impl Default for FunctionBody {
1564 fn default() -> Self {
1565 Self::new()
1566 }
1567}
1568
1569impl fmt::Display for FunctionBody {
1570 #[cfg(feature = "luau")]
1571 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1572 write!(
1573 formatter,
1574 "{}{}{}{}{}{}{}",
1575 display_option(self.generics.as_ref()),
1576 self.parameters_parentheses.tokens().0,
1577 join_type_specifiers(&self.parameters, self.type_specifiers()),
1578 self.parameters_parentheses.tokens().1,
1579 display_option(self.return_type.as_ref()),
1580 self.block,
1581 self.end_token
1582 )
1583 }
1584
1585 #[cfg(not(feature = "luau"))]
1586 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1587 write!(
1588 formatter,
1589 "{}{}{}{}{}",
1590 self.parameters_parentheses.tokens().0,
1591 self.parameters,
1592 self.parameters_parentheses.tokens().1,
1593 self.block,
1594 self.end_token
1595 )
1596 }
1597}
1598
1599#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
1601#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1602#[non_exhaustive]
1603pub enum Parameter {
1604 Ellipsis(TokenReference),
1606 Name(TokenReference),
1608}
1609
1610#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1613#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1614#[non_exhaustive]
1615pub enum Suffix {
1616 #[display("{_0}")]
1617 Call(Call),
1619
1620 #[display("{_0}")]
1621 Index(Index),
1623
1624 #[display("{_0}")]
1625 #[cfg(feature = "luau")]
1626 TypeInstantiation(TypeInstantiation),
1628}
1629
1630#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1632#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1633#[display("{}{}", prefix, join_vec(suffixes))]
1634pub struct VarExpression {
1635 prefix: Prefix,
1636 suffixes: Vec<Suffix>,
1637}
1638
1639impl VarExpression {
1640 pub fn new(prefix: Prefix) -> Self {
1642 Self {
1643 prefix,
1644 suffixes: Vec::new(),
1645 }
1646 }
1647
1648 pub fn prefix(&self) -> &Prefix {
1650 &self.prefix
1651 }
1652
1653 pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
1655 self.suffixes.iter()
1656 }
1657
1658 pub fn with_prefix(self, prefix: Prefix) -> Self {
1660 Self { prefix, ..self }
1661 }
1662
1663 pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
1665 Self { suffixes, ..self }
1666 }
1667}
1668
1669#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1671#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1672#[non_exhaustive]
1673pub enum Var {
1674 #[display("{_0}")]
1676 Expression(Box<VarExpression>),
1677 #[display("{_0}")]
1679 Name(TokenReference),
1680}
1681
1682#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1684#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1685#[display("{var_list}{equal_token}{expr_list}")]
1686pub struct Assignment {
1687 var_list: Punctuated<Var>,
1688 equal_token: TokenReference,
1689 expr_list: Punctuated<Expression>,
1690}
1691
1692impl Assignment {
1693 pub fn new(var_list: Punctuated<Var>, expr_list: Punctuated<Expression>) -> Self {
1695 Self {
1696 var_list,
1697 equal_token: TokenReference::basic_symbol(" = "),
1698 expr_list,
1699 }
1700 }
1701
1702 pub fn expressions(&self) -> &Punctuated<Expression> {
1705 &self.expr_list
1706 }
1707
1708 pub fn equal_token(&self) -> &TokenReference {
1710 &self.equal_token
1711 }
1712
1713 pub fn variables(&self) -> &Punctuated<Var> {
1716 &self.var_list
1717 }
1718
1719 pub fn with_variables(self, var_list: Punctuated<Var>) -> Self {
1721 Self { var_list, ..self }
1722 }
1723
1724 pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
1726 Self {
1727 equal_token,
1728 ..self
1729 }
1730 }
1731
1732 pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1734 Self { expr_list, ..self }
1735 }
1736}
1737
1738#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1740#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1741#[cfg_attr(
1742 not(feature = "luau"),
1743 display("{local_token}{function_token}{name}{body}")
1744)]
1745#[cfg_attr(
1746 feature = "luau",
1747 display(
1748 "{}{}{}{}{}",
1749 join_vec(attributes),
1750 local_token,
1751 function_token,
1752 name,
1753 body
1754 )
1755)]
1756pub struct LocalFunction {
1757 #[cfg(feature = "luau")]
1758 attributes: Vec<LuauAttribute>,
1759 local_token: TokenReference,
1760 function_token: TokenReference,
1761 name: TokenReference,
1762 body: FunctionBody,
1763}
1764
1765impl LocalFunction {
1766 pub fn new(name: TokenReference) -> Self {
1768 LocalFunction {
1769 #[cfg(feature = "luau")]
1770 attributes: Vec::new(),
1771 local_token: TokenReference::basic_symbol("local "),
1772 function_token: TokenReference::basic_symbol("function "),
1773 name,
1774 body: FunctionBody::new(),
1775 }
1776 }
1777
1778 #[cfg(feature = "luau")]
1780 pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
1781 self.attributes.iter()
1782 }
1783
1784 pub fn local_token(&self) -> &TokenReference {
1786 &self.local_token
1787 }
1788
1789 pub fn function_token(&self) -> &TokenReference {
1791 &self.function_token
1792 }
1793
1794 pub fn body(&self) -> &FunctionBody {
1796 &self.body
1797 }
1798
1799 pub fn name(&self) -> &TokenReference {
1801 &self.name
1802 }
1803
1804 #[cfg(feature = "luau")]
1806 pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
1807 Self { attributes, ..self }
1808 }
1809
1810 pub fn with_local_token(self, local_token: TokenReference) -> Self {
1812 Self {
1813 local_token,
1814 ..self
1815 }
1816 }
1817
1818 pub fn with_function_token(self, function_token: TokenReference) -> Self {
1820 Self {
1821 function_token,
1822 ..self
1823 }
1824 }
1825
1826 pub fn with_name(self, name: TokenReference) -> Self {
1828 Self { name, ..self }
1829 }
1830
1831 pub fn with_body(self, body: FunctionBody) -> Self {
1833 Self { body, ..self }
1834 }
1835}
1836
1837#[derive(Clone, Debug, PartialEq, Node)]
1839#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1840pub struct LocalAssignment {
1841 local_token: TokenReference,
1842 #[cfg(feature = "luau")]
1843 #[cfg_attr(
1844 feature = "serde",
1845 serde(skip_serializing_if = "empty_optional_vector")
1846 )]
1847 type_specifiers: Vec<Option<TypeSpecifier>>,
1848 name_list: Punctuated<TokenReference>,
1849 #[cfg(feature = "lua54")]
1850 #[cfg_attr(
1851 feature = "serde",
1852 serde(skip_serializing_if = "empty_optional_vector")
1853 )]
1854 attributes: Vec<Option<Attribute>>,
1855 equal_token: Option<TokenReference>,
1856 expr_list: Punctuated<Expression>,
1857}
1858
1859impl LocalAssignment {
1860 pub fn new(name_list: Punctuated<TokenReference>) -> Self {
1862 Self {
1863 local_token: TokenReference::basic_symbol("local "),
1864 #[cfg(feature = "luau")]
1865 type_specifiers: Vec::new(),
1866 name_list,
1867 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1868 attributes: Vec::new(),
1869 equal_token: None,
1870 expr_list: Punctuated::new(),
1871 }
1872 }
1873
1874 pub fn local_token(&self) -> &TokenReference {
1876 &self.local_token
1877 }
1878
1879 pub fn equal_token(&self) -> Option<&TokenReference> {
1881 self.equal_token.as_ref()
1882 }
1883
1884 pub fn expressions(&self) -> &Punctuated<Expression> {
1887 &self.expr_list
1888 }
1889
1890 pub fn names(&self) -> &Punctuated<TokenReference> {
1893 &self.name_list
1894 }
1895
1896 #[cfg(feature = "luau")]
1901 pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1902 self.type_specifiers.iter().map(Option::as_ref)
1903 }
1904
1905 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1910 pub fn attributes(&self) -> impl Iterator<Item = Option<&Attribute>> {
1911 self.attributes.iter().map(Option::as_ref)
1912 }
1913
1914 pub fn with_local_token(self, local_token: TokenReference) -> Self {
1916 Self {
1917 local_token,
1918 ..self
1919 }
1920 }
1921
1922 #[cfg(feature = "luau")]
1924 pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1925 Self {
1926 type_specifiers,
1927 ..self
1928 }
1929 }
1930
1931 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1933 pub fn with_attributes(self, attributes: Vec<Option<Attribute>>) -> Self {
1934 Self { attributes, ..self }
1935 }
1936
1937 pub fn with_names(self, name_list: Punctuated<TokenReference>) -> Self {
1939 Self { name_list, ..self }
1940 }
1941
1942 pub fn with_equal_token(self, equal_token: Option<TokenReference>) -> Self {
1944 Self {
1945 equal_token,
1946 ..self
1947 }
1948 }
1949
1950 pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1952 Self { expr_list, ..self }
1953 }
1954}
1955
1956impl fmt::Display for LocalAssignment {
1957 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1958 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1959 let attributes = self.attributes().chain(std::iter::repeat(None));
1960 #[cfg(not(feature = "lua54"))]
1961 let attributes = std::iter::repeat_with(|| None::<TokenReference>);
1962 #[cfg(feature = "luau")]
1963 let type_specifiers = self.type_specifiers().chain(std::iter::repeat(None));
1964 #[cfg(not(feature = "luau"))]
1965 let type_specifiers = std::iter::repeat_with(|| None::<TokenReference>);
1966
1967 write!(
1968 formatter,
1969 "{}{}{}{}",
1970 self.local_token,
1971 join_iterators(&self.name_list, attributes, type_specifiers),
1972 display_option(&self.equal_token),
1973 self.expr_list
1974 )
1975 }
1976}
1977
1978#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1981#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1982#[display("{do_token}{block}{end_token}")]
1983pub struct Do {
1984 do_token: TokenReference,
1985 block: Block,
1986 end_token: TokenReference,
1987}
1988
1989impl Do {
1990 pub fn new() -> Self {
1992 Self {
1993 do_token: TokenReference::basic_symbol("do\n"),
1994 block: Block::new(),
1995 end_token: TokenReference::basic_symbol("\nend"),
1996 }
1997 }
1998
1999 pub fn do_token(&self) -> &TokenReference {
2001 &self.do_token
2002 }
2003
2004 pub fn block(&self) -> &Block {
2006 &self.block
2007 }
2008
2009 pub fn end_token(&self) -> &TokenReference {
2011 &self.end_token
2012 }
2013
2014 pub fn with_do_token(self, do_token: TokenReference) -> Self {
2016 Self { do_token, ..self }
2017 }
2018
2019 pub fn with_block(self, block: Block) -> Self {
2021 Self { block, ..self }
2022 }
2023
2024 pub fn with_end_token(self, end_token: TokenReference) -> Self {
2026 Self { end_token, ..self }
2027 }
2028}
2029
2030impl Default for Do {
2031 fn default() -> Self {
2032 Self::new()
2033 }
2034}
2035
2036#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
2038#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2039#[display("{}{}", prefix, join_vec(suffixes))]
2040pub struct FunctionCall {
2041 prefix: Prefix,
2042 suffixes: Vec<Suffix>,
2043}
2044
2045impl FunctionCall {
2046 pub fn new(prefix: Prefix) -> Self {
2049 FunctionCall {
2050 prefix,
2051 suffixes: vec![Suffix::Call(Call::AnonymousCall(
2052 FunctionArgs::Parentheses {
2053 arguments: Punctuated::new(),
2054 parentheses: ContainedSpan::new(
2055 TokenReference::basic_symbol("("),
2056 TokenReference::basic_symbol(")"),
2057 ),
2058 },
2059 ))],
2060 }
2061 }
2062
2063 pub fn prefix(&self) -> &Prefix {
2065 &self.prefix
2066 }
2067
2068 pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
2070 self.suffixes.iter()
2071 }
2072
2073 pub fn with_prefix(self, prefix: Prefix) -> Self {
2075 Self { prefix, ..self }
2076 }
2077
2078 pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
2080 Self { suffixes, ..self }
2081 }
2082}
2083
2084#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2086#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2087#[display(
2088 "{}{}{}",
2089 names,
2090 display_option(self.method_colon()),
2091 display_option(self.method_name())
2092)]
2093pub struct FunctionName {
2094 names: Punctuated<TokenReference>,
2095 colon_name: Option<(TokenReference, TokenReference)>,
2096}
2097
2098impl FunctionName {
2099 pub fn new(names: Punctuated<TokenReference>) -> Self {
2101 Self {
2102 names,
2103 colon_name: None,
2104 }
2105 }
2106
2107 pub fn method_colon(&self) -> Option<&TokenReference> {
2109 Some(&self.colon_name.as_ref()?.0)
2110 }
2111
2112 pub fn method_name(&self) -> Option<&TokenReference> {
2114 Some(&self.colon_name.as_ref()?.1)
2115 }
2116
2117 pub fn names(&self) -> &Punctuated<TokenReference> {
2120 &self.names
2121 }
2122
2123 pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
2125 Self { names, ..self }
2126 }
2127
2128 pub fn with_method(self, method: Option<(TokenReference, TokenReference)>) -> Self {
2131 Self {
2132 colon_name: method,
2133 ..self
2134 }
2135 }
2136}
2137
2138#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
2141#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2142#[cfg_attr(not(feature = "luau"), display("{function_token}{name}{body}"))]
2143#[cfg_attr(
2144 feature = "luau",
2145 display("{}{}{}{}", join_vec(attributes), function_token, name, body)
2146)]
2147pub struct FunctionDeclaration {
2148 #[cfg(feature = "luau")]
2149 attributes: Vec<LuauAttribute>,
2150 function_token: TokenReference,
2151 name: FunctionName,
2152 body: FunctionBody,
2153}
2154
2155impl FunctionDeclaration {
2156 pub fn new(name: FunctionName) -> Self {
2158 Self {
2159 #[cfg(feature = "luau")]
2160 attributes: Vec::new(),
2161 function_token: TokenReference::basic_symbol("function "),
2162 name,
2163 body: FunctionBody::new(),
2164 }
2165 }
2166
2167 #[cfg(feature = "luau")]
2169 pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
2170 self.attributes.iter()
2171 }
2172
2173 pub fn function_token(&self) -> &TokenReference {
2175 &self.function_token
2176 }
2177
2178 pub fn body(&self) -> &FunctionBody {
2180 &self.body
2181 }
2182
2183 pub fn name(&self) -> &FunctionName {
2185 &self.name
2186 }
2187
2188 #[cfg(feature = "luau")]
2190 pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
2191 Self { attributes, ..self }
2192 }
2193
2194 pub fn with_function_token(self, function_token: TokenReference) -> Self {
2196 Self {
2197 function_token,
2198 ..self
2199 }
2200 }
2201
2202 pub fn with_name(self, name: FunctionName) -> Self {
2204 Self { name, ..self }
2205 }
2206
2207 pub fn with_body(self, body: FunctionBody) -> Self {
2209 Self { body, ..self }
2210 }
2211}
2212
2213#[doc(hidden)]
2214#[macro_export]
2215macro_rules! make_bin_op {
2216 ($(#[$outer:meta])* { $(
2217 $([$($version:ident)|+])? $operator:ident = $precedence:expr,
2218 )+ }) => {
2219 paste::paste! {
2220 #[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2221 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2222 #[non_exhaustive]
2223 $(#[$outer])*
2224 #[display("{_0}")]
2225 pub enum BinOp {
2226 $(
2227 #[allow(missing_docs)]
2228 $(
2229 #[cfg(any(
2230 $(feature = "" $version),+
2231 ))]
2232 )*
2233 $operator(TokenReference),
2234 )+
2235 }
2236
2237 impl BinOp {
2238 pub fn precedence_of_token(token: &TokenReference) -> Option<u8> {
2241 match token.token_type() {
2242 TokenType::Symbol { symbol } => match symbol {
2243 $(
2244 $(
2245 #[cfg(any(
2246 $(feature = "" $version),+
2247 ))]
2248 )*
2249 Symbol::$operator => Some($precedence),
2250 )+
2251 _ => None,
2252 },
2253
2254 _ => None
2255 }
2256 }
2257
2258 pub fn token(&self) -> &TokenReference {
2260 match self {
2261 $(
2262 $(
2263 #[cfg(any(
2264 $(feature = "" $version),+
2265 ))]
2266 )*
2267 BinOp::$operator(token) => token,
2268 )+
2269 }
2270 }
2271
2272 pub(crate) fn consume(state: &mut parser_structs::ParserState) -> Option<Self> {
2273 match state.current().unwrap().token_type() {
2274 TokenType::Symbol { symbol } => match symbol {
2275 $(
2276 $(
2277 #[cfg(any(
2278 $(feature = "" $version),+
2279 ))]
2280 )*
2281 Symbol::$operator => {
2282 if !$crate::has_version!(state.lua_version(), $($($version,)+)?) {
2283 return None;
2284 }
2285
2286 Some(BinOp::$operator(state.consume().unwrap()))
2287 },
2288 )+
2289
2290 _ => None,
2291 },
2292
2293 _ => None,
2294 }
2295 }
2296 }
2297 }
2298 };
2299}
2300
2301make_bin_op!(
2302 #[doc = "Operators that require two operands, such as X + Y or X - Y"]
2303 #[visit(skip_visit_self)]
2304 {
2305 Caret = 12,
2306
2307 Percent = 10,
2308 Slash = 10,
2309 Star = 10,
2310 [luau | lua53] DoubleSlash = 10,
2311
2312 Minus = 9,
2313 Plus = 9,
2314
2315 TwoDots = 8,
2316 [lua53] DoubleLessThan = 7,
2317 [lua53] DoubleGreaterThan = 7,
2318
2319 [lua53] Ampersand = 6,
2320
2321 [lua53] Tilde = 5,
2322
2323 [lua53] Pipe = 4,
2324
2325 GreaterThan = 3,
2326 GreaterThanEqual = 3,
2327 LessThan = 3,
2328 LessThanEqual = 3,
2329 TildeEqual = 3,
2330 TwoEqual = 3,
2331
2332 And = 2,
2333
2334 Or = 1,
2335 }
2336);
2337
2338impl BinOp {
2339 pub fn precedence(&self) -> u8 {
2342 BinOp::precedence_of_token(self.token()).expect("invalid token")
2343 }
2344
2345 pub fn is_right_associative(&self) -> bool {
2348 matches!(*self, BinOp::Caret(_) | BinOp::TwoDots(_))
2349 }
2350
2351 pub fn is_right_associative_token(token: &TokenReference) -> bool {
2353 matches!(
2354 token.token_type(),
2355 TokenType::Symbol {
2356 symbol: Symbol::Caret
2357 } | TokenType::Symbol {
2358 symbol: Symbol::TwoDots
2359 }
2360 )
2361 }
2362}
2363
2364#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2366#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2367#[allow(missing_docs)]
2368#[non_exhaustive]
2369#[display("{_0}")]
2370pub enum UnOp {
2371 Minus(TokenReference),
2372 Not(TokenReference),
2373 Hash(TokenReference),
2374 #[cfg(feature = "lua53")]
2375 Tilde(TokenReference),
2376}
2377
2378impl UnOp {
2379 pub fn token(&self) -> &TokenReference {
2381 match self {
2382 UnOp::Minus(token) | UnOp::Not(token) | UnOp::Hash(token) => token,
2383 #[cfg(feature = "lua53")]
2384 UnOp::Tilde(token) => token,
2385 }
2386 }
2387
2388 pub fn precedence() -> u8 {
2391 11
2392 }
2393}
2394
2395#[derive(Clone, Debug, PartialEq, Eq)]
2397#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2398pub struct AstError {
2399 token: Token,
2401
2402 additional: Cow<'static, str>,
2404
2405 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2407 range: Option<(Position, Position)>,
2408}
2409
2410impl AstError {
2411 pub fn token(&self) -> &Token {
2413 &self.token
2414 }
2415
2416 pub fn error_message(&self) -> &str {
2418 self.additional.as_ref()
2419 }
2420
2421 pub fn range(&self) -> (Position, Position) {
2423 self.range
2424 .or_else(|| Some((self.token.start_position(), self.token.end_position())))
2425 .unwrap()
2426 }
2427}
2428
2429impl fmt::Display for AstError {
2430 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2431 let range = self.range();
2432
2433 write!(
2434 formatter,
2435 "unexpected token `{}`. (starting from line {}, character {} and ending on line {}, character {})\nadditional information: {}",
2436 self.token,
2437 range.0.line(),
2438 range.0.character(),
2439 range.1.line(),
2440 range.1.character(),
2441 self.additional,
2442 )
2443 }
2444}
2445
2446impl std::error::Error for AstError {}
2447
2448#[derive(Clone, Debug)]
2450#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2451pub struct Ast {
2452 pub(crate) nodes: Block,
2453 pub(crate) eof: TokenReference,
2454}
2455
2456impl Ast {
2457 pub fn with_nodes(self, nodes: Block) -> Self {
2459 Self { nodes, ..self }
2460 }
2461
2462 pub fn with_eof(self, eof: TokenReference) -> Self {
2464 Self { eof, ..self }
2465 }
2466
2467 pub fn nodes(&self) -> &Block {
2476 &self.nodes
2477 }
2478
2479 pub fn nodes_mut(&mut self) -> &mut Block {
2481 &mut self.nodes
2482 }
2483
2484 pub fn eof(&self) -> &TokenReference {
2486 &self.eof
2487 }
2488}
2489
2490impl fmt::Display for Ast {
2491 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2492 write!(f, "{}", self.nodes())?;
2493 write!(f, "{}", self.eof())
2494 }
2495}
2496
2497#[cfg(test)]
2498mod tests {
2499 use crate::{parse, visitors::VisitorMut};
2500
2501 use super::*;
2502
2503 #[test]
2504 fn test_with_eof_safety() {
2505 let new_ast = {
2506 let ast = parse("local foo = 1").unwrap();
2507 let eof = ast.eof().clone();
2508 ast.with_eof(eof)
2509 };
2510
2511 assert_eq!("local foo = 1", new_ast.to_string());
2512 }
2513
2514 #[test]
2515 fn test_with_nodes_safety() {
2516 let new_ast = {
2517 let ast = parse("local foo = 1").unwrap();
2518 let nodes = ast.nodes().clone();
2519 ast.with_nodes(nodes)
2520 };
2521
2522 assert_eq!(new_ast.to_string(), "local foo = 1");
2523 }
2524
2525 #[test]
2526 fn test_with_visitor_safety() {
2527 let new_ast = {
2528 let ast = parse("local foo = 1").unwrap();
2529
2530 struct SyntaxRewriter;
2531 impl VisitorMut for SyntaxRewriter {
2532 fn visit_token(&mut self, token: Token) -> Token {
2533 token
2534 }
2535 }
2536
2537 SyntaxRewriter.visit_ast(ast)
2538 };
2539
2540 assert_eq!(new_ast.to_string(), "local foo = 1");
2541 }
2542
2543 #[test]
2545 fn test_new_validity() {
2546 let token: TokenReference = TokenReference::new(
2547 Vec::new(),
2548 Token::new(TokenType::Identifier {
2549 identifier: "foo".into(),
2550 }),
2551 Vec::new(),
2552 );
2553
2554 let expression = Expression::Var(Var::Name(token.clone()));
2555
2556 Assignment::new(Punctuated::new(), Punctuated::new());
2557 Do::new();
2558 ElseIf::new(expression.clone());
2559 FunctionBody::new();
2560 FunctionCall::new(Prefix::Name(token.clone()));
2561 FunctionDeclaration::new(FunctionName::new(Punctuated::new()));
2562 GenericFor::new(Punctuated::new(), Punctuated::new());
2563 If::new(expression.clone());
2564 LocalAssignment::new(Punctuated::new());
2565 LocalFunction::new(token.clone());
2566 MethodCall::new(
2567 token.clone(),
2568 FunctionArgs::Parentheses {
2569 arguments: Punctuated::new(),
2570 parentheses: ContainedSpan::new(token.clone(), token.clone()),
2571 },
2572 );
2573 NumericFor::new(token, expression.clone(), expression.clone());
2574 Repeat::new(expression.clone());
2575 Return::new();
2576 TableConstructor::new();
2577 While::new(expression);
2578 }
2579
2580 #[test]
2581 fn test_local_assignment_print() {
2582 let block = Block::new().with_stmts(vec![(
2583 Stmt::LocalAssignment(
2584 LocalAssignment::new(
2585 std::iter::once(Pair::End(TokenReference::new(
2586 vec![],
2587 Token::new(TokenType::Identifier {
2588 identifier: "variable".into(),
2589 }),
2590 vec![],
2591 )))
2592 .collect(),
2593 )
2594 .with_equal_token(Some(TokenReference::symbol(" = ").unwrap()))
2595 .with_expressions(
2596 std::iter::once(Pair::End(Expression::Number(TokenReference::new(
2597 vec![],
2598 Token::new(TokenType::Number { text: "1".into() }),
2599 vec![],
2600 ))))
2601 .collect(),
2602 ),
2603 ),
2604 None,
2605 )]);
2606
2607 let ast = parse("").unwrap().with_nodes(block);
2608 assert_eq!(ast.to_string(), "local variable = 1");
2609 }
2610}