full_moon/ast/
mod.rs

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/// A block of statements, such as in if/do/etc block
52#[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    /// Creates an empty block
67    pub fn new() -> Self {
68        Self {
69            stmts: Vec::new(),
70            last_stmt: None,
71        }
72    }
73
74    /// An iterator over the statements in the block, such as `local foo = 1`.
75    ///
76    /// Note that this does not contain the final statement which can be
77    /// attained via [`Block::last_stmt`].
78    pub fn stmts(&self) -> impl Iterator<Item = &Stmt> {
79        self.stmts.iter().map(|(stmt, _)| stmt)
80    }
81
82    /// An iterator over the statements in the block, including any optional
83    /// semicolon token reference present
84    pub fn stmts_with_semicolon(&self) -> impl Iterator<Item = &(Stmt, Option<TokenReference>)> {
85        self.stmts.iter()
86    }
87
88    /// The last statement of the block if one exists, such as `return foo`
89    pub fn last_stmt(&self) -> Option<&LastStmt> {
90        Some(&self.last_stmt.as_ref()?.0)
91    }
92
93    /// The last statement of the block if on exists, including any optional semicolon token reference present
94    pub fn last_stmt_with_semicolon(&self) -> Option<&(LastStmt, Option<TokenReference>)> {
95        self.last_stmt.as_ref()
96    }
97
98    /// Returns a new block with the given statements
99    /// Takes a vector of statements, followed by an optional semicolon token reference
100    pub fn with_stmts(self, stmts: Vec<(Stmt, Option<TokenReference>)>) -> Self {
101        Self { stmts, ..self }
102    }
103
104    /// Returns a new block with the given last statement, if one is given
105    /// Takes an optional last statement, with an optional semicolon
106    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/// The last statement of a [`Block`]
120#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
121#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
122#[non_exhaustive]
123pub enum LastStmt {
124    /// A `break` statement
125    Break(TokenReference),
126    /// A continue statement
127    /// Only available when the "luau" feature flag is enabled.
128    #[cfg(feature = "luau")]
129    Continue(TokenReference),
130    /// A `return` statement
131    Return(Return),
132}
133
134/// A `return` statement
135#[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    /// Creates a new empty Return
145    /// Default return token is followed by a single space
146    pub fn new() -> Self {
147        Self {
148            token: TokenReference::basic_symbol("return "),
149            returns: Punctuated::new(),
150        }
151    }
152
153    /// The `return` token
154    pub fn token(&self) -> &TokenReference {
155        &self.token
156    }
157
158    /// The values being returned
159    pub fn returns(&self) -> &Punctuated<Expression> {
160        &self.returns
161    }
162
163    /// Returns a new Return with the given `return` token
164    pub fn with_token(self, token: TokenReference) -> Self {
165        Self { token, ..self }
166    }
167
168    /// Returns a new Return with the given punctuated sequence
169    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/// Fields of a [`TableConstructor`]
181#[derive(Clone, Debug, Display, PartialEq, Node)]
182#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
183#[non_exhaustive]
184pub enum Field {
185    /// A key in the format of `[expression] = value`
186    #[display(
187        "{}{}{}{}{}",
188        brackets.tokens().0,
189        key,
190        brackets.tokens().1,
191        equal,
192        value
193    )]
194    ExpressionKey {
195        /// The `[...]` part of `[expression] = value`
196        brackets: ContainedSpan,
197        /// The `expression` part of `[expression] = value`
198        key: Expression,
199        /// The `=` part of `[expression] = value`
200        equal: TokenReference,
201        /// The `value` part of `[expression] = value`
202        value: Expression,
203    },
204
205    /// A key in the format of `name = value`
206    #[display("{key}{equal}{value}")]
207    NameKey {
208        /// The `name` part of `name = value`
209        key: TokenReference,
210        /// The `=` part of `name = value`
211        equal: TokenReference,
212        /// The `value` part of `name = value`
213        value: Expression,
214    },
215
216    /// A set constructor field, such as .a inside { .a } which is equivalent to { a = true }
217    #[display("{dot}{name}")]
218    #[cfg(feature = "cfxlua")]
219    SetConstructor {
220        /// The `.` part of `.a`
221        dot: TokenReference,
222        /// The `a` part of `.a`
223        name: TokenReference,
224    },
225
226    /// A field with no key, just a value (such as `"a"` in `{ "a" }`)
227    #[display("{_0}")]
228    NoKey(Expression),
229}
230
231/// A table being constructed, such as `{ 1, 2, 3 }` or `{ a = 1 }`
232#[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    /// Creates a new empty TableConstructor
244    /// Brace tokens are followed by spaces, such that { `fields` }
245    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    /// The braces of the constructor
256    pub fn braces(&self) -> &ContainedSpan {
257        &self.braces
258    }
259
260    /// Returns the [`Punctuated`] sequence of the fields used to create the table
261    pub fn fields(&self) -> &Punctuated<Field> {
262        &self.fields
263    }
264
265    /// Returns a new TableConstructor with the given braces
266    pub fn with_braces(self, braces: ContainedSpan) -> Self {
267        Self { braces, ..self }
268    }
269
270    /// Returns a new TableConstructor with the given fields
271    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/// An anonymous function, such as `function() end`
283#[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    /// Returns a new AnonymousFunction
299    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    /// The attributes in the function, e.g. `@native`
309    #[cfg(feature = "luau")]
310    pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
311        self.attributes.iter()
312    }
313
314    /// The `function` token
315    pub fn function_token(&self) -> &TokenReference {
316        &self.function_token
317    }
318
319    /// The function body, everything except `function` in `function(a, b, c) call() end`
320    pub fn body(&self) -> &FunctionBody {
321        &self.body
322    }
323
324    /// Returns a new AnonymousFunction with the given attributes (e.g. `@native`)
325    #[cfg(feature = "luau")]
326    pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
327        Self { attributes, ..self }
328    }
329
330    /// Returns a new AnonymousFunction with the given `function` token
331    pub fn with_function_token(self, function_token: TokenReference) -> Self {
332        Self {
333            function_token,
334            ..self
335        }
336    }
337
338    /// Returns a new AnonymousFunction with the given function body
339    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/// An expression, mostly useful for getting values
351#[derive(Clone, Debug, Display, PartialEq, Node)]
352#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
353#[non_exhaustive]
354pub enum Expression {
355    /// A binary operation, such as `1 + 3`
356    #[display("{lhs}{binop}{rhs}")]
357    BinaryOperator {
358        /// The left hand side of the binary operation, the `1` part of `1 + 3`
359        lhs: Box<Expression>,
360        /// The binary operation used, the `+` part of `1 + 3`
361        binop: BinOp,
362        /// The right hand side of the binary operation, the `3` part of `1 + 3`
363        rhs: Box<Expression>,
364    },
365
366    /// A statement in parentheses, such as `(#list)`
367    #[display("{}{}{}", contained.tokens().0, expression, contained.tokens().1)]
368    Parentheses {
369        /// The parentheses of the expression
370        #[node(full_range)]
371        contained: ContainedSpan,
372        /// The expression inside the parentheses
373        expression: Box<Expression>,
374    },
375
376    /// A unary operation, such as `#list`
377    #[display("{unop}{expression}")]
378    UnaryOperator {
379        /// The unary operation, the `#` part of `#list`
380        unop: UnOp,
381        /// The expression the operation is being done on, the `list` part of `#list`
382        expression: Box<Expression>,
383    },
384
385    /// An anonymous function, such as `function() end`
386    #[display("{_0}")]
387    Function(Box<AnonymousFunction>),
388
389    /// A call of a function, such as `call()`
390    #[display("{_0}")]
391    FunctionCall(FunctionCall),
392
393    /// An if expression, such as `if foo then true else false`.
394    /// Only available when the "luau" feature flag is enabled.
395    #[cfg(feature = "luau")]
396    #[display("{_0}")]
397    IfExpression(IfExpression),
398
399    /// An interpolated string, such as `` `hello {"world"}` ``
400    /// Only available when the "luau" feature flag is enabled.
401    #[cfg(feature = "luau")]
402    #[display("{_0}")]
403    InterpolatedString(InterpolatedString),
404
405    /// A table constructor, such as `{ 1, 2, 3 }`
406    #[display("{_0}")]
407    TableConstructor(TableConstructor),
408
409    /// A number token, such as `3.3`
410    #[display("{_0}")]
411    Number(TokenReference),
412
413    /// A string token, such as `"hello"`
414    #[display("{_0}")]
415    String(TokenReference),
416
417    /// A symbol, such as `true`
418    #[display("{_0}")]
419    Symbol(TokenReference),
420
421    /// A value that has been asserted for a particular type, for use in Luau.
422    /// Only available when the "luau" feature flag is enabled.
423    #[cfg(feature = "luau")]
424    #[display("{expression}{type_assertion}")]
425    TypeAssertion {
426        /// The expression being asserted
427        expression: Box<Expression>,
428
429        /// The type assertion
430        type_assertion: TypeAssertion,
431    },
432
433    /// A more complex value, such as `call().x`
434    #[display("{_0}")]
435    Var(Var),
436}
437
438/// A statement that stands alone
439#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
440#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
441#[non_exhaustive]
442pub enum Stmt {
443    /// An assignment, such as `x = 1`
444    #[display("{_0}")]
445    Assignment(Assignment),
446    /// A do block, `do end`
447    #[display("{_0}")]
448    Do(Do),
449    /// A function call on its own, such as `call()`
450    #[display("{_0}")]
451    FunctionCall(FunctionCall),
452    /// A function declaration, such as `function x() end`
453    #[display("{_0}")]
454    FunctionDeclaration(FunctionDeclaration),
455    /// A generic for loop, such as `for index, value in pairs(list) do end`
456    #[display("{_0}")]
457    GenericFor(GenericFor),
458    /// An if statement
459    #[display("{_0}")]
460    If(If),
461    /// A local assignment, such as `local x = 1`
462    #[display("{_0}")]
463    LocalAssignment(LocalAssignment),
464    /// A local function declaration, such as `local function x() end`
465    #[display("{_0}")]
466    LocalFunction(LocalFunction),
467    /// A numeric for loop, such as `for index = 1, 10 do end`
468    #[display("{_0}")]
469    NumericFor(NumericFor),
470    /// A repeat loop
471    #[display("{_0}")]
472    Repeat(Repeat),
473    /// A while loop
474    #[display("{_0}")]
475    While(While),
476
477    /// A compound assignment, such as `+=`
478    /// Only available when the "luau" feature flag is enabled
479    #[cfg(any(feature = "luau", feature = "cfxlua"))]
480    #[display("{_0}")]
481    CompoundAssignment(CompoundAssignment),
482    /// An exported type declaration, such as `export type Meters = number`
483    /// Only available when the "luau" feature flag is enabled.
484    #[cfg(feature = "luau")]
485    ExportedTypeDeclaration(ExportedTypeDeclaration),
486    /// A type declaration, such as `type Meters = number`
487    /// Only available when the "luau" feature flag is enabled.
488    #[cfg(feature = "luau")]
489    TypeDeclaration(TypeDeclaration),
490    /// An exported type function, such as `export type function Pairs(...) end`
491    /// Only available when the "luau" feature flag is enabled.
492    #[cfg(feature = "luau")]
493    ExportedTypeFunction(ExportedTypeFunction),
494    /// A type function, such as `type function Pairs(...) end`
495    /// Only available when the "luau" feature flag is enabled.
496    #[cfg(feature = "luau")]
497    TypeFunction(TypeFunction),
498
499    /// A goto statement, such as `goto label`
500    /// Only available when the "lua52" or "luajit" feature flag is enabled.
501    #[cfg(any(feature = "lua52", feature = "luajit"))]
502    Goto(Goto),
503    /// A label, such as `::label::`
504    /// Only available when the "lua52" or "luajit" feature flag is enabled.
505    #[cfg(any(feature = "lua52", feature = "luajit"))]
506    Label(Label),
507}
508
509/// A node used before another in cases such as function calling
510/// The `("foo")` part of `("foo"):upper()`
511#[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    /// A complicated expression, such as `("foo")`
517    Expression(Box<Expression>),
518    #[display("{_0}")]
519    /// Just a name, such as `foo`
520    Name(TokenReference),
521}
522
523/// The indexing of something, such as `x.y` or `x["y"]`
524/// Values of variants are the keys, such as `"y"`
525#[derive(Clone, Debug, Display, PartialEq, Node)]
526#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
527#[non_exhaustive]
528pub enum Index {
529    /// Indexing in the form of `x["y"]`
530    #[display("{}{}{}", brackets.tokens().0, expression, brackets.tokens().1)]
531    Brackets {
532        /// The `[...]` part of `["y"]`
533        brackets: ContainedSpan,
534        /// The `"y"` part of `["y"]`
535        expression: Expression,
536    },
537
538    /// Indexing in the form of `x.y`
539    #[display("{dot}{name}")]
540    Dot {
541        /// The `.` part of `.y`
542        dot: TokenReference,
543        /// The `y` part of `.y`
544        name: TokenReference,
545    },
546}
547
548/// Arguments used for a function
549#[derive(Clone, Debug, Display, PartialEq, Node)]
550#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
551#[non_exhaustive]
552pub enum FunctionArgs {
553    /// Used when a function is called in the form of `call(1, 2, 3)`
554    #[display(
555        "{}{}{}",
556        parentheses.tokens().0,
557        arguments,
558        parentheses.tokens().1
559    )]
560    Parentheses {
561        /// The `(...) part of (1, 2, 3)`
562        #[node(full_range)]
563        parentheses: ContainedSpan,
564        /// The `1, 2, 3` part of `1, 2, 3`
565        arguments: Punctuated<Expression>,
566    },
567    /// Used when a function is called in the form of `call "foobar"`
568    #[display("{_0}")]
569    String(TokenReference),
570    /// Used when a function is called in the form of `call { 1, 2, 3 }`
571    #[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/// A numeric for loop, such as `for index = 1, 10 do end`
589#[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    /// Creates a new NumericFor from the given index variable, start, and end expressions
610    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    /// The `for` token
629    pub fn for_token(&self) -> &TokenReference {
630        &self.for_token
631    }
632
633    /// The index identity, `index` in the initial example
634    pub fn index_variable(&self) -> &TokenReference {
635        &self.index_variable
636    }
637
638    /// The `=` token
639    pub fn equal_token(&self) -> &TokenReference {
640        &self.equal_token
641    }
642
643    /// The starting point, `1` in the initial example
644    pub fn start(&self) -> &Expression {
645        &self.start
646    }
647
648    /// The comma in between the starting point and end point
649    /// for _ = 1, 10 do
650    ///          ^
651    pub fn start_end_comma(&self) -> &TokenReference {
652        &self.start_end_comma
653    }
654
655    /// The ending point, `10` in the initial example
656    pub fn end(&self) -> &Expression {
657        &self.end
658    }
659
660    /// The comma in between the ending point and limit, if one exists
661    /// for _ = 0, 10, 2 do
662    ///              ^
663    pub fn end_step_comma(&self) -> Option<&TokenReference> {
664        self.end_step_comma.as_ref()
665    }
666
667    /// The step if one exists, `2` in `for index = 0, 10, 2 do end`
668    pub fn step(&self) -> Option<&Expression> {
669        self.step.as_ref()
670    }
671
672    /// The `do` token
673    pub fn do_token(&self) -> &TokenReference {
674        &self.do_token
675    }
676
677    /// The code inside the for loop
678    pub fn block(&self) -> &Block {
679        &self.block
680    }
681
682    /// The `end` token
683    pub fn end_token(&self) -> &TokenReference {
684        &self.end_token
685    }
686
687    /// The type specifiers of the index variable
688    /// `for i: number = 1, 10 do` returns:
689    /// `Some(TypeSpecifier(number))`
690    /// Only available when the "luau" feature flag is enabled.
691    #[cfg(feature = "luau")]
692    pub fn type_specifier(&self) -> Option<&TypeSpecifier> {
693        self.type_specifier.as_ref()
694    }
695
696    /// Returns a new NumericFor with the given for token
697    pub fn with_for_token(self, for_token: TokenReference) -> Self {
698        Self { for_token, ..self }
699    }
700
701    /// Returns a new NumericFor with the given index variable
702    pub fn with_index_variable(self, index_variable: TokenReference) -> Self {
703        Self {
704            index_variable,
705            ..self
706        }
707    }
708
709    /// Returns a new NumericFor with the given `=` token
710    pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
711        Self {
712            equal_token,
713            ..self
714        }
715    }
716
717    /// Returns a new NumericFor with the given start expression
718    pub fn with_start(self, start: Expression) -> Self {
719        Self { start, ..self }
720    }
721
722    /// Returns a new NumericFor with the given comma between the start and end expressions
723    pub fn with_start_end_comma(self, start_end_comma: TokenReference) -> Self {
724        Self {
725            start_end_comma,
726            ..self
727        }
728    }
729
730    /// Returns a new NumericFor with the given end expression
731    pub fn with_end(self, end: Expression) -> Self {
732        Self { end, ..self }
733    }
734
735    /// Returns a new NumericFor with the given comma between the end and the step expressions
736    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    /// Returns a new NumericFor with the given step expression
744    pub fn with_step(self, step: Option<Expression>) -> Self {
745        Self { step, ..self }
746    }
747
748    /// Returns a new NumericFor with the given `do` token
749    pub fn with_do_token(self, do_token: TokenReference) -> Self {
750        Self { do_token, ..self }
751    }
752
753    /// Returns a new NumericFor with the given block
754    pub fn with_block(self, block: Block) -> Self {
755        Self { block, ..self }
756    }
757
758    /// Returns a new NumericFor with the given `end` token
759    pub fn with_end_token(self, end_token: TokenReference) -> Self {
760        Self { end_token, ..self }
761    }
762
763    /// Returns a new NumericFor with the given type specifiers
764    /// Only available when the "luau" feature flag is enabled.
765    #[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/// A generic for loop, such as `for index, value in pairs(list) do end`
816#[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    /// Creates a new GenericFor from the given names and expressions
836    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    /// The `for` token
851    pub fn for_token(&self) -> &TokenReference {
852        &self.for_token
853    }
854
855    /// Returns the punctuated sequence of names
856    /// In `for index, value in pairs(list) do`, iterates over `index` and `value`
857    pub fn names(&self) -> &Punctuated<TokenReference> {
858        &self.names
859    }
860
861    /// The `in` token
862    pub fn in_token(&self) -> &TokenReference {
863        &self.in_token
864    }
865
866    /// Returns the punctuated sequence of the expressions looped over
867    /// In `for index, value in pairs(list) do`, iterates over `pairs(list)`
868    pub fn expressions(&self) -> &Punctuated<Expression> {
869        &self.expr_list
870    }
871
872    /// The `do` token
873    pub fn do_token(&self) -> &TokenReference {
874        &self.do_token
875    }
876
877    /// The code inside the for loop
878    pub fn block(&self) -> &Block {
879        &self.block
880    }
881
882    /// The `end` token
883    pub fn end_token(&self) -> &TokenReference {
884        &self.end_token
885    }
886
887    /// The type specifiers of the named variables, in the order that they were assigned.
888    /// `for i, v: string in pairs() do` returns an iterator containing:
889    /// `None, Some(TypeSpecifier(string))`
890    /// Only available when the "luau" feature flag is enabled.
891    #[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    /// Returns a new GenericFor with the given `for` token
897    pub fn with_for_token(self, for_token: TokenReference) -> Self {
898        Self { for_token, ..self }
899    }
900
901    /// Returns a new GenericFor with the given names
902    pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
903        Self { names, ..self }
904    }
905
906    /// Returns a new GenericFor with the given `in` token
907    pub fn with_in_token(self, in_token: TokenReference) -> Self {
908        Self { in_token, ..self }
909    }
910
911    /// Returns a new GenericFor with the given expression list
912    pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
913        Self { expr_list, ..self }
914    }
915
916    /// Returns a new GenericFor with the given `do` token
917    pub fn with_do_token(self, do_token: TokenReference) -> Self {
918        Self { do_token, ..self }
919    }
920
921    /// Returns a new GenericFor with the given block
922    pub fn with_block(self, block: Block) -> Self {
923        Self { block, ..self }
924    }
925
926    /// Returns a new GenericFor with the given `end` token
927    pub fn with_end_token(self, end_token: TokenReference) -> Self {
928        Self { end_token, ..self }
929    }
930
931    /// Returns a new GenericFor with the given type specifiers
932    /// Only available when the "luau" feature flag is enabled.
933    #[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/// An if statement
975#[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    /// Creates a new If from the given condition
1002    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    /// The `if` token
1016    pub fn if_token(&self) -> &TokenReference {
1017        &self.if_token
1018    }
1019
1020    /// The condition of the if statement, `condition` in `if condition then`
1021    pub fn condition(&self) -> &Expression {
1022        &self.condition
1023    }
1024
1025    /// The `then` token
1026    pub fn then_token(&self) -> &TokenReference {
1027        &self.then_token
1028    }
1029
1030    /// The block inside the initial if statement
1031    pub fn block(&self) -> &Block {
1032        &self.block
1033    }
1034
1035    /// The `else` token if one exists
1036    pub fn else_token(&self) -> Option<&TokenReference> {
1037        self.else_token.as_ref()
1038    }
1039
1040    /// If there are `elseif` conditions, returns a vector of them
1041    /// Expression is the condition, block is the code if the condition is true
1042    // TODO: Make this return an iterator, and remove Option part entirely?
1043    pub fn else_if(&self) -> Option<&Vec<ElseIf>> {
1044        self.else_if.as_ref()
1045    }
1046
1047    /// The code inside an `else` block if one exists
1048    pub fn else_block(&self) -> Option<&Block> {
1049        self.r#else.as_ref()
1050    }
1051
1052    /// The `end` token
1053    pub fn end_token(&self) -> &TokenReference {
1054        &self.end_token
1055    }
1056
1057    /// Returns a new If with the given `if` token
1058    pub fn with_if_token(self, if_token: TokenReference) -> Self {
1059        Self { if_token, ..self }
1060    }
1061
1062    /// Returns a new If with the given condition
1063    pub fn with_condition(self, condition: Expression) -> Self {
1064        Self { condition, ..self }
1065    }
1066
1067    /// Returns a new If with the given `then` token
1068    pub fn with_then_token(self, then_token: TokenReference) -> Self {
1069        Self { then_token, ..self }
1070    }
1071
1072    /// Returns a new If with the given block
1073    pub fn with_block(self, block: Block) -> Self {
1074        Self { block, ..self }
1075    }
1076
1077    /// Returns a new If with the given list of `elseif` blocks
1078    pub fn with_else_if(self, else_if: Option<Vec<ElseIf>>) -> Self {
1079        Self { else_if, ..self }
1080    }
1081
1082    /// Returns a new If with the given `else` token
1083    pub fn with_else_token(self, else_token: Option<TokenReference>) -> Self {
1084        Self { else_token, ..self }
1085    }
1086
1087    /// Returns a new If with the given `else` body
1088    pub fn with_else(self, r#else: Option<Block>) -> Self {
1089        Self { r#else, ..self }
1090    }
1091
1092    /// Returns a new If with the given `end` token
1093    pub fn with_end_token(self, end_token: TokenReference) -> Self {
1094        Self { end_token, ..self }
1095    }
1096}
1097
1098/// An elseif block in a bigger [`If`] statement
1099#[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    /// Creates a new ElseIf from the given condition
1111    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    /// The `elseif` token
1121    pub fn else_if_token(&self) -> &TokenReference {
1122        &self.else_if_token
1123    }
1124
1125    /// The condition of the `elseif`, `condition` in `elseif condition then`
1126    pub fn condition(&self) -> &Expression {
1127        &self.condition
1128    }
1129
1130    /// The `then` token
1131    pub fn then_token(&self) -> &TokenReference {
1132        &self.then_token
1133    }
1134
1135    /// The body of the `elseif`
1136    pub fn block(&self) -> &Block {
1137        &self.block
1138    }
1139
1140    /// Returns a new ElseIf with the given `elseif` token
1141    pub fn with_else_if_token(self, else_if_token: TokenReference) -> Self {
1142        Self {
1143            else_if_token,
1144            ..self
1145        }
1146    }
1147
1148    /// Returns a new ElseIf with the given condition
1149    pub fn with_condition(self, condition: Expression) -> Self {
1150        Self { condition, ..self }
1151    }
1152
1153    /// Returns a new ElseIf with the given `then` token
1154    pub fn with_then_token(self, then_token: TokenReference) -> Self {
1155        Self { then_token, ..self }
1156    }
1157
1158    /// Returns a new ElseIf with the given block
1159    pub fn with_block(self, block: Block) -> Self {
1160        Self { block, ..self }
1161    }
1162}
1163
1164/// A while loop
1165#[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    /// Creates a new While from the given condition
1178    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    /// The `while` token
1189    pub fn while_token(&self) -> &TokenReference {
1190        &self.while_token
1191    }
1192
1193    /// The `condition` part of `while condition do`
1194    pub fn condition(&self) -> &Expression {
1195        &self.condition
1196    }
1197
1198    /// The `do` token
1199    pub fn do_token(&self) -> &TokenReference {
1200        &self.do_token
1201    }
1202
1203    /// The code inside the while loop
1204    pub fn block(&self) -> &Block {
1205        &self.block
1206    }
1207
1208    /// The `end` token
1209    pub fn end_token(&self) -> &TokenReference {
1210        &self.end_token
1211    }
1212
1213    /// Returns a new While with the given `while` token
1214    pub fn with_while_token(self, while_token: TokenReference) -> Self {
1215        Self {
1216            while_token,
1217            ..self
1218        }
1219    }
1220
1221    /// Returns a new While with the given condition
1222    pub fn with_condition(self, condition: Expression) -> Self {
1223        Self { condition, ..self }
1224    }
1225
1226    /// Returns a new While with the given `do` token
1227    pub fn with_do_token(self, do_token: TokenReference) -> Self {
1228        Self { do_token, ..self }
1229    }
1230
1231    /// Returns a new While with the given block
1232    pub fn with_block(self, block: Block) -> Self {
1233        Self { block, ..self }
1234    }
1235
1236    /// Returns a new While with the given `end` token
1237    pub fn with_end_token(self, end_token: TokenReference) -> Self {
1238        Self { end_token, ..self }
1239    }
1240}
1241
1242/// A repeat loop
1243#[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    /// Creates a new Repeat from the given expression to repeat until
1255    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    /// The `repeat` token
1265    pub fn repeat_token(&self) -> &TokenReference {
1266        &self.repeat_token
1267    }
1268
1269    /// The code inside the `repeat` block
1270    pub fn block(&self) -> &Block {
1271        &self.block
1272    }
1273
1274    /// The `until` token
1275    pub fn until_token(&self) -> &TokenReference {
1276        &self.until_token
1277    }
1278
1279    /// The condition for the `until` part
1280    pub fn until(&self) -> &Expression {
1281        &self.until
1282    }
1283
1284    /// Returns a new Repeat with the given `repeat` token
1285    pub fn with_repeat_token(self, repeat_token: TokenReference) -> Self {
1286        Self {
1287            repeat_token,
1288            ..self
1289        }
1290    }
1291
1292    /// Returns a new Repeat with the given block
1293    pub fn with_block(self, block: Block) -> Self {
1294        Self { block, ..self }
1295    }
1296
1297    /// Returns a new Repeat with the given `until` token
1298    pub fn with_until_token(self, until_token: TokenReference) -> Self {
1299        Self {
1300            until_token,
1301            ..self
1302        }
1303    }
1304
1305    /// Returns a new Repeat with the given `until` block
1306    pub fn with_until(self, until: Expression) -> Self {
1307        Self { until, ..self }
1308    }
1309}
1310
1311/// A method call, such as `x:y()`
1312#[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    /// Returns a new MethodCall from the given name and args
1323    pub fn new(name: TokenReference, args: FunctionArgs) -> Self {
1324        Self {
1325            colon_token: TokenReference::basic_symbol(":"),
1326            name,
1327            args,
1328        }
1329    }
1330
1331    /// The `:` in `x:y()`
1332    pub fn colon_token(&self) -> &TokenReference {
1333        &self.colon_token
1334    }
1335
1336    /// The arguments of a method call, the `x, y, z` part of `method:call(x, y, z)`
1337    pub fn args(&self) -> &FunctionArgs {
1338        &self.args
1339    }
1340
1341    /// The method being called, the `call` part of `method:call()`
1342    pub fn name(&self) -> &TokenReference {
1343        &self.name
1344    }
1345
1346    /// Returns a new MethodCall with the given `:` token
1347    pub fn with_colon_token(self, colon_token: TokenReference) -> Self {
1348        Self {
1349            colon_token,
1350            ..self
1351        }
1352    }
1353
1354    /// Returns a new MethodCall with the given name
1355    pub fn with_name(self, name: TokenReference) -> Self {
1356        Self { name, ..self }
1357    }
1358
1359    /// Returns a new MethodCall with the given args
1360    pub fn with_args(self, args: FunctionArgs) -> Self {
1361        Self { args, ..self }
1362    }
1363}
1364
1365/// Something being called
1366#[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    /// A function being called directly, such as `x(1)`
1372    AnonymousCall(FunctionArgs),
1373    #[display("{_0}")]
1374    /// A method call, such as `x:y()`
1375    MethodCall(MethodCall),
1376}
1377
1378/// A function body, everything except `function x` in `function x(a, b, c) call() end`
1379#[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    /// Returns a new empty FunctionBody
1401    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    /// The parentheses of the parameters
1424    pub fn parameters_parentheses(&self) -> &ContainedSpan {
1425        &self.parameters_parentheses
1426    }
1427
1428    /// Returns the [`Punctuated`] sequence of the parameters for the function declaration
1429    pub fn parameters(&self) -> &Punctuated<Parameter> {
1430        &self.parameters
1431    }
1432
1433    /// The code of a function body
1434    pub fn block(&self) -> &Block {
1435        &self.block
1436    }
1437
1438    /// The `end` token
1439    pub fn end_token(&self) -> &TokenReference {
1440        &self.end_token
1441    }
1442
1443    /// The generics declared for the function body.
1444    /// The `<T, U>` part of `function x<T, U>() end`
1445    /// Only available when the "luau" feature flag is enabled.
1446    #[cfg(feature = "luau")]
1447    pub fn generics(&self) -> Option<&GenericDeclaration> {
1448        self.generics.as_ref()
1449    }
1450
1451    /// The type specifiers of the variables, in the order that they were assigned.
1452    /// `(foo: number, bar, baz: boolean)` returns an iterator containing:
1453    /// `Some(TypeSpecifier(number)), None, Some(TypeSpecifier(boolean))`
1454    /// Only available when the "luau" feature flag is enabled.
1455    #[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    /// The return type of the function, if one exists.
1461    /// Only available when the "luau" feature flag is enabled.
1462    #[cfg(feature = "luau")]
1463    pub fn return_type(&self) -> Option<&TypeSpecifier> {
1464        self.return_type.as_ref()
1465    }
1466
1467    /// Returns a new FunctionBody with the given parentheses for the parameters
1468    pub fn with_parameters_parentheses(self, parameters_parentheses: ContainedSpan) -> Self {
1469        Self {
1470            parameters_parentheses,
1471            ..self
1472        }
1473    }
1474
1475    /// Returns a new FunctionBody with the given parameters
1476    pub fn with_parameters(self, parameters: Punctuated<Parameter>) -> Self {
1477        Self { parameters, ..self }
1478    }
1479
1480    /// Returns a new FunctionBody with the given generics declaration
1481    #[cfg(feature = "luau")]
1482    pub fn with_generics(self, generics: Option<GenericDeclaration>) -> Self {
1483        Self { generics, ..self }
1484    }
1485
1486    /// Returns a new FunctionBody with the given type specifiers
1487    #[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    /// Returns a new FunctionBody with the given return type
1496    #[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    /// Returns a new FunctionBody with the given block
1505    pub fn with_block(self, block: Block) -> Self {
1506        Self { block, ..self }
1507    }
1508
1509    /// Returns a new FunctionBody with the given `end` token
1510    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/// A parameter in a function declaration
1552#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
1553#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1554#[non_exhaustive]
1555pub enum Parameter {
1556    /// The `...` vararg syntax, such as `function x(...)`
1557    Ellipsis(TokenReference),
1558    /// A name parameter, such as `function x(a, b, c)`
1559    Name(TokenReference),
1560}
1561
1562/// A suffix in certain cases, such as `:y()` in `x:y()`
1563/// Can be stacked on top of each other, such as in `x()()()`
1564#[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    /// A call, including method calls and direct calls
1570    Call(Call),
1571    #[display("{_0}")]
1572    /// An index, such as `x.y`
1573    Index(Index),
1574}
1575
1576/// A complex expression used by [`Var`], consisting of both a prefix and suffixes
1577#[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    /// Returns a new VarExpression from the given prefix
1587    pub fn new(prefix: Prefix) -> Self {
1588        Self {
1589            prefix,
1590            suffixes: Vec::new(),
1591        }
1592    }
1593
1594    /// The prefix of the expression, such as a name
1595    pub fn prefix(&self) -> &Prefix {
1596        &self.prefix
1597    }
1598
1599    /// An iter over the suffixes, such as indexing or calling
1600    pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
1601        self.suffixes.iter()
1602    }
1603
1604    /// Returns a new VarExpression with the given prefix
1605    pub fn with_prefix(self, prefix: Prefix) -> Self {
1606        Self { prefix, ..self }
1607    }
1608
1609    /// Returns a new VarExpression with the given suffixes
1610    pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
1611        Self { suffixes, ..self }
1612    }
1613}
1614
1615/// Used in [`Assignment`s](Assignment) and [`Value`s](Value)
1616#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1617#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1618#[non_exhaustive]
1619pub enum Var {
1620    /// An expression, such as `x.y.z` or `x()`
1621    #[display("{_0}")]
1622    Expression(Box<VarExpression>),
1623    /// A literal identifier, such as `x`
1624    #[display("{_0}")]
1625    Name(TokenReference),
1626}
1627
1628/// An assignment, such as `x = y`. Not used for [`LocalAssignment`s](LocalAssignment)
1629#[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    /// Returns a new Assignment from the given variable and expression list
1640    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    /// Returns the punctuated sequence over the expressions being assigned.
1649    /// This is the the `1, 2` part of `x, y["a"] = 1, 2`
1650    pub fn expressions(&self) -> &Punctuated<Expression> {
1651        &self.expr_list
1652    }
1653
1654    /// The `=` token in between `x = y`
1655    pub fn equal_token(&self) -> &TokenReference {
1656        &self.equal_token
1657    }
1658
1659    /// Returns the punctuated sequence over the variables being assigned to.
1660    /// This is the `x, y["a"]` part of `x, y["a"] = 1, 2`
1661    pub fn variables(&self) -> &Punctuated<Var> {
1662        &self.var_list
1663    }
1664
1665    /// Returns a new Assignment with the given variables
1666    pub fn with_variables(self, var_list: Punctuated<Var>) -> Self {
1667        Self { var_list, ..self }
1668    }
1669
1670    /// Returns a new Assignment with the given `=` token
1671    pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
1672        Self {
1673            equal_token,
1674            ..self
1675        }
1676    }
1677
1678    /// Returns a new Assignment with the given expressions
1679    pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1680        Self { expr_list, ..self }
1681    }
1682}
1683
1684/// A declaration of a local function, such as `local function x() end`
1685#[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    /// Returns a new LocalFunction from the given name
1713    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    /// The attributes in the function, e.g. `@native`
1725    #[cfg(feature = "luau")]
1726    pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
1727        self.attributes.iter()
1728    }
1729
1730    /// The `local` token
1731    pub fn local_token(&self) -> &TokenReference {
1732        &self.local_token
1733    }
1734
1735    /// The `function` token
1736    pub fn function_token(&self) -> &TokenReference {
1737        &self.function_token
1738    }
1739
1740    /// The function body, everything except `local function x` in `local function x(a, b, c) call() end`
1741    pub fn body(&self) -> &FunctionBody {
1742        &self.body
1743    }
1744
1745    /// The name of the function, the `x` part of `local function x() end`
1746    pub fn name(&self) -> &TokenReference {
1747        &self.name
1748    }
1749
1750    /// Returns a new LocalFunction with the given attributes (e.g. `@native`)
1751    #[cfg(feature = "luau")]
1752    pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
1753        Self { attributes, ..self }
1754    }
1755
1756    /// Returns a new LocalFunction with the given `local` token
1757    pub fn with_local_token(self, local_token: TokenReference) -> Self {
1758        Self {
1759            local_token,
1760            ..self
1761        }
1762    }
1763
1764    /// Returns a new LocalFunction with the given `function` token
1765    pub fn with_function_token(self, function_token: TokenReference) -> Self {
1766        Self {
1767            function_token,
1768            ..self
1769        }
1770    }
1771
1772    /// Returns a new LocalFunction with the given name
1773    pub fn with_name(self, name: TokenReference) -> Self {
1774        Self { name, ..self }
1775    }
1776
1777    /// Returns a new LocalFunction with the given function body
1778    pub fn with_body(self, body: FunctionBody) -> Self {
1779        Self { body, ..self }
1780    }
1781}
1782
1783/// An assignment to a local variable, such as `local x = 1`
1784#[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    /// Returns a new LocalAssignment from the given name list
1807    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    /// The `local` token
1821    pub fn local_token(&self) -> &TokenReference {
1822        &self.local_token
1823    }
1824
1825    /// The `=` token in between `local x = y`, if one exists
1826    pub fn equal_token(&self) -> Option<&TokenReference> {
1827        self.equal_token.as_ref()
1828    }
1829
1830    /// Returns the punctuated sequence of the expressions being assigned.
1831    /// This is the `1, 2` part of `local x, y = 1, 2`
1832    pub fn expressions(&self) -> &Punctuated<Expression> {
1833        &self.expr_list
1834    }
1835
1836    /// Returns the punctuated sequence of names being assigned to.
1837    /// This is the `x, y` part of `local x, y = 1, 2`
1838    pub fn names(&self) -> &Punctuated<TokenReference> {
1839        &self.name_list
1840    }
1841
1842    /// The type specifiers of the variables, in the order that they were assigned.
1843    /// `local foo: number, bar, baz: boolean` returns an iterator containing:
1844    /// `Some(TypeSpecifier(number)), None, Some(TypeSpecifier(boolean))`
1845    /// Only available when the "luau" feature flag is enabled.
1846    #[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    /// The attributes specified for the variables, in the order that they were assigned.
1852    /// `local foo <const>, bar, baz <close>` returns an iterator containing:
1853    /// `Some(Attribute("const")), None, Some(Attribute("close"))`
1854    /// Only available when the "lua54" feature flag is enabled.
1855    #[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    /// Returns a new LocalAssignment with the given `local` token
1861    pub fn with_local_token(self, local_token: TokenReference) -> Self {
1862        Self {
1863            local_token,
1864            ..self
1865        }
1866    }
1867
1868    /// Returns a new LocalAssignment with the given type specifiers
1869    #[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    /// Returns a new LocalAssignment with the given attributes
1878    #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1879    pub fn with_attributes(self, attributes: Vec<Option<Attribute>>) -> Self {
1880        Self { attributes, ..self }
1881    }
1882
1883    /// Returns a new LocalAssignment with the given name list
1884    pub fn with_names(self, name_list: Punctuated<TokenReference>) -> Self {
1885        Self { name_list, ..self }
1886    }
1887
1888    /// Returns a new LocalAssignment with the given `=` token
1889    pub fn with_equal_token(self, equal_token: Option<TokenReference>) -> Self {
1890        Self {
1891            equal_token,
1892            ..self
1893        }
1894    }
1895
1896    /// Returns a new LocalAssignment with the given expression list
1897    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/// A `do` block, such as `do ... end`
1925/// This is not used for things like `while true do end`, only those on their own
1926#[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    /// Creates an empty Do
1937    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    /// The `do` token
1946    pub fn do_token(&self) -> &TokenReference {
1947        &self.do_token
1948    }
1949
1950    /// The code inside the `do ... end`
1951    pub fn block(&self) -> &Block {
1952        &self.block
1953    }
1954
1955    /// The `end` token
1956    pub fn end_token(&self) -> &TokenReference {
1957        &self.end_token
1958    }
1959
1960    /// Returns a new Do with the given `do` token
1961    pub fn with_do_token(self, do_token: TokenReference) -> Self {
1962        Self { do_token, ..self }
1963    }
1964
1965    /// Returns a new Do with the given block
1966    pub fn with_block(self, block: Block) -> Self {
1967        Self { block, ..self }
1968    }
1969
1970    /// Returns a new Do with the given `end` token
1971    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/// A function being called, such as `call()`
1983#[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    /// Creates a new FunctionCall from the given prefix
1993    /// Sets the suffixes such that the return is `prefixes()`
1994    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    /// The prefix of a function call, the `call` part of `call()`
2010    pub fn prefix(&self) -> &Prefix {
2011        &self.prefix
2012    }
2013
2014    /// The suffix of a function call, the `()` part of `call()`
2015    pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
2016        self.suffixes.iter()
2017    }
2018
2019    /// Returns a new FunctionCall with the given prefix
2020    pub fn with_prefix(self, prefix: Prefix) -> Self {
2021        Self { prefix, ..self }
2022    }
2023
2024    /// Returns a new FunctionCall with the given suffixes
2025    pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
2026        Self { suffixes, ..self }
2027    }
2028}
2029
2030/// A function name when being declared as [`FunctionDeclaration`]
2031#[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    /// Creates a new FunctionName from the given list of names
2046    pub fn new(names: Punctuated<TokenReference>) -> Self {
2047        Self {
2048            names,
2049            colon_name: None,
2050        }
2051    }
2052
2053    /// The colon between the name and the method, the `:` part of `function x:y() end`
2054    pub fn method_colon(&self) -> Option<&TokenReference> {
2055        Some(&self.colon_name.as_ref()?.0)
2056    }
2057
2058    /// A method name if one exists, the `y` part of `function x:y() end`
2059    pub fn method_name(&self) -> Option<&TokenReference> {
2060        Some(&self.colon_name.as_ref()?.1)
2061    }
2062
2063    /// Returns the punctuated sequence over the names used when defining the function.
2064    /// This is the `x.y.z` part of `function x.y.z() end`
2065    pub fn names(&self) -> &Punctuated<TokenReference> {
2066        &self.names
2067    }
2068
2069    /// Returns a new FunctionName with the given names
2070    pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
2071        Self { names, ..self }
2072    }
2073
2074    /// Returns a new FunctionName with the given method name
2075    /// The first token is the colon, and the second token is the method name itself
2076    pub fn with_method(self, method: Option<(TokenReference, TokenReference)>) -> Self {
2077        Self {
2078            colon_name: method,
2079            ..self
2080        }
2081    }
2082}
2083
2084/// A normal function declaration, supports simple declarations like `function x() end`
2085/// as well as complicated declarations such as `function x.y.z:a() end`
2086#[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    /// Creates a new FunctionDeclaration from the given name
2103    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    /// The attributes in the function, e.g. `@native`
2114    #[cfg(feature = "luau")]
2115    pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
2116        self.attributes.iter()
2117    }
2118
2119    /// The `function` token
2120    pub fn function_token(&self) -> &TokenReference {
2121        &self.function_token
2122    }
2123
2124    /// The body of the function
2125    pub fn body(&self) -> &FunctionBody {
2126        &self.body
2127    }
2128
2129    /// The name of the function
2130    pub fn name(&self) -> &FunctionName {
2131        &self.name
2132    }
2133
2134    /// Returns a new FunctionDeclaration with the given attributes (e.g. `@native`)
2135    #[cfg(feature = "luau")]
2136    pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
2137        Self { attributes, ..self }
2138    }
2139
2140    /// Returns a new FunctionDeclaration with the given `function` token
2141    pub fn with_function_token(self, function_token: TokenReference) -> Self {
2142        Self {
2143            function_token,
2144            ..self
2145        }
2146    }
2147
2148    /// Returns a new FunctionDeclaration with the given function name
2149    pub fn with_name(self, name: FunctionName) -> Self {
2150        Self { name, ..self }
2151    }
2152
2153    /// Returns a new FunctionDeclaration with the given function body
2154    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                /// The precedence of non-unary operator. The larger the number, the higher the precedence.
2185                /// Shares the same precedence table as unary operators.
2186                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                /// The token associated with this operator
2205                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    /// The precedence of the operator. The larger the number, the higher the precedence.
2286    /// See more at <http://www.lua.org/manual/5.1/manual.html#2.5.6>
2287    pub fn precedence(&self) -> u8 {
2288        BinOp::precedence_of_token(self.token()).expect("invalid token")
2289    }
2290
2291    /// Whether the operator is right associative. If not, it is left associative.
2292    /// See more at <https://www.lua.org/pil/3.5.html>
2293    pub fn is_right_associative(&self) -> bool {
2294        matches!(*self, BinOp::Caret(_) | BinOp::TwoDots(_))
2295    }
2296
2297    /// Given a token, returns whether it is a right associative binary operator.
2298    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/// Operators that require just one operand, such as #X
2311#[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    /// The token associated with the operator
2326    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    /// The precedence of unary operator. The larger the number, the higher the precedence.
2335    /// Shares the same precedence table as binary operators.
2336    pub fn precedence() -> u8 {
2337        11
2338    }
2339}
2340
2341/// An error that occurs when creating the AST.
2342#[derive(Clone, Debug, PartialEq, Eq)]
2343#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2344pub struct AstError {
2345    /// The token that caused the error
2346    token: Token,
2347
2348    /// Any additional information that could be provided for debugging
2349    additional: Cow<'static, str>,
2350
2351    /// If set, this is the complete range of the error
2352    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2353    range: Option<(Position, Position)>,
2354}
2355
2356impl AstError {
2357    /// Returns the token that caused the error
2358    pub fn token(&self) -> &Token {
2359        &self.token
2360    }
2361
2362    /// Returns a human readable error message
2363    pub fn error_message(&self) -> &str {
2364        self.additional.as_ref()
2365    }
2366
2367    /// Returns the range of the error
2368    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/// An abstract syntax tree, contains all the nodes used in the code
2395#[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    /// Returns a new Ast with the given nodes
2404    pub fn with_nodes(self, nodes: Block) -> Self {
2405        Self { nodes, ..self }
2406    }
2407
2408    /// Returns a new Ast with the given EOF token
2409    pub fn with_eof(self, eof: TokenReference) -> Self {
2410        Self { eof, ..self }
2411    }
2412
2413    /// The entire code of the function
2414    ///
2415    /// ```rust
2416    /// # fn main() -> Result<(), Vec<full_moon::Error>> {
2417    /// assert_eq!(full_moon::parse("local x = 1; local y = 2")?.nodes().stmts().count(), 2);
2418    /// # Ok(())
2419    /// # }
2420    /// ```
2421    pub fn nodes(&self) -> &Block {
2422        &self.nodes
2423    }
2424
2425    /// The entire code of the function, but mutable
2426    pub fn nodes_mut(&mut self) -> &mut Block {
2427        &mut self.nodes
2428    }
2429
2430    /// The EOF token at the end of every Ast
2431    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    // Tests AST nodes with new methods that call unwrap
2490    #[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}