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 ExportedTypeDeclaration(ExportedTypeDeclaration),
486 #[cfg(feature = "luau")]
489 TypeDeclaration(TypeDeclaration),
490 #[cfg(feature = "luau")]
493 ExportedTypeFunction(ExportedTypeFunction),
494 #[cfg(feature = "luau")]
497 TypeFunction(TypeFunction),
498
499 #[cfg(any(feature = "lua52", feature = "luajit"))]
502 Goto(Goto),
503 #[cfg(any(feature = "lua52", feature = "luajit"))]
506 Label(Label),
507}
508
509#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
512#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
513#[non_exhaustive]
514pub enum Prefix {
515 #[display("{_0}")]
516 Expression(Box<Expression>),
518 #[display("{_0}")]
519 Name(TokenReference),
521}
522
523#[derive(Clone, Debug, Display, PartialEq, Node)]
526#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
527#[non_exhaustive]
528pub enum Index {
529 #[display("{}{}{}", brackets.tokens().0, expression, brackets.tokens().1)]
531 Brackets {
532 brackets: ContainedSpan,
534 expression: Expression,
536 },
537
538 #[display("{dot}{name}")]
540 Dot {
541 dot: TokenReference,
543 name: TokenReference,
545 },
546}
547
548#[derive(Clone, Debug, Display, PartialEq, Node)]
550#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
551#[non_exhaustive]
552pub enum FunctionArgs {
553 #[display(
555 "{}{}{}",
556 parentheses.tokens().0,
557 arguments,
558 parentheses.tokens().1
559 )]
560 Parentheses {
561 #[node(full_range)]
563 parentheses: ContainedSpan,
564 arguments: Punctuated<Expression>,
566 },
567 #[display("{_0}")]
569 String(TokenReference),
570 #[display("{_0}")]
572 TableConstructor(TableConstructor),
573}
574
575impl FunctionArgs {
576 pub(crate) fn empty() -> Self {
577 FunctionArgs::Parentheses {
578 parentheses: ContainedSpan::new(
579 TokenReference::basic_symbol("("),
580 TokenReference::basic_symbol(")"),
581 ),
582
583 arguments: Punctuated::new(),
584 }
585 }
586}
587
588#[derive(Clone, Debug, PartialEq, Node)]
590#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
591pub struct NumericFor {
592 for_token: TokenReference,
593 index_variable: TokenReference,
594 equal_token: TokenReference,
595 start: Expression,
596 start_end_comma: TokenReference,
597 end: Expression,
598 end_step_comma: Option<TokenReference>,
599 step: Option<Expression>,
600 do_token: TokenReference,
601 block: Block,
602 end_token: TokenReference,
603 #[cfg(feature = "luau")]
604 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
605 type_specifier: Option<TypeSpecifier>,
606}
607
608impl NumericFor {
609 pub fn new(index_variable: TokenReference, start: Expression, end: Expression) -> Self {
611 Self {
612 for_token: TokenReference::basic_symbol("for "),
613 index_variable,
614 equal_token: TokenReference::basic_symbol(" = "),
615 start,
616 start_end_comma: TokenReference::basic_symbol(", "),
617 end,
618 end_step_comma: None,
619 step: None,
620 do_token: TokenReference::basic_symbol(" do\n"),
621 block: Block::new(),
622 end_token: TokenReference::basic_symbol("\nend"),
623 #[cfg(feature = "luau")]
624 type_specifier: None,
625 }
626 }
627
628 pub fn for_token(&self) -> &TokenReference {
630 &self.for_token
631 }
632
633 pub fn index_variable(&self) -> &TokenReference {
635 &self.index_variable
636 }
637
638 pub fn equal_token(&self) -> &TokenReference {
640 &self.equal_token
641 }
642
643 pub fn start(&self) -> &Expression {
645 &self.start
646 }
647
648 pub fn start_end_comma(&self) -> &TokenReference {
652 &self.start_end_comma
653 }
654
655 pub fn end(&self) -> &Expression {
657 &self.end
658 }
659
660 pub fn end_step_comma(&self) -> Option<&TokenReference> {
664 self.end_step_comma.as_ref()
665 }
666
667 pub fn step(&self) -> Option<&Expression> {
669 self.step.as_ref()
670 }
671
672 pub fn do_token(&self) -> &TokenReference {
674 &self.do_token
675 }
676
677 pub fn block(&self) -> &Block {
679 &self.block
680 }
681
682 pub fn end_token(&self) -> &TokenReference {
684 &self.end_token
685 }
686
687 #[cfg(feature = "luau")]
692 pub fn type_specifier(&self) -> Option<&TypeSpecifier> {
693 self.type_specifier.as_ref()
694 }
695
696 pub fn with_for_token(self, for_token: TokenReference) -> Self {
698 Self { for_token, ..self }
699 }
700
701 pub fn with_index_variable(self, index_variable: TokenReference) -> Self {
703 Self {
704 index_variable,
705 ..self
706 }
707 }
708
709 pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
711 Self {
712 equal_token,
713 ..self
714 }
715 }
716
717 pub fn with_start(self, start: Expression) -> Self {
719 Self { start, ..self }
720 }
721
722 pub fn with_start_end_comma(self, start_end_comma: TokenReference) -> Self {
724 Self {
725 start_end_comma,
726 ..self
727 }
728 }
729
730 pub fn with_end(self, end: Expression) -> Self {
732 Self { end, ..self }
733 }
734
735 pub fn with_end_step_comma(self, end_step_comma: Option<TokenReference>) -> Self {
737 Self {
738 end_step_comma,
739 ..self
740 }
741 }
742
743 pub fn with_step(self, step: Option<Expression>) -> Self {
745 Self { step, ..self }
746 }
747
748 pub fn with_do_token(self, do_token: TokenReference) -> Self {
750 Self { do_token, ..self }
751 }
752
753 pub fn with_block(self, block: Block) -> Self {
755 Self { block, ..self }
756 }
757
758 pub fn with_end_token(self, end_token: TokenReference) -> Self {
760 Self { end_token, ..self }
761 }
762
763 #[cfg(feature = "luau")]
766 pub fn with_type_specifier(self, type_specifier: Option<TypeSpecifier>) -> Self {
767 Self {
768 type_specifier,
769 ..self
770 }
771 }
772}
773
774impl fmt::Display for NumericFor {
775 #[cfg(feature = "luau")]
776 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
777 write!(
778 formatter,
779 "{}{}{}{}{}{}{}{}{}{}{}{}",
780 self.for_token,
781 self.index_variable,
782 display_option(self.type_specifier()),
783 self.equal_token,
784 self.start,
785 self.start_end_comma,
786 self.end,
787 display_option(self.end_step_comma()),
788 display_option(self.step()),
789 self.do_token,
790 self.block,
791 self.end_token,
792 )
793 }
794
795 #[cfg(not(feature = "luau"))]
796 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
797 write!(
798 formatter,
799 "{}{}{}{}{}{}{}{}{}{}{}",
800 self.for_token,
801 self.index_variable,
802 self.equal_token,
803 self.start,
804 self.start_end_comma,
805 self.end,
806 display_option(self.end_step_comma()),
807 display_option(self.step()),
808 self.do_token,
809 self.block,
810 self.end_token,
811 )
812 }
813}
814
815#[derive(Clone, Debug, PartialEq, Node)]
817#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
818pub struct GenericFor {
819 for_token: TokenReference,
820 names: Punctuated<TokenReference>,
821 in_token: TokenReference,
822 expr_list: Punctuated<Expression>,
823 do_token: TokenReference,
824 block: Block,
825 end_token: TokenReference,
826 #[cfg(feature = "luau")]
827 #[cfg_attr(
828 feature = "serde",
829 serde(skip_serializing_if = "vec_empty_or_all_none")
830 )]
831 type_specifiers: Vec<Option<TypeSpecifier>>,
832}
833
834impl GenericFor {
835 pub fn new(names: Punctuated<TokenReference>, expr_list: Punctuated<Expression>) -> Self {
837 Self {
838 for_token: TokenReference::basic_symbol("for "),
839 names,
840 in_token: TokenReference::basic_symbol(" in "),
841 expr_list,
842 do_token: TokenReference::basic_symbol(" do\n"),
843 block: Block::new(),
844 end_token: TokenReference::basic_symbol("\nend"),
845 #[cfg(feature = "luau")]
846 type_specifiers: Vec::new(),
847 }
848 }
849
850 pub fn for_token(&self) -> &TokenReference {
852 &self.for_token
853 }
854
855 pub fn names(&self) -> &Punctuated<TokenReference> {
858 &self.names
859 }
860
861 pub fn in_token(&self) -> &TokenReference {
863 &self.in_token
864 }
865
866 pub fn expressions(&self) -> &Punctuated<Expression> {
869 &self.expr_list
870 }
871
872 pub fn do_token(&self) -> &TokenReference {
874 &self.do_token
875 }
876
877 pub fn block(&self) -> &Block {
879 &self.block
880 }
881
882 pub fn end_token(&self) -> &TokenReference {
884 &self.end_token
885 }
886
887 #[cfg(feature = "luau")]
892 pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
893 self.type_specifiers.iter().map(Option::as_ref)
894 }
895
896 pub fn with_for_token(self, for_token: TokenReference) -> Self {
898 Self { for_token, ..self }
899 }
900
901 pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
903 Self { names, ..self }
904 }
905
906 pub fn with_in_token(self, in_token: TokenReference) -> Self {
908 Self { in_token, ..self }
909 }
910
911 pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
913 Self { expr_list, ..self }
914 }
915
916 pub fn with_do_token(self, do_token: TokenReference) -> Self {
918 Self { do_token, ..self }
919 }
920
921 pub fn with_block(self, block: Block) -> Self {
923 Self { block, ..self }
924 }
925
926 pub fn with_end_token(self, end_token: TokenReference) -> Self {
928 Self { end_token, ..self }
929 }
930
931 #[cfg(feature = "luau")]
934 pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
935 Self {
936 type_specifiers,
937 ..self
938 }
939 }
940}
941
942impl fmt::Display for GenericFor {
943 #[cfg(feature = "luau")]
944 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
945 write!(
946 formatter,
947 "{}{}{}{}{}{}{}",
948 self.for_token,
949 join_type_specifiers(&self.names, self.type_specifiers()),
950 self.in_token,
951 self.expr_list,
952 self.do_token,
953 self.block,
954 self.end_token
955 )
956 }
957
958 #[cfg(not(feature = "luau"))]
959 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
960 write!(
961 formatter,
962 "{}{}{}{}{}{}{}",
963 self.for_token,
964 self.names,
965 self.in_token,
966 self.expr_list,
967 self.do_token,
968 self.block,
969 self.end_token
970 )
971 }
972}
973
974#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
976#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
977#[display(
978 "{}{}{}{}{}{}{}{}",
979 if_token,
980 condition,
981 then_token,
982 block,
983 display_option(else_if.as_ref().map(join_vec)),
984 display_option(else_token),
985 display_option(r#else),
986 end_token
987)]
988pub struct If {
989 if_token: TokenReference,
990 condition: Expression,
991 then_token: TokenReference,
992 block: Block,
993 else_if: Option<Vec<ElseIf>>,
994 else_token: Option<TokenReference>,
995 #[cfg_attr(feature = "serde", serde(rename = "else"))]
996 r#else: Option<Block>,
997 end_token: TokenReference,
998}
999
1000impl If {
1001 pub fn new(condition: Expression) -> Self {
1003 Self {
1004 if_token: TokenReference::basic_symbol("if "),
1005 condition,
1006 then_token: TokenReference::basic_symbol(" then"),
1007 block: Block::new(),
1008 else_if: None,
1009 else_token: None,
1010 r#else: None,
1011 end_token: TokenReference::basic_symbol("\nend"),
1012 }
1013 }
1014
1015 pub fn if_token(&self) -> &TokenReference {
1017 &self.if_token
1018 }
1019
1020 pub fn condition(&self) -> &Expression {
1022 &self.condition
1023 }
1024
1025 pub fn then_token(&self) -> &TokenReference {
1027 &self.then_token
1028 }
1029
1030 pub fn block(&self) -> &Block {
1032 &self.block
1033 }
1034
1035 pub fn else_token(&self) -> Option<&TokenReference> {
1037 self.else_token.as_ref()
1038 }
1039
1040 pub fn else_if(&self) -> Option<&Vec<ElseIf>> {
1044 self.else_if.as_ref()
1045 }
1046
1047 pub fn else_block(&self) -> Option<&Block> {
1049 self.r#else.as_ref()
1050 }
1051
1052 pub fn end_token(&self) -> &TokenReference {
1054 &self.end_token
1055 }
1056
1057 pub fn with_if_token(self, if_token: TokenReference) -> Self {
1059 Self { if_token, ..self }
1060 }
1061
1062 pub fn with_condition(self, condition: Expression) -> Self {
1064 Self { condition, ..self }
1065 }
1066
1067 pub fn with_then_token(self, then_token: TokenReference) -> Self {
1069 Self { then_token, ..self }
1070 }
1071
1072 pub fn with_block(self, block: Block) -> Self {
1074 Self { block, ..self }
1075 }
1076
1077 pub fn with_else_if(self, else_if: Option<Vec<ElseIf>>) -> Self {
1079 Self { else_if, ..self }
1080 }
1081
1082 pub fn with_else_token(self, else_token: Option<TokenReference>) -> Self {
1084 Self { else_token, ..self }
1085 }
1086
1087 pub fn with_else(self, r#else: Option<Block>) -> Self {
1089 Self { r#else, ..self }
1090 }
1091
1092 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1094 Self { end_token, ..self }
1095 }
1096}
1097
1098#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1100#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1101#[display("{else_if_token}{condition}{then_token}{block}")]
1102pub struct ElseIf {
1103 else_if_token: TokenReference,
1104 condition: Expression,
1105 then_token: TokenReference,
1106 block: Block,
1107}
1108
1109impl ElseIf {
1110 pub fn new(condition: Expression) -> Self {
1112 Self {
1113 else_if_token: TokenReference::basic_symbol("elseif "),
1114 condition,
1115 then_token: TokenReference::basic_symbol(" then\n"),
1116 block: Block::new(),
1117 }
1118 }
1119
1120 pub fn else_if_token(&self) -> &TokenReference {
1122 &self.else_if_token
1123 }
1124
1125 pub fn condition(&self) -> &Expression {
1127 &self.condition
1128 }
1129
1130 pub fn then_token(&self) -> &TokenReference {
1132 &self.then_token
1133 }
1134
1135 pub fn block(&self) -> &Block {
1137 &self.block
1138 }
1139
1140 pub fn with_else_if_token(self, else_if_token: TokenReference) -> Self {
1142 Self {
1143 else_if_token,
1144 ..self
1145 }
1146 }
1147
1148 pub fn with_condition(self, condition: Expression) -> Self {
1150 Self { condition, ..self }
1151 }
1152
1153 pub fn with_then_token(self, then_token: TokenReference) -> Self {
1155 Self { then_token, ..self }
1156 }
1157
1158 pub fn with_block(self, block: Block) -> Self {
1160 Self { block, ..self }
1161 }
1162}
1163
1164#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1166#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1167#[display("{while_token}{condition}{do_token}{block}{end_token}")]
1168pub struct While {
1169 while_token: TokenReference,
1170 condition: Expression,
1171 do_token: TokenReference,
1172 block: Block,
1173 end_token: TokenReference,
1174}
1175
1176impl While {
1177 pub fn new(condition: Expression) -> Self {
1179 Self {
1180 while_token: TokenReference::basic_symbol("while "),
1181 condition,
1182 do_token: TokenReference::basic_symbol(" do\n"),
1183 block: Block::new(),
1184 end_token: TokenReference::basic_symbol("end\n"),
1185 }
1186 }
1187
1188 pub fn while_token(&self) -> &TokenReference {
1190 &self.while_token
1191 }
1192
1193 pub fn condition(&self) -> &Expression {
1195 &self.condition
1196 }
1197
1198 pub fn do_token(&self) -> &TokenReference {
1200 &self.do_token
1201 }
1202
1203 pub fn block(&self) -> &Block {
1205 &self.block
1206 }
1207
1208 pub fn end_token(&self) -> &TokenReference {
1210 &self.end_token
1211 }
1212
1213 pub fn with_while_token(self, while_token: TokenReference) -> Self {
1215 Self {
1216 while_token,
1217 ..self
1218 }
1219 }
1220
1221 pub fn with_condition(self, condition: Expression) -> Self {
1223 Self { condition, ..self }
1224 }
1225
1226 pub fn with_do_token(self, do_token: TokenReference) -> Self {
1228 Self { do_token, ..self }
1229 }
1230
1231 pub fn with_block(self, block: Block) -> Self {
1233 Self { block, ..self }
1234 }
1235
1236 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1238 Self { end_token, ..self }
1239 }
1240}
1241
1242#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1244#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1245#[display("{repeat_token}{block}{until_token}{until}")]
1246pub struct Repeat {
1247 repeat_token: TokenReference,
1248 block: Block,
1249 until_token: TokenReference,
1250 until: Expression,
1251}
1252
1253impl Repeat {
1254 pub fn new(until: Expression) -> Self {
1256 Self {
1257 repeat_token: TokenReference::basic_symbol("repeat\n"),
1258 block: Block::new(),
1259 until_token: TokenReference::basic_symbol("\nuntil "),
1260 until,
1261 }
1262 }
1263
1264 pub fn repeat_token(&self) -> &TokenReference {
1266 &self.repeat_token
1267 }
1268
1269 pub fn block(&self) -> &Block {
1271 &self.block
1272 }
1273
1274 pub fn until_token(&self) -> &TokenReference {
1276 &self.until_token
1277 }
1278
1279 pub fn until(&self) -> &Expression {
1281 &self.until
1282 }
1283
1284 pub fn with_repeat_token(self, repeat_token: TokenReference) -> Self {
1286 Self {
1287 repeat_token,
1288 ..self
1289 }
1290 }
1291
1292 pub fn with_block(self, block: Block) -> Self {
1294 Self { block, ..self }
1295 }
1296
1297 pub fn with_until_token(self, until_token: TokenReference) -> Self {
1299 Self {
1300 until_token,
1301 ..self
1302 }
1303 }
1304
1305 pub fn with_until(self, until: Expression) -> Self {
1307 Self { until, ..self }
1308 }
1309}
1310
1311#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1313#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1314#[display("{colon_token}{name}{args}")]
1315pub struct MethodCall {
1316 colon_token: TokenReference,
1317 name: TokenReference,
1318 args: FunctionArgs,
1319}
1320
1321impl MethodCall {
1322 pub fn new(name: TokenReference, args: FunctionArgs) -> Self {
1324 Self {
1325 colon_token: TokenReference::basic_symbol(":"),
1326 name,
1327 args,
1328 }
1329 }
1330
1331 pub fn colon_token(&self) -> &TokenReference {
1333 &self.colon_token
1334 }
1335
1336 pub fn args(&self) -> &FunctionArgs {
1338 &self.args
1339 }
1340
1341 pub fn name(&self) -> &TokenReference {
1343 &self.name
1344 }
1345
1346 pub fn with_colon_token(self, colon_token: TokenReference) -> Self {
1348 Self {
1349 colon_token,
1350 ..self
1351 }
1352 }
1353
1354 pub fn with_name(self, name: TokenReference) -> Self {
1356 Self { name, ..self }
1357 }
1358
1359 pub fn with_args(self, args: FunctionArgs) -> Self {
1361 Self { args, ..self }
1362 }
1363}
1364
1365#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1367#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1368#[non_exhaustive]
1369pub enum Call {
1370 #[display("{_0}")]
1371 AnonymousCall(FunctionArgs),
1373 #[display("{_0}")]
1374 MethodCall(MethodCall),
1376}
1377
1378#[derive(Clone, Debug, PartialEq, Node)]
1380#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1381pub struct FunctionBody {
1382 #[cfg(feature = "luau")]
1383 generics: Option<GenericDeclaration>,
1384
1385 parameters_parentheses: ContainedSpan,
1386 parameters: Punctuated<Parameter>,
1387
1388 #[cfg(feature = "luau")]
1389 type_specifiers: Vec<Option<TypeSpecifier>>,
1390
1391 #[cfg(feature = "luau")]
1392 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1393 return_type: Option<TypeSpecifier>,
1394
1395 block: Block,
1396 end_token: TokenReference,
1397}
1398
1399impl FunctionBody {
1400 pub fn new() -> Self {
1402 Self {
1403 #[cfg(feature = "luau")]
1404 generics: None,
1405
1406 parameters_parentheses: ContainedSpan::new(
1407 TokenReference::basic_symbol("("),
1408 TokenReference::basic_symbol(")"),
1409 ),
1410 parameters: Punctuated::new(),
1411
1412 #[cfg(feature = "luau")]
1413 type_specifiers: Vec::new(),
1414
1415 #[cfg(feature = "luau")]
1416 return_type: None,
1417
1418 block: Block::new(),
1419 end_token: TokenReference::basic_symbol("\nend"),
1420 }
1421 }
1422
1423 pub fn parameters_parentheses(&self) -> &ContainedSpan {
1425 &self.parameters_parentheses
1426 }
1427
1428 pub fn parameters(&self) -> &Punctuated<Parameter> {
1430 &self.parameters
1431 }
1432
1433 pub fn block(&self) -> &Block {
1435 &self.block
1436 }
1437
1438 pub fn end_token(&self) -> &TokenReference {
1440 &self.end_token
1441 }
1442
1443 #[cfg(feature = "luau")]
1447 pub fn generics(&self) -> Option<&GenericDeclaration> {
1448 self.generics.as_ref()
1449 }
1450
1451 #[cfg(feature = "luau")]
1456 pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1457 self.type_specifiers.iter().map(Option::as_ref)
1458 }
1459
1460 #[cfg(feature = "luau")]
1463 pub fn return_type(&self) -> Option<&TypeSpecifier> {
1464 self.return_type.as_ref()
1465 }
1466
1467 pub fn with_parameters_parentheses(self, parameters_parentheses: ContainedSpan) -> Self {
1469 Self {
1470 parameters_parentheses,
1471 ..self
1472 }
1473 }
1474
1475 pub fn with_parameters(self, parameters: Punctuated<Parameter>) -> Self {
1477 Self { parameters, ..self }
1478 }
1479
1480 #[cfg(feature = "luau")]
1482 pub fn with_generics(self, generics: Option<GenericDeclaration>) -> Self {
1483 Self { generics, ..self }
1484 }
1485
1486 #[cfg(feature = "luau")]
1488 pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1489 Self {
1490 type_specifiers,
1491 ..self
1492 }
1493 }
1494
1495 #[cfg(feature = "luau")]
1497 pub fn with_return_type(self, return_type: Option<TypeSpecifier>) -> Self {
1498 Self {
1499 return_type,
1500 ..self
1501 }
1502 }
1503
1504 pub fn with_block(self, block: Block) -> Self {
1506 Self { block, ..self }
1507 }
1508
1509 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1511 Self { end_token, ..self }
1512 }
1513}
1514
1515impl Default for FunctionBody {
1516 fn default() -> Self {
1517 Self::new()
1518 }
1519}
1520
1521impl fmt::Display for FunctionBody {
1522 #[cfg(feature = "luau")]
1523 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1524 write!(
1525 formatter,
1526 "{}{}{}{}{}{}{}",
1527 display_option(self.generics.as_ref()),
1528 self.parameters_parentheses.tokens().0,
1529 join_type_specifiers(&self.parameters, self.type_specifiers()),
1530 self.parameters_parentheses.tokens().1,
1531 display_option(self.return_type.as_ref()),
1532 self.block,
1533 self.end_token
1534 )
1535 }
1536
1537 #[cfg(not(feature = "luau"))]
1538 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1539 write!(
1540 formatter,
1541 "{}{}{}{}{}",
1542 self.parameters_parentheses.tokens().0,
1543 self.parameters,
1544 self.parameters_parentheses.tokens().1,
1545 self.block,
1546 self.end_token
1547 )
1548 }
1549}
1550
1551#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
1553#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1554#[non_exhaustive]
1555pub enum Parameter {
1556 Ellipsis(TokenReference),
1558 Name(TokenReference),
1560}
1561
1562#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1565#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1566#[non_exhaustive]
1567pub enum Suffix {
1568 #[display("{_0}")]
1569 Call(Call),
1571 #[display("{_0}")]
1572 Index(Index),
1574}
1575
1576#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1578#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1579#[display("{}{}", prefix, join_vec(suffixes))]
1580pub struct VarExpression {
1581 prefix: Prefix,
1582 suffixes: Vec<Suffix>,
1583}
1584
1585impl VarExpression {
1586 pub fn new(prefix: Prefix) -> Self {
1588 Self {
1589 prefix,
1590 suffixes: Vec::new(),
1591 }
1592 }
1593
1594 pub fn prefix(&self) -> &Prefix {
1596 &self.prefix
1597 }
1598
1599 pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
1601 self.suffixes.iter()
1602 }
1603
1604 pub fn with_prefix(self, prefix: Prefix) -> Self {
1606 Self { prefix, ..self }
1607 }
1608
1609 pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
1611 Self { suffixes, ..self }
1612 }
1613}
1614
1615#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1617#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1618#[non_exhaustive]
1619pub enum Var {
1620 #[display("{_0}")]
1622 Expression(Box<VarExpression>),
1623 #[display("{_0}")]
1625 Name(TokenReference),
1626}
1627
1628#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1630#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1631#[display("{var_list}{equal_token}{expr_list}")]
1632pub struct Assignment {
1633 var_list: Punctuated<Var>,
1634 equal_token: TokenReference,
1635 expr_list: Punctuated<Expression>,
1636}
1637
1638impl Assignment {
1639 pub fn new(var_list: Punctuated<Var>, expr_list: Punctuated<Expression>) -> Self {
1641 Self {
1642 var_list,
1643 equal_token: TokenReference::basic_symbol(" = "),
1644 expr_list,
1645 }
1646 }
1647
1648 pub fn expressions(&self) -> &Punctuated<Expression> {
1651 &self.expr_list
1652 }
1653
1654 pub fn equal_token(&self) -> &TokenReference {
1656 &self.equal_token
1657 }
1658
1659 pub fn variables(&self) -> &Punctuated<Var> {
1662 &self.var_list
1663 }
1664
1665 pub fn with_variables(self, var_list: Punctuated<Var>) -> Self {
1667 Self { var_list, ..self }
1668 }
1669
1670 pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
1672 Self {
1673 equal_token,
1674 ..self
1675 }
1676 }
1677
1678 pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1680 Self { expr_list, ..self }
1681 }
1682}
1683
1684#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1686#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1687#[cfg_attr(
1688 not(feature = "luau"),
1689 display("{local_token}{function_token}{name}{body}")
1690)]
1691#[cfg_attr(
1692 feature = "luau",
1693 display(
1694 "{}{}{}{}{}",
1695 join_vec(attributes),
1696 local_token,
1697 function_token,
1698 name,
1699 body
1700 )
1701)]
1702pub struct LocalFunction {
1703 #[cfg(feature = "luau")]
1704 attributes: Vec<LuauAttribute>,
1705 local_token: TokenReference,
1706 function_token: TokenReference,
1707 name: TokenReference,
1708 body: FunctionBody,
1709}
1710
1711impl LocalFunction {
1712 pub fn new(name: TokenReference) -> Self {
1714 LocalFunction {
1715 #[cfg(feature = "luau")]
1716 attributes: Vec::new(),
1717 local_token: TokenReference::basic_symbol("local "),
1718 function_token: TokenReference::basic_symbol("function "),
1719 name,
1720 body: FunctionBody::new(),
1721 }
1722 }
1723
1724 #[cfg(feature = "luau")]
1726 pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
1727 self.attributes.iter()
1728 }
1729
1730 pub fn local_token(&self) -> &TokenReference {
1732 &self.local_token
1733 }
1734
1735 pub fn function_token(&self) -> &TokenReference {
1737 &self.function_token
1738 }
1739
1740 pub fn body(&self) -> &FunctionBody {
1742 &self.body
1743 }
1744
1745 pub fn name(&self) -> &TokenReference {
1747 &self.name
1748 }
1749
1750 #[cfg(feature = "luau")]
1752 pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
1753 Self { attributes, ..self }
1754 }
1755
1756 pub fn with_local_token(self, local_token: TokenReference) -> Self {
1758 Self {
1759 local_token,
1760 ..self
1761 }
1762 }
1763
1764 pub fn with_function_token(self, function_token: TokenReference) -> Self {
1766 Self {
1767 function_token,
1768 ..self
1769 }
1770 }
1771
1772 pub fn with_name(self, name: TokenReference) -> Self {
1774 Self { name, ..self }
1775 }
1776
1777 pub fn with_body(self, body: FunctionBody) -> Self {
1779 Self { body, ..self }
1780 }
1781}
1782
1783#[derive(Clone, Debug, PartialEq, Node)]
1785#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1786pub struct LocalAssignment {
1787 local_token: TokenReference,
1788 #[cfg(feature = "luau")]
1789 #[cfg_attr(
1790 feature = "serde",
1791 serde(skip_serializing_if = "empty_optional_vector")
1792 )]
1793 type_specifiers: Vec<Option<TypeSpecifier>>,
1794 name_list: Punctuated<TokenReference>,
1795 #[cfg(feature = "lua54")]
1796 #[cfg_attr(
1797 feature = "serde",
1798 serde(skip_serializing_if = "empty_optional_vector")
1799 )]
1800 attributes: Vec<Option<Attribute>>,
1801 equal_token: Option<TokenReference>,
1802 expr_list: Punctuated<Expression>,
1803}
1804
1805impl LocalAssignment {
1806 pub fn new(name_list: Punctuated<TokenReference>) -> Self {
1808 Self {
1809 local_token: TokenReference::basic_symbol("local "),
1810 #[cfg(feature = "luau")]
1811 type_specifiers: Vec::new(),
1812 name_list,
1813 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1814 attributes: Vec::new(),
1815 equal_token: None,
1816 expr_list: Punctuated::new(),
1817 }
1818 }
1819
1820 pub fn local_token(&self) -> &TokenReference {
1822 &self.local_token
1823 }
1824
1825 pub fn equal_token(&self) -> Option<&TokenReference> {
1827 self.equal_token.as_ref()
1828 }
1829
1830 pub fn expressions(&self) -> &Punctuated<Expression> {
1833 &self.expr_list
1834 }
1835
1836 pub fn names(&self) -> &Punctuated<TokenReference> {
1839 &self.name_list
1840 }
1841
1842 #[cfg(feature = "luau")]
1847 pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1848 self.type_specifiers.iter().map(Option::as_ref)
1849 }
1850
1851 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1856 pub fn attributes(&self) -> impl Iterator<Item = Option<&Attribute>> {
1857 self.attributes.iter().map(Option::as_ref)
1858 }
1859
1860 pub fn with_local_token(self, local_token: TokenReference) -> Self {
1862 Self {
1863 local_token,
1864 ..self
1865 }
1866 }
1867
1868 #[cfg(feature = "luau")]
1870 pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1871 Self {
1872 type_specifiers,
1873 ..self
1874 }
1875 }
1876
1877 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1879 pub fn with_attributes(self, attributes: Vec<Option<Attribute>>) -> Self {
1880 Self { attributes, ..self }
1881 }
1882
1883 pub fn with_names(self, name_list: Punctuated<TokenReference>) -> Self {
1885 Self { name_list, ..self }
1886 }
1887
1888 pub fn with_equal_token(self, equal_token: Option<TokenReference>) -> Self {
1890 Self {
1891 equal_token,
1892 ..self
1893 }
1894 }
1895
1896 pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1898 Self { expr_list, ..self }
1899 }
1900}
1901
1902impl fmt::Display for LocalAssignment {
1903 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1904 #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1905 let attributes = self.attributes().chain(std::iter::repeat(None));
1906 #[cfg(not(feature = "lua54"))]
1907 let attributes = std::iter::repeat_with(|| None::<TokenReference>);
1908 #[cfg(feature = "luau")]
1909 let type_specifiers = self.type_specifiers().chain(std::iter::repeat(None));
1910 #[cfg(not(feature = "luau"))]
1911 let type_specifiers = std::iter::repeat_with(|| None::<TokenReference>);
1912
1913 write!(
1914 formatter,
1915 "{}{}{}{}",
1916 self.local_token,
1917 join_iterators(&self.name_list, attributes, type_specifiers),
1918 display_option(&self.equal_token),
1919 self.expr_list
1920 )
1921 }
1922}
1923
1924#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1927#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1928#[display("{do_token}{block}{end_token}")]
1929pub struct Do {
1930 do_token: TokenReference,
1931 block: Block,
1932 end_token: TokenReference,
1933}
1934
1935impl Do {
1936 pub fn new() -> Self {
1938 Self {
1939 do_token: TokenReference::basic_symbol("do\n"),
1940 block: Block::new(),
1941 end_token: TokenReference::basic_symbol("\nend"),
1942 }
1943 }
1944
1945 pub fn do_token(&self) -> &TokenReference {
1947 &self.do_token
1948 }
1949
1950 pub fn block(&self) -> &Block {
1952 &self.block
1953 }
1954
1955 pub fn end_token(&self) -> &TokenReference {
1957 &self.end_token
1958 }
1959
1960 pub fn with_do_token(self, do_token: TokenReference) -> Self {
1962 Self { do_token, ..self }
1963 }
1964
1965 pub fn with_block(self, block: Block) -> Self {
1967 Self { block, ..self }
1968 }
1969
1970 pub fn with_end_token(self, end_token: TokenReference) -> Self {
1972 Self { end_token, ..self }
1973 }
1974}
1975
1976impl Default for Do {
1977 fn default() -> Self {
1978 Self::new()
1979 }
1980}
1981
1982#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1984#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1985#[display("{}{}", prefix, join_vec(suffixes))]
1986pub struct FunctionCall {
1987 prefix: Prefix,
1988 suffixes: Vec<Suffix>,
1989}
1990
1991impl FunctionCall {
1992 pub fn new(prefix: Prefix) -> Self {
1995 FunctionCall {
1996 prefix,
1997 suffixes: vec![Suffix::Call(Call::AnonymousCall(
1998 FunctionArgs::Parentheses {
1999 arguments: Punctuated::new(),
2000 parentheses: ContainedSpan::new(
2001 TokenReference::basic_symbol("("),
2002 TokenReference::basic_symbol(")"),
2003 ),
2004 },
2005 ))],
2006 }
2007 }
2008
2009 pub fn prefix(&self) -> &Prefix {
2011 &self.prefix
2012 }
2013
2014 pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
2016 self.suffixes.iter()
2017 }
2018
2019 pub fn with_prefix(self, prefix: Prefix) -> Self {
2021 Self { prefix, ..self }
2022 }
2023
2024 pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
2026 Self { suffixes, ..self }
2027 }
2028}
2029
2030#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2032#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2033#[display(
2034 "{}{}{}",
2035 names,
2036 display_option(self.method_colon()),
2037 display_option(self.method_name())
2038)]
2039pub struct FunctionName {
2040 names: Punctuated<TokenReference>,
2041 colon_name: Option<(TokenReference, TokenReference)>,
2042}
2043
2044impl FunctionName {
2045 pub fn new(names: Punctuated<TokenReference>) -> Self {
2047 Self {
2048 names,
2049 colon_name: None,
2050 }
2051 }
2052
2053 pub fn method_colon(&self) -> Option<&TokenReference> {
2055 Some(&self.colon_name.as_ref()?.0)
2056 }
2057
2058 pub fn method_name(&self) -> Option<&TokenReference> {
2060 Some(&self.colon_name.as_ref()?.1)
2061 }
2062
2063 pub fn names(&self) -> &Punctuated<TokenReference> {
2066 &self.names
2067 }
2068
2069 pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
2071 Self { names, ..self }
2072 }
2073
2074 pub fn with_method(self, method: Option<(TokenReference, TokenReference)>) -> Self {
2077 Self {
2078 colon_name: method,
2079 ..self
2080 }
2081 }
2082}
2083
2084#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
2087#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2088#[cfg_attr(not(feature = "luau"), display("{function_token}{name}{body}"))]
2089#[cfg_attr(
2090 feature = "luau",
2091 display("{}{}{}{}", join_vec(attributes), function_token, name, body)
2092)]
2093pub struct FunctionDeclaration {
2094 #[cfg(feature = "luau")]
2095 attributes: Vec<LuauAttribute>,
2096 function_token: TokenReference,
2097 name: FunctionName,
2098 body: FunctionBody,
2099}
2100
2101impl FunctionDeclaration {
2102 pub fn new(name: FunctionName) -> Self {
2104 Self {
2105 #[cfg(feature = "luau")]
2106 attributes: Vec::new(),
2107 function_token: TokenReference::basic_symbol("function "),
2108 name,
2109 body: FunctionBody::new(),
2110 }
2111 }
2112
2113 #[cfg(feature = "luau")]
2115 pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
2116 self.attributes.iter()
2117 }
2118
2119 pub fn function_token(&self) -> &TokenReference {
2121 &self.function_token
2122 }
2123
2124 pub fn body(&self) -> &FunctionBody {
2126 &self.body
2127 }
2128
2129 pub fn name(&self) -> &FunctionName {
2131 &self.name
2132 }
2133
2134 #[cfg(feature = "luau")]
2136 pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
2137 Self { attributes, ..self }
2138 }
2139
2140 pub fn with_function_token(self, function_token: TokenReference) -> Self {
2142 Self {
2143 function_token,
2144 ..self
2145 }
2146 }
2147
2148 pub fn with_name(self, name: FunctionName) -> Self {
2150 Self { name, ..self }
2151 }
2152
2153 pub fn with_body(self, body: FunctionBody) -> Self {
2155 Self { body, ..self }
2156 }
2157}
2158
2159#[doc(hidden)]
2160#[macro_export]
2161macro_rules! make_bin_op {
2162 ($(#[$outer:meta])* { $(
2163 $([$($version:ident)|+])? $operator:ident = $precedence:expr,
2164 )+ }) => {
2165 paste::paste! {
2166 #[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2167 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2168 #[non_exhaustive]
2169 $(#[$outer])*
2170 #[display("{_0}")]
2171 pub enum BinOp {
2172 $(
2173 #[allow(missing_docs)]
2174 $(
2175 #[cfg(any(
2176 $(feature = "" $version),+
2177 ))]
2178 )*
2179 $operator(TokenReference),
2180 )+
2181 }
2182
2183 impl BinOp {
2184 pub fn precedence_of_token(token: &TokenReference) -> Option<u8> {
2187 match token.token_type() {
2188 TokenType::Symbol { symbol } => match symbol {
2189 $(
2190 $(
2191 #[cfg(any(
2192 $(feature = "" $version),+
2193 ))]
2194 )*
2195 Symbol::$operator => Some($precedence),
2196 )+
2197 _ => None,
2198 },
2199
2200 _ => None
2201 }
2202 }
2203
2204 pub fn token(&self) -> &TokenReference {
2206 match self {
2207 $(
2208 $(
2209 #[cfg(any(
2210 $(feature = "" $version),+
2211 ))]
2212 )*
2213 BinOp::$operator(token) => token,
2214 )+
2215 }
2216 }
2217
2218 pub(crate) fn consume(state: &mut parser_structs::ParserState) -> Option<Self> {
2219 match state.current().unwrap().token_type() {
2220 TokenType::Symbol { symbol } => match symbol {
2221 $(
2222 $(
2223 #[cfg(any(
2224 $(feature = "" $version),+
2225 ))]
2226 )*
2227 Symbol::$operator => {
2228 if !$crate::has_version!(state.lua_version(), $($($version,)+)?) {
2229 return None;
2230 }
2231
2232 Some(BinOp::$operator(state.consume().unwrap()))
2233 },
2234 )+
2235
2236 _ => None,
2237 },
2238
2239 _ => None,
2240 }
2241 }
2242 }
2243 }
2244 };
2245}
2246
2247make_bin_op!(
2248 #[doc = "Operators that require two operands, such as X + Y or X - Y"]
2249 #[visit(skip_visit_self)]
2250 {
2251 Caret = 12,
2252
2253 Percent = 10,
2254 Slash = 10,
2255 Star = 10,
2256 [luau | lua53] DoubleSlash = 10,
2257
2258 Minus = 9,
2259 Plus = 9,
2260
2261 TwoDots = 8,
2262 [lua53] DoubleLessThan = 7,
2263 [lua53] DoubleGreaterThan = 7,
2264
2265 [lua53] Ampersand = 6,
2266
2267 [lua53] Tilde = 5,
2268
2269 [lua53] Pipe = 4,
2270
2271 GreaterThan = 3,
2272 GreaterThanEqual = 3,
2273 LessThan = 3,
2274 LessThanEqual = 3,
2275 TildeEqual = 3,
2276 TwoEqual = 3,
2277
2278 And = 2,
2279
2280 Or = 1,
2281 }
2282);
2283
2284impl BinOp {
2285 pub fn precedence(&self) -> u8 {
2288 BinOp::precedence_of_token(self.token()).expect("invalid token")
2289 }
2290
2291 pub fn is_right_associative(&self) -> bool {
2294 matches!(*self, BinOp::Caret(_) | BinOp::TwoDots(_))
2295 }
2296
2297 pub fn is_right_associative_token(token: &TokenReference) -> bool {
2299 matches!(
2300 token.token_type(),
2301 TokenType::Symbol {
2302 symbol: Symbol::Caret
2303 } | TokenType::Symbol {
2304 symbol: Symbol::TwoDots
2305 }
2306 )
2307 }
2308}
2309
2310#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2312#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2313#[allow(missing_docs)]
2314#[non_exhaustive]
2315#[display("{_0}")]
2316pub enum UnOp {
2317 Minus(TokenReference),
2318 Not(TokenReference),
2319 Hash(TokenReference),
2320 #[cfg(feature = "lua53")]
2321 Tilde(TokenReference),
2322}
2323
2324impl UnOp {
2325 pub fn token(&self) -> &TokenReference {
2327 match self {
2328 UnOp::Minus(token) | UnOp::Not(token) | UnOp::Hash(token) => token,
2329 #[cfg(feature = "lua53")]
2330 UnOp::Tilde(token) => token,
2331 }
2332 }
2333
2334 pub fn precedence() -> u8 {
2337 11
2338 }
2339}
2340
2341#[derive(Clone, Debug, PartialEq, Eq)]
2343#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2344pub struct AstError {
2345 token: Token,
2347
2348 additional: Cow<'static, str>,
2350
2351 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2353 range: Option<(Position, Position)>,
2354}
2355
2356impl AstError {
2357 pub fn token(&self) -> &Token {
2359 &self.token
2360 }
2361
2362 pub fn error_message(&self) -> &str {
2364 self.additional.as_ref()
2365 }
2366
2367 pub fn range(&self) -> (Position, Position) {
2369 self.range
2370 .or_else(|| Some((self.token.start_position(), self.token.end_position())))
2371 .unwrap()
2372 }
2373}
2374
2375impl fmt::Display for AstError {
2376 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2377 let range = self.range();
2378
2379 write!(
2380 formatter,
2381 "unexpected token `{}`. (starting from line {}, character {} and ending on line {}, character {})\nadditional information: {}",
2382 self.token,
2383 range.0.line(),
2384 range.0.character(),
2385 range.1.line(),
2386 range.1.character(),
2387 self.additional,
2388 )
2389 }
2390}
2391
2392impl std::error::Error for AstError {}
2393
2394#[derive(Clone, Debug)]
2396#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2397pub struct Ast {
2398 pub(crate) nodes: Block,
2399 pub(crate) eof: TokenReference,
2400}
2401
2402impl Ast {
2403 pub fn with_nodes(self, nodes: Block) -> Self {
2405 Self { nodes, ..self }
2406 }
2407
2408 pub fn with_eof(self, eof: TokenReference) -> Self {
2410 Self { eof, ..self }
2411 }
2412
2413 pub fn nodes(&self) -> &Block {
2422 &self.nodes
2423 }
2424
2425 pub fn nodes_mut(&mut self) -> &mut Block {
2427 &mut self.nodes
2428 }
2429
2430 pub fn eof(&self) -> &TokenReference {
2432 &self.eof
2433 }
2434}
2435
2436impl fmt::Display for Ast {
2437 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2438 write!(f, "{}", self.nodes())?;
2439 write!(f, "{}", self.eof())
2440 }
2441}
2442
2443#[cfg(test)]
2444mod tests {
2445 use crate::{parse, visitors::VisitorMut};
2446
2447 use super::*;
2448
2449 #[test]
2450 fn test_with_eof_safety() {
2451 let new_ast = {
2452 let ast = parse("local foo = 1").unwrap();
2453 let eof = ast.eof().clone();
2454 ast.with_eof(eof)
2455 };
2456
2457 assert_eq!("local foo = 1", new_ast.to_string());
2458 }
2459
2460 #[test]
2461 fn test_with_nodes_safety() {
2462 let new_ast = {
2463 let ast = parse("local foo = 1").unwrap();
2464 let nodes = ast.nodes().clone();
2465 ast.with_nodes(nodes)
2466 };
2467
2468 assert_eq!(new_ast.to_string(), "local foo = 1");
2469 }
2470
2471 #[test]
2472 fn test_with_visitor_safety() {
2473 let new_ast = {
2474 let ast = parse("local foo = 1").unwrap();
2475
2476 struct SyntaxRewriter;
2477 impl VisitorMut for SyntaxRewriter {
2478 fn visit_token(&mut self, token: Token) -> Token {
2479 token
2480 }
2481 }
2482
2483 SyntaxRewriter.visit_ast(ast)
2484 };
2485
2486 assert_eq!(new_ast.to_string(), "local foo = 1");
2487 }
2488
2489 #[test]
2491 fn test_new_validity() {
2492 let token: TokenReference = TokenReference::new(
2493 Vec::new(),
2494 Token::new(TokenType::Identifier {
2495 identifier: "foo".into(),
2496 }),
2497 Vec::new(),
2498 );
2499
2500 let expression = Expression::Var(Var::Name(token.clone()));
2501
2502 Assignment::new(Punctuated::new(), Punctuated::new());
2503 Do::new();
2504 ElseIf::new(expression.clone());
2505 FunctionBody::new();
2506 FunctionCall::new(Prefix::Name(token.clone()));
2507 FunctionDeclaration::new(FunctionName::new(Punctuated::new()));
2508 GenericFor::new(Punctuated::new(), Punctuated::new());
2509 If::new(expression.clone());
2510 LocalAssignment::new(Punctuated::new());
2511 LocalFunction::new(token.clone());
2512 MethodCall::new(
2513 token.clone(),
2514 FunctionArgs::Parentheses {
2515 arguments: Punctuated::new(),
2516 parentheses: ContainedSpan::new(token.clone(), token.clone()),
2517 },
2518 );
2519 NumericFor::new(token, expression.clone(), expression.clone());
2520 Repeat::new(expression.clone());
2521 Return::new();
2522 TableConstructor::new();
2523 While::new(expression);
2524 }
2525
2526 #[test]
2527 fn test_local_assignment_print() {
2528 let block = Block::new().with_stmts(vec![(
2529 Stmt::LocalAssignment(
2530 LocalAssignment::new(
2531 std::iter::once(Pair::End(TokenReference::new(
2532 vec![],
2533 Token::new(TokenType::Identifier {
2534 identifier: "variable".into(),
2535 }),
2536 vec![],
2537 )))
2538 .collect(),
2539 )
2540 .with_equal_token(Some(TokenReference::symbol(" = ").unwrap()))
2541 .with_expressions(
2542 std::iter::once(Pair::End(Expression::Number(TokenReference::new(
2543 vec![],
2544 Token::new(TokenType::Number { text: "1".into() }),
2545 vec![],
2546 ))))
2547 .collect(),
2548 ),
2549 ),
2550 None,
2551 )]);
2552
2553 let ast = parse("").unwrap().with_nodes(block);
2554 assert_eq!(ast.to_string(), "local variable = 1");
2555 }
2556}