1 #[macro_use]
2 mod parser_util;
3 mod parsers;
4 pub mod punctuated;
5 pub mod span;
6 mod update_positions;
7 mod visitors;
8 
9 use crate::{
10     tokenizer::{Symbol, Token, TokenReference, TokenType},
11     util::*,
12 };
13 use derive_more::Display;
14 use full_moon_derive::{Node, Visit};
15 
16 #[cfg(feature = "serde")]
17 use serde::{Deserialize, Serialize};
18 use std::{borrow::Cow, fmt};
19 
20 use parser_util::{
21     InternalAstError, OneOrMore, Parser, ParserState, ZeroOrMore, ZeroOrMoreDelimited,
22 };
23 
24 use punctuated::{Pair, Punctuated};
25 use span::ContainedSpan;
26 
27 #[cfg(feature = "roblox")]
28 pub mod types;
29 #[cfg(feature = "roblox")]
30 use types::*;
31 
32 #[cfg(feature = "roblox")]
33 mod type_visitors;
34 
35 #[cfg(feature = "lua52")]
36 pub mod lua52;
37 #[cfg(feature = "lua52")]
38 use lua52::*;
39 
40 /// A block of statements, such as in if/do/etc block
41 #[derive(Clone, Debug, Default, Display, PartialEq, Node, Visit)]
42 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
43 #[display(
44     fmt = "{}{}",
45     "display_optional_punctuated_vec(stmts)",
46     "display_option(&last_stmt.as_ref().map(display_optional_punctuated))"
47 )]
48 pub struct Block {
49     stmts: Vec<(Stmt, Option<TokenReference>)>,
50     #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
51     last_stmt: Option<(LastStmt, Option<TokenReference>)>,
52 }
53 
54 impl Block {
55     /// Creates an empty block
new() -> Self56     pub fn new() -> Self {
57         Self {
58             stmts: Vec::new(),
59             last_stmt: None,
60         }
61     }
62 
63     /// An iterator over the statements in the block, such as `local foo = 1`
stmts(&self) -> impl Iterator<Item = &Stmt>64     pub fn stmts(&self) -> impl Iterator<Item = &Stmt> {
65         self.stmts.iter().map(|(stmt, _)| stmt)
66     }
67 
68     /// An iterator over the statements in the block, including any optional
69     /// semicolon token reference present
stmts_with_semicolon(&self) -> impl Iterator<Item = &(Stmt, Option<TokenReference>)>70     pub fn stmts_with_semicolon(&self) -> impl Iterator<Item = &(Stmt, Option<TokenReference>)> {
71         self.stmts.iter()
72     }
73 
74     /// The last statement of the block if one exists, such as `return foo`
last_stmt(&self) -> Option<&LastStmt>75     pub fn last_stmt(&self) -> Option<&LastStmt> {
76         Some(&self.last_stmt.as_ref()?.0)
77     }
78 
79     /// The last statement of the block if on exists, including any optional semicolon token reference present
last_stmt_with_semicolon(&self) -> Option<&(LastStmt, Option<TokenReference>)>80     pub fn last_stmt_with_semicolon(&self) -> Option<&(LastStmt, Option<TokenReference>)> {
81         self.last_stmt.as_ref()
82     }
83 
84     /// Returns a new block with the given statements
85     /// Takes a vector of statements, followed by an optional semicolon token reference
with_stmts(self, stmts: Vec<(Stmt, Option<TokenReference>)>) -> Self86     pub fn with_stmts(self, stmts: Vec<(Stmt, Option<TokenReference>)>) -> Self {
87         Self { stmts, ..self }
88     }
89 
90     /// Returns a new block with the given last statement, if one is given
91     /// Takes an optional last statement, with an optional semicolon
with_last_stmt(self, last_stmt: Option<(LastStmt, Option<TokenReference>)>) -> Self92     pub fn with_last_stmt(self, last_stmt: Option<(LastStmt, Option<TokenReference>)>) -> Self {
93         Self { last_stmt, ..self }
94     }
95 }
96 
97 /// The last statement of a [`Block`]
98 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
99 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
100 #[non_exhaustive]
101 pub enum LastStmt {
102     /// A `break` statement
103     Break(TokenReference),
104     /// A continue statement
105     /// Only available when the "roblox" feature flag is enabled.
106     #[cfg(feature = "roblox")]
107     Continue(TokenReference),
108     /// A `return` statement
109     Return(Return),
110 }
111 
112 /// A `return` statement
113 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
114 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
115 #[display(fmt = "{}{}", token, returns)]
116 pub struct Return {
117     token: TokenReference,
118     returns: Punctuated<Expression>,
119 }
120 
121 impl Return {
122     /// Creates a new empty Return
123     /// Default return token is followed by a single space
new() -> Self124     pub fn new() -> Self {
125         Self {
126             token: TokenReference::symbol("return ").unwrap(),
127             returns: Punctuated::new(),
128         }
129     }
130 
131     /// The `return` token
token(&self) -> &TokenReference132     pub fn token(&self) -> &TokenReference {
133         &self.token
134     }
135 
136     /// The values being returned
returns(&self) -> &Punctuated<Expression>137     pub fn returns(&self) -> &Punctuated<Expression> {
138         &self.returns
139     }
140 
141     /// Returns a new Return with the given `return` token
with_token(self, token: TokenReference) -> Self142     pub fn with_token(self, token: TokenReference) -> Self {
143         Self { token, ..self }
144     }
145 
146     /// Returns a new Return with the given punctuated sequence
with_returns(self, returns: Punctuated<Expression>) -> Self147     pub fn with_returns(self, returns: Punctuated<Expression>) -> Self {
148         Self { returns, ..self }
149     }
150 }
151 
152 impl Default for Return {
default() -> Self153     fn default() -> Self {
154         Self::new()
155     }
156 }
157 
158 /// Fields of a [`TableConstructor`]
159 #[derive(Clone, Debug, Display, PartialEq, Node)]
160 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
161 #[non_exhaustive]
162 pub enum Field {
163     /// A key in the format of `[expression] = value`
164     #[display(
165         fmt = "{}{}{}{}{}",
166         "brackets.tokens().0",
167         "key",
168         "brackets.tokens().1",
169         "equal",
170         "value"
171     )]
172     ExpressionKey {
173         /// The `[...]` part of `[expression] = value`
174         brackets: ContainedSpan,
175         /// The `expression` part of `[expression] = value`
176         key: Expression,
177         /// The `=` part of `[expression] = value`
178         equal: TokenReference,
179         /// The `value` part of `[expression] = value`
180         value: Expression,
181     },
182 
183     /// A key in the format of `name = value`
184     #[display(fmt = "{}{}{}", "key", "equal", "value")]
185     NameKey {
186         /// The `name` part of `name = value`
187         key: TokenReference,
188         /// The `=` part of `name = value`
189         equal: TokenReference,
190         /// The `value` part of `name = value`
191         value: Expression,
192     },
193 
194     /// A field with no key, just a value (such as `"a"` in `{ "a" }`)
195     #[display(fmt = "{}", "_0")]
196     NoKey(Expression),
197 }
198 
199 /// A table being constructed, such as `{ 1, 2, 3 }` or `{ a = 1 }`
200 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
201 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
202 #[display(fmt = "{}{}{}", "braces.tokens().0", "fields", "braces.tokens().1")]
203 pub struct TableConstructor {
204     #[node(full_range)]
205     #[visit(contains = "fields")]
206     braces: ContainedSpan,
207     fields: Punctuated<Field>,
208 }
209 
210 impl TableConstructor {
211     /// Creates a new empty TableConstructor
212     /// Brace tokens are followed by spaces, such that { `fields` }
new() -> Self213     pub fn new() -> Self {
214         Self {
215             braces: ContainedSpan::new(
216                 TokenReference::symbol("{ ").unwrap(),
217                 TokenReference::symbol(" }").unwrap(),
218             ),
219             fields: Punctuated::new(),
220         }
221     }
222 
223     /// The braces of the constructor
braces(&self) -> &ContainedSpan224     pub fn braces(&self) -> &ContainedSpan {
225         &self.braces
226     }
227 
228     /// Returns the [`Punctuated`] sequence of the fields used to create the table
fields(&self) -> &Punctuated<Field>229     pub fn fields(&self) -> &Punctuated<Field> {
230         &self.fields
231     }
232 
233     /// Returns a new TableConstructor with the given braces
with_braces(self, braces: ContainedSpan) -> Self234     pub fn with_braces(self, braces: ContainedSpan) -> Self {
235         Self { braces, ..self }
236     }
237 
238     /// Returns a new TableConstructor with the given fields
with_fields(self, fields: Punctuated<Field>) -> Self239     pub fn with_fields(self, fields: Punctuated<Field>) -> Self {
240         Self { fields, ..self }
241     }
242 }
243 
244 impl Default for TableConstructor {
default() -> Self245     fn default() -> Self {
246         Self::new()
247     }
248 }
249 
250 /// An expression, mostly useful for getting values
251 #[derive(Clone, Debug, Display, PartialEq, Node)]
252 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
253 #[cfg_attr(feature = "serde", serde(untagged))]
254 #[non_exhaustive]
255 pub enum Expression {
256     /// A binary operation, such as `1 + 3`
257     #[display(fmt = "{}{}{}", "lhs", "binop", "rhs")]
258     BinaryOperator {
259         /// The left hand side of the binary operation, the `1` part of `1 + 3`
260         lhs: Box<Expression>,
261         /// The binary operation used, the `+` part of `1 + 3`
262         binop: BinOp,
263         /// The right hand side of the binary operation, the `3` part of `1 + 3`
264         rhs: Box<Expression>,
265     },
266 
267     /// A statement in parentheses, such as `(#list)`
268     #[display(
269         fmt = "{}{}{}",
270         "contained.tokens().0",
271         "expression",
272         "contained.tokens().1"
273     )]
274     Parentheses {
275         /// The parentheses of the `ParenExpression`
276         #[node(full_range)]
277         contained: ContainedSpan,
278         /// The expression inside the parentheses
279         expression: Box<Expression>,
280     },
281 
282     /// A unary operation, such as `#list`
283     #[display(fmt = "{}{}", "unop", "expression")]
284     UnaryOperator {
285         /// The unary operation, the `#` part of `#list`
286         unop: UnOp,
287         /// The expression the operation is being done on, the `list` part of `#list`
288         expression: Box<Expression>,
289     },
290 
291     /// A value, such as "strings"
292     #[cfg_attr(not(feature = "roblox"), display(fmt = "{}", value))]
293     #[cfg_attr(
294         feature = "roblox",
295         display(fmt = "{}{}", value, "display_option(type_assertion)")
296     )]
297     Value {
298         /// The value itself
299         value: Box<Value>,
300         /// What the value is being asserted as using `::`.
301         /// Only available when the "roblox" feature flag is enabled.
302         #[cfg(feature = "roblox")]
303         #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
304         type_assertion: Option<TypeAssertion>,
305     },
306 }
307 
308 /// Values that cannot be used standalone, but as part of things such as [`Stmt`]
309 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
310 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
311 #[non_exhaustive]
312 pub enum Value {
313     /// An anonymous function, such as `function() end)`
314     #[display(fmt = "{}{}", "_0.0", "_0.1")]
315     Function((TokenReference, FunctionBody)),
316     /// A call of a function, such as `call()`
317     #[display(fmt = "{}", "_0")]
318     FunctionCall(FunctionCall),
319     /// A table constructor, such as `{ 1, 2, 3 }`
320     #[display(fmt = "{}", "_0")]
321     TableConstructor(TableConstructor),
322     /// A number token, such as `3.3`
323     #[display(fmt = "{}", "_0")]
324     Number(TokenReference),
325     /// An expression between parentheses, such as `(3 + 2)`
326     #[display(fmt = "{}", "_0")]
327     ParenthesesExpression(Expression),
328     /// A string token, such as `"hello"`
329     #[display(fmt = "{}", "_0")]
330     String(TokenReference),
331     /// A symbol, such as `true`
332     #[display(fmt = "{}", "_0")]
333     Symbol(TokenReference),
334     /// A more complex value, such as `call().x`
335     #[display(fmt = "{}", "_0")]
336     Var(Var),
337 }
338 
339 /// A statement that stands alone
340 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
341 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
342 #[non_exhaustive]
343 pub enum Stmt {
344     /// An assignment, such as `x = 1`
345     #[display(fmt = "{}", _0)]
346     Assignment(Assignment),
347     /// A do block, `do end`
348     #[display(fmt = "{}", _0)]
349     Do(Do),
350     /// A function call on its own, such as `call()`
351     #[display(fmt = "{}", _0)]
352     FunctionCall(FunctionCall),
353     /// A function declaration, such as `function x() end`
354     #[display(fmt = "{}", _0)]
355     FunctionDeclaration(FunctionDeclaration),
356     /// A generic for loop, such as `for index, value in pairs(list) do end`
357     #[display(fmt = "{}", _0)]
358     GenericFor(GenericFor),
359     /// An if statement
360     #[display(fmt = "{}", _0)]
361     If(If),
362     /// A local assignment, such as `local x = 1`
363     #[display(fmt = "{}", _0)]
364     LocalAssignment(LocalAssignment),
365     /// A local function declaration, such as `local function x() end`
366     #[display(fmt = "{}", _0)]
367     LocalFunction(LocalFunction),
368     /// A numeric for loop, such as `for index = 1, 10 do end`
369     #[display(fmt = "{}", _0)]
370     NumericFor(NumericFor),
371     /// A repeat loop
372     #[display(fmt = "{}", _0)]
373     Repeat(Repeat),
374     /// A while loop
375     #[display(fmt = "{}", _0)]
376     While(While),
377 
378     /// A compound assignment, such as `+=`
379     /// Only available when the "roblox" feature flag is enabled
380     #[cfg(feature = "roblox")]
381     #[display(fmt = "{}", _0)]
382     CompoundAssignment(CompoundAssignment),
383     /// An exported type declaration, such as `export type Meters = number`
384     /// Only available when the "roblox" feature flag is enabled.
385     #[cfg(feature = "roblox")]
386     ExportedTypeDeclaration(ExportedTypeDeclaration),
387     /// A type declaration, such as `type Meters = number`
388     /// Only available when the "roblox" feature flag is enabled.
389     #[cfg(feature = "roblox")]
390     TypeDeclaration(TypeDeclaration),
391 
392     /// A goto statement, such as `goto label`
393     /// Only available when the "lua52" feature flag is enabled.
394     #[cfg(feature = "lua52")]
395     Goto(Goto),
396     /// A label, such as `::label::`
397     /// Only available when the "lua52" feature flag is enabled.
398     #[cfg(feature = "lua52")]
399     Label(Label),
400 }
401 
402 /// A node used before another in cases such as function calling
403 /// The `("foo")` part of `("foo"):upper()`
404 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
405 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
406 #[non_exhaustive]
407 pub enum Prefix {
408     #[display(fmt = "{}", _0)]
409     /// A complicated expression, such as `("foo")`
410     Expression(Expression),
411     #[display(fmt = "{}", _0)]
412     /// Just a name, such as `foo`
413     Name(TokenReference),
414 }
415 
416 /// The indexing of something, such as `x.y` or `x["y"]`
417 /// Values of variants are the keys, such as `"y"`
418 #[derive(Clone, Debug, Display, PartialEq, Node)]
419 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
420 #[non_exhaustive]
421 pub enum Index {
422     /// Indexing in the form of `x["y"]`
423     #[display(
424         fmt = "{}{}{}",
425         "brackets.tokens().0",
426         "expression",
427         "brackets.tokens().1"
428     )]
429     Brackets {
430         /// The `[...]` part of `["y"]`
431         brackets: ContainedSpan,
432         /// The `"y"` part of `["y"]`
433         expression: Expression,
434     },
435 
436     /// Indexing in the form of `x.y`
437     #[display(fmt = "{}{}", "dot", "name")]
438     Dot {
439         /// The `.` part of `.y`
440         dot: TokenReference,
441         /// The `y` part of `.y`
442         name: TokenReference,
443     },
444 }
445 
446 /// Arguments used for a function
447 #[derive(Clone, Debug, Display, PartialEq, Node)]
448 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
449 #[non_exhaustive]
450 pub enum FunctionArgs {
451     /// Used when a function is called in the form of `call(1, 2, 3)`
452     #[display(
453         fmt = "{}{}{}",
454         "parentheses.tokens().0",
455         "arguments",
456         "parentheses.tokens().1"
457     )]
458     Parentheses {
459         /// The `(...) part of (1, 2, 3)`
460         #[node(full_range)]
461         parentheses: ContainedSpan,
462         /// The `1, 2, 3` part of `1, 2, 3`
463         arguments: Punctuated<Expression>,
464     },
465     /// Used when a function is called in the form of `call "foobar"`
466     #[display(fmt = "{}", "_0")]
467     String(TokenReference),
468     /// Used when a function is called in the form of `call { 1, 2, 3 }`
469     #[display(fmt = "{}", "_0")]
470     TableConstructor(TableConstructor),
471 }
472 
473 /// A numeric for loop, such as `for index = 1, 10 do end`
474 #[derive(Clone, Debug, PartialEq, Node)]
475 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
476 pub struct NumericFor {
477     for_token: TokenReference,
478     index_variable: TokenReference,
479     equal_token: TokenReference,
480     start: Expression,
481     start_end_comma: TokenReference,
482     end: Expression,
483     end_step_comma: Option<TokenReference>,
484     step: Option<Expression>,
485     do_token: TokenReference,
486     block: Block,
487     end_token: TokenReference,
488     #[cfg(feature = "roblox")]
489     type_specifier: Option<TypeSpecifier>,
490 }
491 
492 impl NumericFor {
493     /// Creates a new NumericFor from the given index variable, start, and end expressions
new(index_variable: TokenReference, start: Expression, end: Expression) -> Self494     pub fn new(index_variable: TokenReference, start: Expression, end: Expression) -> Self {
495         Self {
496             for_token: TokenReference::symbol("for ").unwrap(),
497             index_variable,
498             equal_token: TokenReference::symbol(" = ").unwrap(),
499             start,
500             start_end_comma: TokenReference::symbol(", ").unwrap(),
501             end,
502             end_step_comma: None,
503             step: None,
504             do_token: TokenReference::symbol(" do\n").unwrap(),
505             block: Block::new(),
506             end_token: TokenReference::symbol("\nend").unwrap(),
507             #[cfg(feature = "roblox")]
508             type_specifier: None,
509         }
510     }
511 
512     /// The `for` token
for_token(&self) -> &TokenReference513     pub fn for_token(&self) -> &TokenReference {
514         &self.for_token
515     }
516 
517     /// The index identity, `index` in the initial example
index_variable(&self) -> &TokenReference518     pub fn index_variable(&self) -> &TokenReference {
519         &self.index_variable
520     }
521 
522     /// The `=` token
equal_token(&self) -> &TokenReference523     pub fn equal_token(&self) -> &TokenReference {
524         &self.equal_token
525     }
526 
527     /// The starting point, `1` in the initial example
start(&self) -> &Expression528     pub fn start(&self) -> &Expression {
529         &self.start
530     }
531 
532     /// The comma in between the starting point and end point
533     /// for _ = 1, 10 do
534     ///          ^
start_end_comma(&self) -> &TokenReference535     pub fn start_end_comma(&self) -> &TokenReference {
536         &self.start_end_comma
537     }
538 
539     /// The ending point, `10` in the initial example
end(&self) -> &Expression540     pub fn end(&self) -> &Expression {
541         &self.end
542     }
543 
544     /// The comma in between the ending point and limit, if one exists
545     /// for _ = 0, 10, 2 do
546     ///              ^
end_step_comma(&self) -> Option<&TokenReference>547     pub fn end_step_comma(&self) -> Option<&TokenReference> {
548         self.end_step_comma.as_ref()
549     }
550 
551     /// The step if one exists, `2` in `for index = 0, 10, 2 do end`
step(&self) -> Option<&Expression>552     pub fn step(&self) -> Option<&Expression> {
553         self.step.as_ref()
554     }
555 
556     /// The `do` token
do_token(&self) -> &TokenReference557     pub fn do_token(&self) -> &TokenReference {
558         &self.do_token
559     }
560 
561     /// The code inside the for loop
block(&self) -> &Block562     pub fn block(&self) -> &Block {
563         &self.block
564     }
565 
566     /// The `end` token
end_token(&self) -> &TokenReference567     pub fn end_token(&self) -> &TokenReference {
568         &self.end_token
569     }
570 
571     /// The type specifiers of the index variable
572     /// `for i: number = 1, 10 do` returns:
573     /// `Some(TypeSpecifier(number))`
574     /// Only available when the "roblox" feature flag is enabled.
575     #[cfg(feature = "roblox")]
type_specifier(&self) -> Option<&TypeSpecifier>576     pub fn type_specifier(&self) -> Option<&TypeSpecifier> {
577         self.type_specifier.as_ref()
578     }
579 
580     /// Returns a new NumericFor with the given for token
with_for_token(self, for_token: TokenReference) -> Self581     pub fn with_for_token(self, for_token: TokenReference) -> Self {
582         Self { for_token, ..self }
583     }
584 
585     /// Returns a new NumericFor with the given index variable
with_index_variable(self, index_variable: TokenReference) -> Self586     pub fn with_index_variable(self, index_variable: TokenReference) -> Self {
587         Self {
588             index_variable,
589             ..self
590         }
591     }
592 
593     /// Returns a new NumericFor with the given `=` token
with_equal_token(self, equal_token: TokenReference) -> Self594     pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
595         Self {
596             equal_token,
597             ..self
598         }
599     }
600 
601     /// Returns a new NumericFor with the given start expression
with_start(self, start: Expression) -> Self602     pub fn with_start(self, start: Expression) -> Self {
603         Self { start, ..self }
604     }
605 
606     /// Returns a new NumericFor with the given comma between the start and end expressions
with_start_end_comma(self, start_end_comma: TokenReference) -> Self607     pub fn with_start_end_comma(self, start_end_comma: TokenReference) -> Self {
608         Self {
609             start_end_comma,
610             ..self
611         }
612     }
613 
614     /// Returns a new NumericFor with the given end expression
with_end(self, end: Expression) -> Self615     pub fn with_end(self, end: Expression) -> Self {
616         Self { end, ..self }
617     }
618 
619     /// Returns a new NumericFor with the given comma between the end and the step expressions
with_end_step_comma(self, end_step_comma: Option<TokenReference>) -> Self620     pub fn with_end_step_comma(self, end_step_comma: Option<TokenReference>) -> Self {
621         Self {
622             end_step_comma,
623             ..self
624         }
625     }
626 
627     /// Returns a new NumericFor with the given step expression
with_step(self, step: Option<Expression>) -> Self628     pub fn with_step(self, step: Option<Expression>) -> Self {
629         Self { step, ..self }
630     }
631 
632     /// Returns a new NumericFor with the given `do` token
with_do_token(self, do_token: TokenReference) -> Self633     pub fn with_do_token(self, do_token: TokenReference) -> Self {
634         Self { do_token, ..self }
635     }
636 
637     /// Returns a new NumericFor with the given block
with_block(self, block: Block) -> Self638     pub fn with_block(self, block: Block) -> Self {
639         Self { block, ..self }
640     }
641 
642     /// Returns a new NumericFor with the given `end` token
with_end_token(self, end_token: TokenReference) -> Self643     pub fn with_end_token(self, end_token: TokenReference) -> Self {
644         Self { end_token, ..self }
645     }
646 
647     /// Returns a new NumericFor with the given type specifiers
648     /// Only available when the "roblox" feature flag is enabled.
649     #[cfg(feature = "roblox")]
with_type_specifier(self, type_specifier: Option<TypeSpecifier>) -> Self650     pub fn with_type_specifier(self, type_specifier: Option<TypeSpecifier>) -> Self {
651         Self {
652             type_specifier,
653             ..self
654         }
655     }
656 }
657 
658 impl fmt::Display for NumericFor {
659     #[cfg(feature = "roblox")]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result660     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
661         write!(
662             formatter,
663             "{}{}{}{}{}{}{}{}{}{}{}{}",
664             self.for_token,
665             self.index_variable,
666             display_option(self.type_specifier()),
667             self.equal_token,
668             self.start,
669             self.start_end_comma,
670             self.end,
671             display_option(self.end_step_comma()),
672             display_option(self.step()),
673             self.do_token,
674             self.block,
675             self.end_token,
676         )
677     }
678 
679     #[cfg(not(feature = "roblox"))]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result680     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
681         write!(
682             formatter,
683             "{}{}{}{}{}{}{}{}{}{}{}",
684             self.for_token,
685             self.index_variable,
686             self.equal_token,
687             self.start,
688             self.start_end_comma,
689             self.end,
690             display_option(self.end_step_comma()),
691             display_option(self.step()),
692             self.do_token,
693             self.block,
694             self.end_token,
695         )
696     }
697 }
698 
699 /// A generic for loop, such as `for index, value in pairs(list) do end`
700 #[derive(Clone, Debug, PartialEq, Node)]
701 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
702 pub struct GenericFor {
703     for_token: TokenReference,
704     names: Punctuated<TokenReference>,
705     in_token: TokenReference,
706     expr_list: Punctuated<Expression>,
707     do_token: TokenReference,
708     block: Block,
709     end_token: TokenReference,
710     #[cfg(feature = "roblox")]
711     type_specifiers: Vec<Option<TypeSpecifier>>,
712 }
713 
714 impl GenericFor {
715     /// Creates a new GenericFor from the given names and expressions
new(names: Punctuated<TokenReference>, expr_list: Punctuated<Expression>) -> Self716     pub fn new(names: Punctuated<TokenReference>, expr_list: Punctuated<Expression>) -> Self {
717         Self {
718             for_token: TokenReference::symbol("for ").unwrap(),
719             names,
720             in_token: TokenReference::symbol(" in ").unwrap(),
721             expr_list,
722             do_token: TokenReference::symbol(" do\n").unwrap(),
723             block: Block::new(),
724             end_token: TokenReference::symbol("\nend").unwrap(),
725             #[cfg(feature = "roblox")]
726             type_specifiers: Vec::new(),
727         }
728     }
729 
730     /// The `for` token
for_token(&self) -> &TokenReference731     pub fn for_token(&self) -> &TokenReference {
732         &self.for_token
733     }
734 
735     /// Returns the punctuated sequence of names
736     /// In `for index, value in pairs(list) do`, iterates over `index` and `value`
names(&self) -> &Punctuated<TokenReference>737     pub fn names(&self) -> &Punctuated<TokenReference> {
738         &self.names
739     }
740 
741     /// The `in` token
in_token(&self) -> &TokenReference742     pub fn in_token(&self) -> &TokenReference {
743         &self.in_token
744     }
745 
746     /// Returns the punctuated sequence of the expressions looped over
747     /// In `for index, value in pairs(list) do`, iterates over `pairs(list)`
expressions(&self) -> &Punctuated<Expression>748     pub fn expressions(&self) -> &Punctuated<Expression> {
749         &self.expr_list
750     }
751 
752     /// The `do` token
do_token(&self) -> &TokenReference753     pub fn do_token(&self) -> &TokenReference {
754         &self.do_token
755     }
756 
757     /// The code inside the for loop
block(&self) -> &Block758     pub fn block(&self) -> &Block {
759         &self.block
760     }
761 
762     /// The `end` token
end_token(&self) -> &TokenReference763     pub fn end_token(&self) -> &TokenReference {
764         &self.end_token
765     }
766 
767     /// The type specifiers of the named variables, in the order that they were assigned.
768     /// `for i, v: string in pairs() do` returns an iterator containing:
769     /// `None, Some(TypeSpecifier(string))`
770     /// Only available when the "roblox" feature flag is enabled.
771     #[cfg(feature = "roblox")]
type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>>772     pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
773         self.type_specifiers.iter().map(Option::as_ref)
774     }
775 
776     /// Returns a new GenericFor with the given `for` token
with_for_token(self, for_token: TokenReference) -> Self777     pub fn with_for_token(self, for_token: TokenReference) -> Self {
778         Self { for_token, ..self }
779     }
780 
781     /// Returns a new GenericFor with the given names
with_names(self, names: Punctuated<TokenReference>) -> Self782     pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
783         Self { names, ..self }
784     }
785 
786     /// Returns a new GenericFor with the given `in` token
with_in_token(self, in_token: TokenReference) -> Self787     pub fn with_in_token(self, in_token: TokenReference) -> Self {
788         Self { in_token, ..self }
789     }
790 
791     /// Returns a new GenericFor with the given expression list
with_expressions(self, expr_list: Punctuated<Expression>) -> Self792     pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
793         Self { expr_list, ..self }
794     }
795 
796     /// Returns a new GenericFor with the given `do` token
with_do_token(self, do_token: TokenReference) -> Self797     pub fn with_do_token(self, do_token: TokenReference) -> Self {
798         Self { do_token, ..self }
799     }
800 
801     /// Returns a new GenericFor with the given block
with_block(self, block: Block) -> Self802     pub fn with_block(self, block: Block) -> Self {
803         Self { block, ..self }
804     }
805 
806     /// Returns a new GenericFor with the given `end` token
with_end_token(self, end_token: TokenReference) -> Self807     pub fn with_end_token(self, end_token: TokenReference) -> Self {
808         Self { end_token, ..self }
809     }
810 
811     /// Returns a new GenericFor with the given type specifiers
812     /// Only available when the "roblox" feature flag is enabled.
813     #[cfg(feature = "roblox")]
with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self814     pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
815         Self {
816             type_specifiers,
817             ..self
818         }
819     }
820 }
821 
822 impl fmt::Display for GenericFor {
823     #[cfg(feature = "roblox")]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result824     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
825         write!(
826             formatter,
827             "{}{}{}{}{}{}{}",
828             self.for_token,
829             join_type_specifiers(&self.names, self.type_specifiers()),
830             self.in_token,
831             self.expr_list,
832             self.do_token,
833             self.block,
834             self.end_token
835         )
836     }
837 
838     #[cfg(not(feature = "roblox"))]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result839     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
840         write!(
841             formatter,
842             "{}{}{}{}{}{}{}",
843             self.for_token,
844             self.names,
845             self.in_token,
846             self.expr_list,
847             self.do_token,
848             self.block,
849             self.end_token
850         )
851     }
852 }
853 
854 /// An if statement
855 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
856 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
857 #[display(
858     fmt = "{}{}{}{}{}{}{}{}",
859     "if_token",
860     "condition",
861     "then_token",
862     "block",
863     "display_option(else_if.as_ref().map(join_vec))",
864     "display_option(else_token)",
865     "display_option(r#else)",
866     "end_token"
867 )]
868 pub struct If {
869     if_token: TokenReference,
870     condition: Expression,
871     then_token: TokenReference,
872     block: Block,
873     else_if: Option<Vec<ElseIf>>,
874     else_token: Option<TokenReference>,
875     #[cfg_attr(feature = "serde", serde(rename = "else"))]
876     r#else: Option<Block>,
877     end_token: TokenReference,
878 }
879 
880 impl If {
881     /// Creates a new If from the given condition
new(condition: Expression) -> Self882     pub fn new(condition: Expression) -> Self {
883         Self {
884             if_token: TokenReference::symbol("if ").unwrap(),
885             condition,
886             then_token: TokenReference::symbol(" then").unwrap(),
887             block: Block::new(),
888             else_if: None,
889             else_token: None,
890             r#else: None,
891             end_token: TokenReference::symbol("\nend").unwrap(),
892         }
893     }
894 
895     /// The `if` token
if_token(&self) -> &TokenReference896     pub fn if_token(&self) -> &TokenReference {
897         &self.if_token
898     }
899 
900     /// The condition of the if statement, `condition` in `if condition then`
condition(&self) -> &Expression901     pub fn condition(&self) -> &Expression {
902         &self.condition
903     }
904 
905     /// The `then` token
then_token(&self) -> &TokenReference906     pub fn then_token(&self) -> &TokenReference {
907         &self.then_token
908     }
909 
910     /// The block inside the initial if statement
block(&self) -> &Block911     pub fn block(&self) -> &Block {
912         &self.block
913     }
914 
915     /// The `else` token if one exists
else_token(&self) -> Option<&TokenReference>916     pub fn else_token(&self) -> Option<&TokenReference> {
917         self.else_token.as_ref()
918     }
919 
920     /// If there are `elseif` conditions, returns a vector of them
921     /// Expression is the condition, block is the code if the condition is true
922     // TODO: Make this return an iterator, and remove Option part entirely?
else_if(&self) -> Option<&Vec<ElseIf>>923     pub fn else_if(&self) -> Option<&Vec<ElseIf>> {
924         self.else_if.as_ref()
925     }
926 
927     /// The code inside an `else` block if one exists
else_block(&self) -> Option<&Block>928     pub fn else_block(&self) -> Option<&Block> {
929         self.r#else.as_ref()
930     }
931 
932     /// The `end` token
end_token(&self) -> &TokenReference933     pub fn end_token(&self) -> &TokenReference {
934         &self.end_token
935     }
936 
937     /// Returns a new If with the given `if` token
with_if_token(self, if_token: TokenReference) -> Self938     pub fn with_if_token(self, if_token: TokenReference) -> Self {
939         Self { if_token, ..self }
940     }
941 
942     /// Returns a new If with the given condition
with_condition(self, condition: Expression) -> Self943     pub fn with_condition(self, condition: Expression) -> Self {
944         Self { condition, ..self }
945     }
946 
947     /// Returns a new If with the given `then` token
with_then_token(self, then_token: TokenReference) -> Self948     pub fn with_then_token(self, then_token: TokenReference) -> Self {
949         Self { then_token, ..self }
950     }
951 
952     /// Returns a new If with the given block
with_block(self, block: Block) -> Self953     pub fn with_block(self, block: Block) -> Self {
954         Self { block, ..self }
955     }
956 
957     /// Returns a new If with the given list of `elseif` blocks
with_else_if(self, else_if: Option<Vec<ElseIf>>) -> Self958     pub fn with_else_if(self, else_if: Option<Vec<ElseIf>>) -> Self {
959         Self { else_if, ..self }
960     }
961 
962     /// Returns a new If with the given `else` token
with_else_token(self, else_token: Option<TokenReference>) -> Self963     pub fn with_else_token(self, else_token: Option<TokenReference>) -> Self {
964         Self { else_token, ..self }
965     }
966 
967     /// Returns a new If with the given `else` body
with_else(self, r#else: Option<Block>) -> Self968     pub fn with_else(self, r#else: Option<Block>) -> Self {
969         Self { r#else, ..self }
970     }
971 
972     /// Returns a new If with the given `end` token
with_end_token(self, end_token: TokenReference) -> Self973     pub fn with_end_token(self, end_token: TokenReference) -> Self {
974         Self { end_token, ..self }
975     }
976 }
977 
978 /// An elseif block in a bigger [`If`] statement
979 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
980 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
981 #[display(fmt = "{}{}{}{}", "else_if_token", "condition", "then_token", "block")]
982 pub struct ElseIf {
983     else_if_token: TokenReference,
984     condition: Expression,
985     then_token: TokenReference,
986     block: Block,
987 }
988 
989 impl ElseIf {
990     /// Creates a new ElseIf from the given condition
new(condition: Expression) -> Self991     pub fn new(condition: Expression) -> Self {
992         Self {
993             else_if_token: TokenReference::symbol("elseif ").unwrap(),
994             condition,
995             then_token: TokenReference::symbol(" then\n").unwrap(),
996             block: Block::new(),
997         }
998     }
999 
1000     /// The `elseif` token
else_if_token(&self) -> &TokenReference1001     pub fn else_if_token(&self) -> &TokenReference {
1002         &self.else_if_token
1003     }
1004 
1005     /// The condition of the `elseif`, `condition` in `elseif condition then`
condition(&self) -> &Expression1006     pub fn condition(&self) -> &Expression {
1007         &self.condition
1008     }
1009 
1010     /// The `then` token
then_token(&self) -> &TokenReference1011     pub fn then_token(&self) -> &TokenReference {
1012         &self.then_token
1013     }
1014 
1015     /// The body of the `elseif`
block(&self) -> &Block1016     pub fn block(&self) -> &Block {
1017         &self.block
1018     }
1019 
1020     /// Returns a new ElseIf with the given `elseif` token
with_else_if_token(self, else_if_token: TokenReference) -> Self1021     pub fn with_else_if_token(self, else_if_token: TokenReference) -> Self {
1022         Self {
1023             else_if_token,
1024             ..self
1025         }
1026     }
1027 
1028     /// Returns a new ElseIf with the given condition
with_condition(self, condition: Expression) -> Self1029     pub fn with_condition(self, condition: Expression) -> Self {
1030         Self { condition, ..self }
1031     }
1032 
1033     /// Returns a new ElseIf with the given `then` token
with_then_token(self, then_token: TokenReference) -> Self1034     pub fn with_then_token(self, then_token: TokenReference) -> Self {
1035         Self { then_token, ..self }
1036     }
1037 
1038     /// Returns a new ElseIf with the given block
with_block(self, block: Block) -> Self1039     pub fn with_block(self, block: Block) -> Self {
1040         Self { block, ..self }
1041     }
1042 }
1043 
1044 /// A while loop
1045 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1046 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1047 #[display(
1048     fmt = "{}{}{}{}{}",
1049     "while_token",
1050     "condition",
1051     "do_token",
1052     "block",
1053     "end_token"
1054 )]
1055 pub struct While {
1056     while_token: TokenReference,
1057     condition: Expression,
1058     do_token: TokenReference,
1059     block: Block,
1060     end_token: TokenReference,
1061 }
1062 
1063 impl While {
1064     /// Creates a new While from the given condition
new(condition: Expression) -> Self1065     pub fn new(condition: Expression) -> Self {
1066         Self {
1067             while_token: TokenReference::symbol("while ").unwrap(),
1068             condition,
1069             do_token: TokenReference::symbol(" do\n").unwrap(),
1070             block: Block::new(),
1071             end_token: TokenReference::symbol("end\n").unwrap(),
1072         }
1073     }
1074 
1075     /// The `while` token
while_token(&self) -> &TokenReference1076     pub fn while_token(&self) -> &TokenReference {
1077         &self.while_token
1078     }
1079 
1080     /// The `condition` part of `while condition do`
condition(&self) -> &Expression1081     pub fn condition(&self) -> &Expression {
1082         &self.condition
1083     }
1084 
1085     /// The `do` token
do_token(&self) -> &TokenReference1086     pub fn do_token(&self) -> &TokenReference {
1087         &self.do_token
1088     }
1089 
1090     /// The code inside the while loop
block(&self) -> &Block1091     pub fn block(&self) -> &Block {
1092         &self.block
1093     }
1094 
1095     /// The `end` token
end_token(&self) -> &TokenReference1096     pub fn end_token(&self) -> &TokenReference {
1097         &self.end_token
1098     }
1099 
1100     /// Returns a new While with the given `while` token
with_while_token(self, while_token: TokenReference) -> Self1101     pub fn with_while_token(self, while_token: TokenReference) -> Self {
1102         Self {
1103             while_token,
1104             ..self
1105         }
1106     }
1107 
1108     /// Returns a new While with the given condition
with_condition(self, condition: Expression) -> Self1109     pub fn with_condition(self, condition: Expression) -> Self {
1110         Self { condition, ..self }
1111     }
1112 
1113     /// Returns a new While with the given `do` token
with_do_token(self, do_token: TokenReference) -> Self1114     pub fn with_do_token(self, do_token: TokenReference) -> Self {
1115         Self { do_token, ..self }
1116     }
1117 
1118     /// Returns a new While with the given block
with_block(self, block: Block) -> Self1119     pub fn with_block(self, block: Block) -> Self {
1120         Self { block, ..self }
1121     }
1122 
1123     /// Returns a new While with the given `end` token
with_end_token(self, end_token: TokenReference) -> Self1124     pub fn with_end_token(self, end_token: TokenReference) -> Self {
1125         Self { end_token, ..self }
1126     }
1127 }
1128 
1129 /// A repeat loop
1130 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1131 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1132 #[display(fmt = "{}{}{}{}", "repeat_token", "block", "until_token", "until")]
1133 pub struct Repeat {
1134     repeat_token: TokenReference,
1135     block: Block,
1136     until_token: TokenReference,
1137     until: Expression,
1138 }
1139 
1140 impl Repeat {
1141     /// Creates a new Repeat from the given expression to repeat until
new(until: Expression) -> Self1142     pub fn new(until: Expression) -> Self {
1143         Self {
1144             repeat_token: TokenReference::symbol("repeat\n").unwrap(),
1145             block: Block::new(),
1146             until_token: TokenReference::symbol("\nuntil ").unwrap(),
1147             until,
1148         }
1149     }
1150 
1151     /// The `repeat` token
repeat_token(&self) -> &TokenReference1152     pub fn repeat_token(&self) -> &TokenReference {
1153         &self.repeat_token
1154     }
1155 
1156     /// The code inside the `repeat` block
block(&self) -> &Block1157     pub fn block(&self) -> &Block {
1158         &self.block
1159     }
1160 
1161     /// The `until` token
until_token(&self) -> &TokenReference1162     pub fn until_token(&self) -> &TokenReference {
1163         &self.until_token
1164     }
1165 
1166     /// The condition for the `until` part
until(&self) -> &Expression1167     pub fn until(&self) -> &Expression {
1168         &self.until
1169     }
1170 
1171     /// Returns a new Repeat with the given `repeat` token
with_repeat_token(self, repeat_token: TokenReference) -> Self1172     pub fn with_repeat_token(self, repeat_token: TokenReference) -> Self {
1173         Self {
1174             repeat_token,
1175             ..self
1176         }
1177     }
1178 
1179     /// Returns a new Repeat with the given block
with_block(self, block: Block) -> Self1180     pub fn with_block(self, block: Block) -> Self {
1181         Self { block, ..self }
1182     }
1183 
1184     /// Returns a new Repeat with the given `until` token
with_until_token(self, until_token: TokenReference) -> Self1185     pub fn with_until_token(self, until_token: TokenReference) -> Self {
1186         Self {
1187             until_token,
1188             ..self
1189         }
1190     }
1191 
1192     /// Returns a new Repeat with the given `until` block
with_until(self, until: Expression) -> Self1193     pub fn with_until(self, until: Expression) -> Self {
1194         Self { until, ..self }
1195     }
1196 }
1197 
1198 /// A method call, such as `x:y()`
1199 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1200 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1201 #[display(fmt = "{}{}{}", "colon_token", "name", "args")]
1202 pub struct MethodCall {
1203     colon_token: TokenReference,
1204     name: TokenReference,
1205     args: FunctionArgs,
1206 }
1207 
1208 impl MethodCall {
1209     /// Returns a new MethodCall from the given name and args
new(name: TokenReference, args: FunctionArgs) -> Self1210     pub fn new(name: TokenReference, args: FunctionArgs) -> Self {
1211         Self {
1212             colon_token: TokenReference::symbol(":").unwrap(),
1213             name,
1214             args,
1215         }
1216     }
1217 
1218     /// The `:` in `x:y()`
colon_token(&self) -> &TokenReference1219     pub fn colon_token(&self) -> &TokenReference {
1220         &self.colon_token
1221     }
1222 
1223     /// The arguments of a method call, the `x, y, z` part of `method:call(x, y, z)`
args(&self) -> &FunctionArgs1224     pub fn args(&self) -> &FunctionArgs {
1225         &self.args
1226     }
1227 
1228     /// The method being called, the `call` part of `method:call()`
name(&self) -> &TokenReference1229     pub fn name(&self) -> &TokenReference {
1230         &self.name
1231     }
1232 
1233     /// Returns a new MethodCall with the given `:` token
with_colon_token(self, colon_token: TokenReference) -> Self1234     pub fn with_colon_token(self, colon_token: TokenReference) -> Self {
1235         Self {
1236             colon_token,
1237             ..self
1238         }
1239     }
1240 
1241     /// Returns a new MethodCall with the given name
with_name(self, name: TokenReference) -> Self1242     pub fn with_name(self, name: TokenReference) -> Self {
1243         Self { name, ..self }
1244     }
1245 
1246     /// Returns a new MethodCall with the given args
with_args(self, args: FunctionArgs) -> Self1247     pub fn with_args(self, args: FunctionArgs) -> Self {
1248         Self { args, ..self }
1249     }
1250 }
1251 
1252 /// Something being called
1253 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1254 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1255 #[non_exhaustive]
1256 pub enum Call {
1257     #[display(fmt = "{}", "_0")]
1258     /// A function being called directly, such as `x(1)`
1259     AnonymousCall(FunctionArgs),
1260     #[display(fmt = "{}", "_0")]
1261     /// A method call, such as `x:y()`
1262     MethodCall(MethodCall),
1263 }
1264 
1265 /// A function body, everything except `function x` in `function x(a, b, c) call() end`
1266 #[derive(Clone, Debug, PartialEq, Node)]
1267 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1268 pub struct FunctionBody {
1269     parameters_parentheses: ContainedSpan,
1270     parameters: Punctuated<Parameter>,
1271 
1272     #[cfg(feature = "roblox")]
1273     type_specifiers: Vec<Option<TypeSpecifier>>,
1274 
1275     #[cfg(feature = "roblox")]
1276     #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1277     return_type: Option<TypeSpecifier>,
1278 
1279     block: Block,
1280     end_token: TokenReference,
1281 }
1282 
1283 impl FunctionBody {
1284     /// Returns a new empty FunctionBody
new() -> Self1285     pub fn new() -> Self {
1286         Self {
1287             parameters_parentheses: ContainedSpan::new(
1288                 TokenReference::symbol("(").unwrap(),
1289                 TokenReference::symbol(")").unwrap(),
1290             ),
1291             parameters: Punctuated::new(),
1292 
1293             #[cfg(feature = "roblox")]
1294             type_specifiers: Vec::new(),
1295 
1296             #[cfg(feature = "roblox")]
1297             return_type: None,
1298 
1299             block: Block::new(),
1300             end_token: TokenReference::symbol("\nend").unwrap(),
1301         }
1302     }
1303 
1304     /// The parentheses of the parameters
parameters_parentheses(&self) -> &ContainedSpan1305     pub fn parameters_parentheses(&self) -> &ContainedSpan {
1306         &self.parameters_parentheses
1307     }
1308 
1309     /// Returns the [`Punctuated`] sequence of the parameters for the function declaration
parameters(&self) -> &Punctuated<Parameter>1310     pub fn parameters(&self) -> &Punctuated<Parameter> {
1311         &self.parameters
1312     }
1313 
1314     /// The code of a function body
block(&self) -> &Block1315     pub fn block(&self) -> &Block {
1316         &self.block
1317     }
1318 
1319     /// The `end` token
end_token(&self) -> &TokenReference1320     pub fn end_token(&self) -> &TokenReference {
1321         &self.end_token
1322     }
1323 
1324     /// The type specifiers of the variables, in the order that they were assigned.
1325     /// `(foo: number, bar, baz: boolean)` returns an iterator containing:
1326     /// `Some(TypeSpecifier(number)), None, Some(TypeSpecifier(boolean))`
1327     /// Only available when the "roblox" feature flag is enabled.
1328     #[cfg(feature = "roblox")]
type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>>1329     pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1330         self.type_specifiers.iter().map(Option::as_ref)
1331     }
1332 
1333     /// The return type of the function, if one exists.
1334     /// Only available when the "roblox" feature flag is enabled.
1335     #[cfg(feature = "roblox")]
return_type(&self) -> Option<&TypeSpecifier>1336     pub fn return_type(&self) -> Option<&TypeSpecifier> {
1337         self.return_type.as_ref()
1338     }
1339 
1340     /// Returns a new FunctionBody with the given parentheses for the parameters
with_parameters_parentheses(self, parameters_parentheses: ContainedSpan) -> Self1341     pub fn with_parameters_parentheses(self, parameters_parentheses: ContainedSpan) -> Self {
1342         Self {
1343             parameters_parentheses,
1344             ..self
1345         }
1346     }
1347 
1348     /// Returns a new FunctionBody with the given parameters
with_parameters(self, parameters: Punctuated<Parameter>) -> Self1349     pub fn with_parameters(self, parameters: Punctuated<Parameter>) -> Self {
1350         Self { parameters, ..self }
1351     }
1352 
1353     /// Returns a new FunctionBody with the given type specifiers
1354     #[cfg(feature = "roblox")]
with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self1355     pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1356         Self {
1357             type_specifiers,
1358             ..self
1359         }
1360     }
1361 
1362     /// Returns a new FunctionBody with the given return type
1363     #[cfg(feature = "roblox")]
with_return_type(self, return_type: Option<TypeSpecifier>) -> Self1364     pub fn with_return_type(self, return_type: Option<TypeSpecifier>) -> Self {
1365         Self {
1366             return_type,
1367             ..self
1368         }
1369     }
1370 
1371     /// Returns a new FunctionBody with the given block
with_block(self, block: Block) -> Self1372     pub fn with_block(self, block: Block) -> Self {
1373         Self { block, ..self }
1374     }
1375 
1376     /// Returns a new FunctionBody with the given `end` token
with_end_token(self, end_token: TokenReference) -> Self1377     pub fn with_end_token(self, end_token: TokenReference) -> Self {
1378         Self { end_token, ..self }
1379     }
1380 }
1381 
1382 impl Default for FunctionBody {
default() -> Self1383     fn default() -> Self {
1384         Self::new()
1385     }
1386 }
1387 
1388 impl fmt::Display for FunctionBody {
1389     #[cfg(feature = "roblox")]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result1390     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1391         write!(
1392             formatter,
1393             "{}{}{}{}{}{}",
1394             self.parameters_parentheses.tokens().0,
1395             join_type_specifiers(&self.parameters, self.type_specifiers()),
1396             self.parameters_parentheses.tokens().1,
1397             display_option(self.return_type.as_ref()),
1398             self.block,
1399             self.end_token
1400         )
1401     }
1402 
1403     #[cfg(not(feature = "roblox"))]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result1404     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1405         write!(
1406             formatter,
1407             "{}{}{}{}{}",
1408             self.parameters_parentheses.tokens().0,
1409             self.parameters,
1410             self.parameters_parentheses.tokens().1,
1411             self.block,
1412             self.end_token
1413         )
1414     }
1415 }
1416 
1417 /// A parameter in a function declaration
1418 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1419 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1420 #[non_exhaustive]
1421 pub enum Parameter {
1422     /// The `...` vararg syntax, such as `function x(...)`
1423     Ellipse(TokenReference),
1424     /// A name parameter, such as `function x(a, b, c)`
1425     Name(TokenReference),
1426 }
1427 
1428 /// A suffix in certain cases, such as `:y()` in `x:y()`
1429 /// Can be stacked on top of each other, such as in `x()()()`
1430 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1431 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1432 #[non_exhaustive]
1433 pub enum Suffix {
1434     #[display(fmt = "{}", "_0")]
1435     /// A call, including method calls and direct calls
1436     Call(Call),
1437     #[display(fmt = "{}", "_0")]
1438     /// An index, such as `x.y`
1439     Index(Index),
1440 }
1441 
1442 /// A complex expression used by [`Var`], consisting of both a prefix and suffixes
1443 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1444 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1445 #[display(fmt = "{}{}", "prefix", "join_vec(suffixes)")]
1446 pub struct VarExpression {
1447     prefix: Prefix,
1448     suffixes: Vec<Suffix>,
1449 }
1450 
1451 impl VarExpression {
1452     /// Returns a new VarExpression from the given prefix
new(prefix: Prefix) -> Self1453     pub fn new(prefix: Prefix) -> Self {
1454         Self {
1455             prefix,
1456             suffixes: Vec::new(),
1457         }
1458     }
1459 
1460     /// The prefix of the expression, such as a name
prefix(&self) -> &Prefix1461     pub fn prefix(&self) -> &Prefix {
1462         &self.prefix
1463     }
1464 
1465     /// An iter over the suffixes, such as indexing or calling
suffixes(&self) -> impl Iterator<Item = &Suffix>1466     pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
1467         self.suffixes.iter()
1468     }
1469 
1470     /// Returns a new VarExpression with the given prefix
with_prefix(self, prefix: Prefix) -> Self1471     pub fn with_prefix(self, prefix: Prefix) -> Self {
1472         Self { prefix, ..self }
1473     }
1474 
1475     /// Returns a new VarExpression with the given suffixes
with_suffixes(self, suffixes: Vec<Suffix>) -> Self1476     pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
1477         Self { suffixes, ..self }
1478     }
1479 }
1480 
1481 /// Used in [`Assignment`s](Assignment) and [`Value`s](Value)
1482 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1483 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1484 #[non_exhaustive]
1485 pub enum Var {
1486     /// An expression, such as `x.y.z` or `x()`
1487     #[display(fmt = "{}", "_0")]
1488     Expression(VarExpression),
1489     /// A literal identifier, such as `x`
1490     #[display(fmt = "{}", "_0")]
1491     Name(TokenReference),
1492 }
1493 
1494 /// An assignment, such as `x = y`. Not used for [`LocalAssignment`s](LocalAssignment)
1495 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1496 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1497 #[display(fmt = "{}{}{}", "var_list", "equal_token", "expr_list")]
1498 pub struct Assignment {
1499     var_list: Punctuated<Var>,
1500     equal_token: TokenReference,
1501     expr_list: Punctuated<Expression>,
1502 }
1503 
1504 impl Assignment {
1505     /// Returns a new Assignment from the given variable and expression list
new(var_list: Punctuated<Var>, expr_list: Punctuated<Expression>) -> Self1506     pub fn new(var_list: Punctuated<Var>, expr_list: Punctuated<Expression>) -> Self {
1507         Self {
1508             var_list,
1509             equal_token: TokenReference::symbol(" = ").unwrap(),
1510             expr_list,
1511         }
1512     }
1513 
1514     /// Returns the punctuated sequence over the expressions being assigned.
1515     /// This is the the `1, 2` part of `x, y["a"] = 1, 2`
expressions(&self) -> &Punctuated<Expression>1516     pub fn expressions(&self) -> &Punctuated<Expression> {
1517         &self.expr_list
1518     }
1519 
1520     /// The `=` token in between `x = y`
equal_token(&self) -> &TokenReference1521     pub fn equal_token(&self) -> &TokenReference {
1522         &self.equal_token
1523     }
1524 
1525     /// Returns the punctuated sequence over the variables being assigned to.
1526     /// This is the `x, y["a"]` part of `x, y["a"] = 1, 2`
variables(&self) -> &Punctuated<Var>1527     pub fn variables(&self) -> &Punctuated<Var> {
1528         &self.var_list
1529     }
1530 
1531     /// Returns a new Assignment with the given variables
with_variables(self, var_list: Punctuated<Var>) -> Self1532     pub fn with_variables(self, var_list: Punctuated<Var>) -> Self {
1533         Self { var_list, ..self }
1534     }
1535 
1536     /// Returns a new Assignment with the given `=` token
with_equal_token(self, equal_token: TokenReference) -> Self1537     pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
1538         Self {
1539             equal_token,
1540             ..self
1541         }
1542     }
1543 
1544     /// Returns a new Assignment with the given expressions
with_expressions(self, expr_list: Punctuated<Expression>) -> Self1545     pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1546         Self { expr_list, ..self }
1547     }
1548 }
1549 
1550 /// A declaration of a local function, such as `local function x() end`
1551 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1552 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1553 #[cfg_attr(
1554     not(feature = "roblox"),
1555     display(fmt = "{}{}{}{}", "local_token", "function_token", "name", "body")
1556 )]
1557 #[cfg_attr(
1558     feature = "roblox",
1559     display(
1560         fmt = "{}{}{}{}{}",
1561         "local_token",
1562         "function_token",
1563         "name",
1564         "display_option(self.generics())",
1565         "body"
1566     )
1567 )]
1568 pub struct LocalFunction {
1569     local_token: TokenReference,
1570     function_token: TokenReference,
1571     name: TokenReference,
1572     #[cfg(feature = "roblox")]
1573     generics: Option<GenericDeclaration>,
1574     body: FunctionBody,
1575 }
1576 
1577 impl LocalFunction {
1578     /// Returns a new LocalFunction from the given name
new(name: TokenReference) -> Self1579     pub fn new(name: TokenReference) -> Self {
1580         LocalFunction {
1581             local_token: TokenReference::symbol("local ").unwrap(),
1582             function_token: TokenReference::symbol("function ").unwrap(),
1583             name,
1584             #[cfg(feature = "roblox")]
1585             generics: None,
1586             body: FunctionBody::new(),
1587         }
1588     }
1589 
1590     /// The `local` token
local_token(&self) -> &TokenReference1591     pub fn local_token(&self) -> &TokenReference {
1592         &self.local_token
1593     }
1594 
1595     /// The `function` token
function_token(&self) -> &TokenReference1596     pub fn function_token(&self) -> &TokenReference {
1597         &self.function_token
1598     }
1599 
1600     /// The function body, everything except `local function x` in `local function x(a, b, c) call() end`
body(&self) -> &FunctionBody1601     pub fn body(&self) -> &FunctionBody {
1602         &self.body
1603     }
1604 
1605     /// The name of the function, the `x` part of `local function x() end`
name(&self) -> &TokenReference1606     pub fn name(&self) -> &TokenReference {
1607         &self.name
1608     }
1609 
1610     /// Any generics declared for the function, the `<T, U>` part of `local function x<T, U>() end`
1611     #[cfg(feature = "roblox")]
generics(&self) -> Option<&GenericDeclaration>1612     pub fn generics(&self) -> Option<&GenericDeclaration> {
1613         self.generics.as_ref()
1614     }
1615 
1616     /// Returns a new LocalFunction with the given `local` token
with_local_token(self, local_token: TokenReference) -> Self1617     pub fn with_local_token(self, local_token: TokenReference) -> Self {
1618         Self {
1619             local_token,
1620             ..self
1621         }
1622     }
1623 
1624     /// Returns a new LocalFunction with the given `function` token
with_function_token(self, function_token: TokenReference) -> Self1625     pub fn with_function_token(self, function_token: TokenReference) -> Self {
1626         Self {
1627             function_token,
1628             ..self
1629         }
1630     }
1631 
1632     /// Returns a new LocalFunction with the given name
with_name(self, name: TokenReference) -> Self1633     pub fn with_name(self, name: TokenReference) -> Self {
1634         Self { name, ..self }
1635     }
1636 
1637     /// Returns a new LocalFunction with the given generics
1638     #[cfg(feature = "roblox")]
with_generics(self, generics: Option<GenericDeclaration>) -> Self1639     pub fn with_generics(self, generics: Option<GenericDeclaration>) -> Self {
1640         Self { generics, ..self }
1641     }
1642 
1643     /// Returns a new LocalFunction with the given function body
with_body(self, body: FunctionBody) -> Self1644     pub fn with_body(self, body: FunctionBody) -> Self {
1645         Self { body, ..self }
1646     }
1647 }
1648 
1649 /// An assignment to a local variable, such as `local x = 1`
1650 #[derive(Clone, Debug, PartialEq, Node)]
1651 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1652 pub struct LocalAssignment {
1653     local_token: TokenReference,
1654     #[cfg(feature = "roblox")]
1655     type_specifiers: Vec<Option<TypeSpecifier>>,
1656     name_list: Punctuated<TokenReference>,
1657     equal_token: Option<TokenReference>,
1658     expr_list: Punctuated<Expression>,
1659 }
1660 
1661 impl LocalAssignment {
1662     /// Returns a new LocalAssignment from the given name list
new(name_list: Punctuated<TokenReference>) -> Self1663     pub fn new(name_list: Punctuated<TokenReference>) -> Self {
1664         Self {
1665             local_token: TokenReference::symbol("local ").unwrap(),
1666             #[cfg(feature = "roblox")]
1667             type_specifiers: Vec::new(),
1668             name_list,
1669             equal_token: None,
1670             expr_list: Punctuated::new(),
1671         }
1672     }
1673 
1674     /// The `local` token
local_token(&self) -> &TokenReference1675     pub fn local_token(&self) -> &TokenReference {
1676         &self.local_token
1677     }
1678 
1679     /// The `=` token in between `local x = y`, if one exists
equal_token(&self) -> Option<&TokenReference>1680     pub fn equal_token(&self) -> Option<&TokenReference> {
1681         self.equal_token.as_ref()
1682     }
1683 
1684     /// Returns the punctuated sequence of the expressions being assigned.
1685     /// This is the `1, 2` part of `local x, y = 1, 2`
expressions(&self) -> &Punctuated<Expression>1686     pub fn expressions(&self) -> &Punctuated<Expression> {
1687         &self.expr_list
1688     }
1689 
1690     /// Returns the punctuated sequence of names being assigned to.
1691     /// This is the `x, y` part of `local x, y = 1, 2`
names(&self) -> &Punctuated<TokenReference>1692     pub fn names(&self) -> &Punctuated<TokenReference> {
1693         &self.name_list
1694     }
1695 
1696     /// The type specifiers of the variables, in the order that they were assigned.
1697     /// `local foo: number, bar, baz: boolean` returns an iterator containing:
1698     /// `Some(TypeSpecifier(number)), None, Some(TypeSpecifier(boolean))`
1699     /// Only available when the "roblox" feature flag is enabled.
1700     #[cfg(feature = "roblox")]
type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>>1701     pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1702         self.type_specifiers.iter().map(Option::as_ref)
1703     }
1704 
1705     /// Returns a new LocalAssignment with the given `local` token
with_local_token(self, local_token: TokenReference) -> Self1706     pub fn with_local_token(self, local_token: TokenReference) -> Self {
1707         Self {
1708             local_token,
1709             ..self
1710         }
1711     }
1712 
1713     /// Returns a new LocalAssignment with the given type specifiers
1714     #[cfg(feature = "roblox")]
with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self1715     pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1716         Self {
1717             type_specifiers,
1718             ..self
1719         }
1720     }
1721 
1722     /// Returns a new LocalAssignment with the given name list
with_names(self, name_list: Punctuated<TokenReference>) -> Self1723     pub fn with_names(self, name_list: Punctuated<TokenReference>) -> Self {
1724         Self { name_list, ..self }
1725     }
1726 
1727     /// Returns a new LocalAssignment with the given `=` token
with_equal_token(self, equal_token: Option<TokenReference>) -> Self1728     pub fn with_equal_token(self, equal_token: Option<TokenReference>) -> Self {
1729         Self {
1730             equal_token,
1731             ..self
1732         }
1733     }
1734 
1735     /// Returns a new LocalAssignment with the given expression list
with_expressions(self, expr_list: Punctuated<Expression>) -> Self1736     pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1737         Self { expr_list, ..self }
1738     }
1739 }
1740 
1741 impl fmt::Display for LocalAssignment {
1742     #[cfg(feature = "roblox")]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result1743     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1744         write!(
1745             formatter,
1746             "{}{}{}{}",
1747             self.local_token,
1748             join_type_specifiers(&self.name_list, self.type_specifiers()),
1749             display_option(&self.equal_token),
1750             self.expr_list
1751         )
1752     }
1753 
1754     #[cfg(not(feature = "roblox"))]
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result1755     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1756         write!(
1757             formatter,
1758             "{}{}{}{}",
1759             self.local_token,
1760             self.name_list,
1761             display_option(&self.equal_token),
1762             self.expr_list
1763         )
1764     }
1765 }
1766 
1767 /// A `do` block, such as `do ... end`
1768 /// This is not used for things like `while true do end`, only those on their own
1769 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1770 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1771 #[display(fmt = "{}{}{}", "do_token", "block", "end_token")]
1772 pub struct Do {
1773     do_token: TokenReference,
1774     block: Block,
1775     end_token: TokenReference,
1776 }
1777 
1778 impl Do {
1779     /// Creates an empty Do
new() -> Self1780     pub fn new() -> Self {
1781         Self {
1782             do_token: TokenReference::symbol("do\n").unwrap(),
1783             block: Block::new(),
1784             end_token: TokenReference::symbol("\nend").unwrap(),
1785         }
1786     }
1787 
1788     /// The `do` token
do_token(&self) -> &TokenReference1789     pub fn do_token(&self) -> &TokenReference {
1790         &self.do_token
1791     }
1792 
1793     /// The code inside the `do ... end`
block(&self) -> &Block1794     pub fn block(&self) -> &Block {
1795         &self.block
1796     }
1797 
1798     /// The `end` token
end_token(&self) -> &TokenReference1799     pub fn end_token(&self) -> &TokenReference {
1800         &self.end_token
1801     }
1802 
1803     /// Returns a new Do with the given `do` token
with_do_token(self, do_token: TokenReference) -> Self1804     pub fn with_do_token(self, do_token: TokenReference) -> Self {
1805         Self { do_token, ..self }
1806     }
1807 
1808     /// Returns a new Do with the given block
with_block(self, block: Block) -> Self1809     pub fn with_block(self, block: Block) -> Self {
1810         Self { block, ..self }
1811     }
1812 
1813     /// Returns a new Do with the given `end` token
with_end_token(self, end_token: TokenReference) -> Self1814     pub fn with_end_token(self, end_token: TokenReference) -> Self {
1815         Self { end_token, ..self }
1816     }
1817 }
1818 
1819 impl Default for Do {
default() -> Self1820     fn default() -> Self {
1821         Self::new()
1822     }
1823 }
1824 
1825 /// A function being called, such as `call()`
1826 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1827 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1828 #[display(fmt = "{}{}", "prefix", "join_vec(suffixes)")]
1829 pub struct FunctionCall {
1830     prefix: Prefix,
1831     suffixes: Vec<Suffix>,
1832 }
1833 
1834 impl FunctionCall {
1835     /// Creates a new FunctionCall from the given prefix
1836     /// Sets the suffixes such that the return is `prefixes()`
new(prefix: Prefix) -> Self1837     pub fn new(prefix: Prefix) -> Self {
1838         FunctionCall {
1839             prefix,
1840             suffixes: vec![Suffix::Call(Call::AnonymousCall(
1841                 FunctionArgs::Parentheses {
1842                     arguments: Punctuated::new(),
1843                     parentheses: ContainedSpan::new(
1844                         TokenReference::symbol("(").unwrap(),
1845                         TokenReference::symbol(")").unwrap(),
1846                     ),
1847                 },
1848             ))],
1849         }
1850     }
1851 
1852     /// The prefix of a function call, the `call` part of `call()`
prefix(&self) -> &Prefix1853     pub fn prefix(&self) -> &Prefix {
1854         &self.prefix
1855     }
1856 
1857     /// The suffix of a function call, the `()` part of `call()`
suffixes(&self) -> impl Iterator<Item = &Suffix>1858     pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
1859         self.suffixes.iter()
1860     }
1861 
1862     /// Returns a new FunctionCall with the given prefix
with_prefix(self, prefix: Prefix) -> Self1863     pub fn with_prefix(self, prefix: Prefix) -> Self {
1864         Self { prefix, ..self }
1865     }
1866 
1867     /// Returns a new FunctionCall with the given suffixes
with_suffixes(self, suffixes: Vec<Suffix>) -> Self1868     pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
1869         Self { suffixes, ..self }
1870     }
1871 }
1872 
1873 /// A function name when being declared as [`FunctionDeclaration`]
1874 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1875 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1876 #[display(
1877     fmt = "{}{}{}",
1878     "names",
1879     "display_option(self.method_colon())",
1880     "display_option(self.method_name())"
1881 )]
1882 pub struct FunctionName {
1883     names: Punctuated<TokenReference>,
1884     colon_name: Option<(TokenReference, TokenReference)>,
1885 }
1886 
1887 impl FunctionName {
1888     /// Creates a new FunctionName from the given list of names
new(names: Punctuated<TokenReference>) -> Self1889     pub fn new(names: Punctuated<TokenReference>) -> Self {
1890         Self {
1891             names,
1892             colon_name: None,
1893         }
1894     }
1895 
1896     /// The colon between the name and the method, the `:` part of `function x:y() end`
method_colon(&self) -> Option<&TokenReference>1897     pub fn method_colon(&self) -> Option<&TokenReference> {
1898         Some(&self.colon_name.as_ref()?.0)
1899     }
1900 
1901     /// A method name if one exists, the `y` part of `function x:y() end`
method_name(&self) -> Option<&TokenReference>1902     pub fn method_name(&self) -> Option<&TokenReference> {
1903         Some(&self.colon_name.as_ref()?.1)
1904     }
1905 
1906     /// Returns the punctuated sequence over the names used when defining the function.
1907     /// This is the `x.y.z` part of `function x.y.z() end`
names(&self) -> &Punctuated<TokenReference>1908     pub fn names(&self) -> &Punctuated<TokenReference> {
1909         &self.names
1910     }
1911 
1912     /// Returns a new FunctionName with the given names
with_names(self, names: Punctuated<TokenReference>) -> Self1913     pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
1914         Self { names, ..self }
1915     }
1916 
1917     /// Returns a new FunctionName with the given method name
1918     /// The first token is the colon, and the second token is the method name itself
with_method(self, method: Option<(TokenReference, TokenReference)>) -> Self1919     pub fn with_method(self, method: Option<(TokenReference, TokenReference)>) -> Self {
1920         Self {
1921             colon_name: method,
1922             ..self
1923         }
1924     }
1925 }
1926 
1927 /// A normal function declaration, supports simple declarations like `function x() end`
1928 /// as well as complicated declarations such as `function x.y.z:a() end`
1929 #[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1930 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1931 #[cfg_attr(
1932     not(feature = "roblox"),
1933     display(fmt = "{}{}{}", "function_token", "name", "body")
1934 )]
1935 #[cfg_attr(
1936     feature = "roblox",
1937     display(
1938         fmt = "{}{}{}{}",
1939         "function_token",
1940         "name",
1941         "display_option(self.generics())",
1942         "body"
1943     )
1944 )]
1945 pub struct FunctionDeclaration {
1946     function_token: TokenReference,
1947     name: FunctionName,
1948     #[cfg(feature = "roblox")]
1949     generics: Option<GenericDeclaration>,
1950     body: FunctionBody,
1951 }
1952 
1953 impl FunctionDeclaration {
1954     /// Creates a new FunctionDeclaration from the given name
new(name: FunctionName) -> Self1955     pub fn new(name: FunctionName) -> Self {
1956         Self {
1957             function_token: TokenReference::symbol("function ").unwrap(),
1958             name,
1959             #[cfg(feature = "roblox")]
1960             generics: None,
1961             body: FunctionBody::new(),
1962         }
1963     }
1964 
1965     /// The `function` token
function_token(&self) -> &TokenReference1966     pub fn function_token(&self) -> &TokenReference {
1967         &self.function_token
1968     }
1969 
1970     /// The body of the function
body(&self) -> &FunctionBody1971     pub fn body(&self) -> &FunctionBody {
1972         &self.body
1973     }
1974 
1975     /// The name of the function
name(&self) -> &FunctionName1976     pub fn name(&self) -> &FunctionName {
1977         &self.name
1978     }
1979 
1980     /// Any generics declared for the function
1981     #[cfg(feature = "roblox")]
generics(&self) -> Option<&GenericDeclaration>1982     pub fn generics(&self) -> Option<&GenericDeclaration> {
1983         self.generics.as_ref()
1984     }
1985 
1986     /// Returns a new FunctionDeclaration with the given `function` token
with_function_token(self, function_token: TokenReference) -> Self1987     pub fn with_function_token(self, function_token: TokenReference) -> Self {
1988         Self {
1989             function_token,
1990             ..self
1991         }
1992     }
1993 
1994     /// Returns a new FunctionDeclaration with the given function name
with_name(self, name: FunctionName) -> Self1995     pub fn with_name(self, name: FunctionName) -> Self {
1996         Self { name, ..self }
1997     }
1998 
1999     /// Returns a new FunctionDeclaration with the given generics
2000     #[cfg(feature = "roblox")]
with_generics(self, generics: Option<GenericDeclaration>) -> Self2001     pub fn with_generics(self, generics: Option<GenericDeclaration>) -> Self {
2002         Self { generics, ..self }
2003     }
2004 
2005     /// Returns a new FunctionDeclaration with the given function body
with_body(self, body: FunctionBody) -> Self2006     pub fn with_body(self, body: FunctionBody) -> Self {
2007         Self { body, ..self }
2008     }
2009 }
2010 
2011 make_op!(BinOp,
2012     #[doc = "Operators that require two operands, such as X + Y or X - Y"]
2013     #[visit(skip_visit_self)]
2014     {
2015         And,
2016         Caret,
2017         GreaterThan,
2018         GreaterThanEqual,
2019         LessThan,
2020         LessThanEqual,
2021         Minus,
2022         Or,
2023         Percent,
2024         Plus,
2025         Slash,
2026         Star,
2027         TildeEqual,
2028         TwoDots,
2029         TwoEqual,
2030     }
2031 );
2032 
2033 impl BinOp {
2034     /// The precedence of the operator, from a scale of 1 to 8. The larger the number, the higher the precedence.
2035     /// See more at http://www.lua.org/manual/5.1/manual.html#2.5.6
precedence(&self) -> u82036     pub fn precedence(&self) -> u8 {
2037         match *self {
2038             BinOp::Caret(_) => 8,
2039             BinOp::Star(_) | BinOp::Slash(_) | BinOp::Percent(_) => 6,
2040             BinOp::Plus(_) | BinOp::Minus(_) => 5,
2041             BinOp::TwoDots(_) => 4,
2042             BinOp::GreaterThan(_)
2043             | BinOp::LessThan(_)
2044             | BinOp::GreaterThanEqual(_)
2045             | BinOp::LessThanEqual(_)
2046             | BinOp::TildeEqual(_)
2047             | BinOp::TwoEqual(_) => 3,
2048             BinOp::And(_) => 2,
2049             BinOp::Or(_) => 1,
2050         }
2051     }
2052 
2053     /// Whether the operator is right associative. If not, it is left associative.
2054     /// See more at https://www.lua.org/pil/3.5.html
is_right_associative(&self) -> bool2055     pub fn is_right_associative(&self) -> bool {
2056         matches!(*self, BinOp::Caret(_) | BinOp::TwoDots(_))
2057     }
2058 }
2059 
2060 make_op!(UnOp,
2061     #[doc = "Operators that require just one operand, such as #X"]
2062     {
2063         Minus,
2064         Not,
2065         Hash,
2066     }
2067 );
2068 
2069 impl UnOp {
2070     /// The precedence of the operator, from a scale of 1 to 8. The larger the number, the higher the precedence.
2071     /// See more at http://www.lua.org/manual/5.1/manual.html#2.5.6
precedence(&self) -> u82072     pub fn precedence(&self) -> u8 {
2073         7
2074     }
2075 }
2076 
2077 /// An error that occurs when creating the ast *after* tokenizing
2078 #[derive(Clone, Debug, PartialEq)]
2079 #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2080 pub enum AstError {
2081     /// There were no tokens passed, which shouldn't happen normally
2082     Empty,
2083     /// Tokens passed had no end of file token, which shouldn't happen normally
2084     NoEof,
2085     /// An unexpected token, the most likely scenario when getting an AstError
2086     UnexpectedToken {
2087         /// The token that caused the error
2088         token: Token,
2089         /// Any additional information that could be provided for debugging
2090         additional: Option<Cow<'static, str>>,
2091     },
2092 }
2093 
2094 impl fmt::Display for AstError {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result2095     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2096         match self {
2097             AstError::Empty => write!(formatter, "tokens passed was empty, which shouldn't happen normally"),
2098             AstError::NoEof => write!(formatter, "tokens passed had no eof token, which shouldn't happen normally"),
2099             AstError::UnexpectedToken { token, additional } => write!(
2100                 formatter,
2101                 "unexpected token `{}`. (starting from line {}, character {} and ending on line {}, character {}){}",
2102                 token,
2103                 token.start_position().line(),
2104                 token.start_position().character(),
2105                 token.end_position().line(),
2106                 token.end_position().character(),
2107                 match additional {
2108                     Some(additional) => format!("\nadditional information: {}", additional),
2109                     None => String::new(),
2110                 }
2111             )
2112         }
2113     }
2114 }
2115 
2116 impl std::error::Error for AstError {}
2117 
2118 /// An abstract syntax tree, contains all the nodes used in the code
2119 #[derive(Clone, Debug)]
2120 pub struct Ast {
2121     pub(crate) nodes: Block,
2122     pub(crate) eof: TokenReference,
2123 }
2124 
2125 impl Ast {
2126     /// Create an Ast from the passed tokens. You probably want [`parse`](crate::parse)
2127     ///
2128     /// # Errors
2129     ///
2130     /// If the tokens passed are impossible to get through normal tokenization,
2131     /// an error of Empty (if the vector is empty) or NoEof (if there is no eof token)
2132     /// will be returned.
2133     ///
2134     /// More likely, if the tokens pass are invalid Lua 5.1 code, an
2135     /// UnexpectedToken error will be returned.
from_tokens(tokens: Vec<Token>) -> Result<Ast, AstError>2136     pub fn from_tokens(tokens: Vec<Token>) -> Result<Ast, AstError> {
2137         if *tokens.last().ok_or(AstError::Empty)?.token_type() != TokenType::Eof {
2138             Err(AstError::NoEof)
2139         } else {
2140             let mut tokens = extract_token_references(tokens);
2141             let mut state = ParserState::new(&tokens);
2142 
2143             if tokens
2144                 .iter()
2145                 .filter(|token| !token.token_type().is_trivia())
2146                 .count()
2147                 == 1
2148             {
2149                 // Entirely comments/whitespace
2150                 return Ok(Ast {
2151                     nodes: Block {
2152                         stmts: Vec::new(),
2153                         last_stmt: None,
2154                     },
2155                     eof: tokens.pop().expect(
2156                         "(internal full-moon error) No EOF in tokens after checking for EOF.",
2157                     ),
2158                 });
2159             }
2160 
2161             // ParserState has to have at least 2 tokens, the last being an EOF, thus unwrap() can't fail
2162             if state.peek().token_type().is_trivia() {
2163                 state = state.advance().unwrap();
2164             }
2165 
2166             match parsers::ParseBlock.parse(state) {
2167                 Ok((state, block)) => {
2168                     if state.index == tokens.len() - 1 {
2169                         Ok(Ast {
2170                             nodes: block,
2171                             eof: tokens.pop().expect(
2172                                 "(internal full-moon error) No EOF in tokens after checking for EOF."
2173                             ),
2174                         })
2175                     } else {
2176                         Err(AstError::UnexpectedToken {
2177                             token: state.peek().token.clone(),
2178                             additional: Some(Cow::Borrowed("leftover token")),
2179                         })
2180                     }
2181                 }
2182 
2183                 Err(InternalAstError::NoMatch) => Err(AstError::UnexpectedToken {
2184                     token: state.peek().token.clone(),
2185                     additional: None,
2186                 }),
2187 
2188                 Err(InternalAstError::UnexpectedToken { token, additional }) => {
2189                     Err(AstError::UnexpectedToken {
2190                         token: token.token,
2191                         additional,
2192                     })
2193                 }
2194             }
2195         }
2196     }
2197 
2198     /// Returns a new Ast with the given nodes
with_nodes(self, nodes: Block) -> Self2199     pub fn with_nodes(self, nodes: Block) -> Self {
2200         Self { nodes, ..self }
2201     }
2202 
2203     /// Returns a new Ast with the given EOF token
with_eof(self, eof: TokenReference) -> Self2204     pub fn with_eof(self, eof: TokenReference) -> Self {
2205         Self { eof, ..self }
2206     }
2207 
2208     /// The entire code of the function
2209     ///
2210     /// ```rust
2211     /// # fn main() -> Result<(), Box<std::error::Error>> {
2212     /// assert_eq!(full_moon::parse("local x = 1; local y = 2")?.nodes().stmts().count(), 2);
2213     /// # Ok(())
2214     /// # }
2215     /// ```
nodes(&self) -> &Block2216     pub fn nodes(&self) -> &Block {
2217         &self.nodes
2218     }
2219 
2220     /// The entire code of the function, but mutable
nodes_mut(&mut self) -> &mut Block2221     pub fn nodes_mut(&mut self) -> &mut Block {
2222         &mut self.nodes
2223     }
2224 
2225     /// The EOF token at the end of every Ast
eof(&self) -> &TokenReference2226     pub fn eof(&self) -> &TokenReference {
2227         &self.eof
2228     }
2229 }
2230 
2231 /// Extracts leading and trailing trivia from tokens
extract_token_references(mut tokens: Vec<Token>) -> Vec<TokenReference>2232 pub(crate) fn extract_token_references(mut tokens: Vec<Token>) -> Vec<TokenReference> {
2233     let mut references = Vec::new();
2234     let (mut leading_trivia, mut trailing_trivia) = (Vec::new(), Vec::new());
2235     let mut tokens = tokens.drain(..).peekable();
2236 
2237     while let Some(token) = tokens.next() {
2238         if token.token_type().is_trivia() {
2239             leading_trivia.push(token);
2240         } else {
2241             while let Some(token) = tokens.peek() {
2242                 if token.token_type().is_trivia() {
2243                     // Take all trivia up to and including the newline character. If we see a newline character
2244                     // we should break once we have taken it in.
2245                     let should_break =
2246                         if let TokenType::Whitespace { ref characters } = &*token.token_type() {
2247                             // Use contains in order to tolerate \r\n line endings and mixed whitespace tokens
2248                             characters.contains('\n')
2249                         } else {
2250                             false
2251                         };
2252 
2253                     trailing_trivia.push(tokens.next().unwrap());
2254 
2255                     if should_break {
2256                         break;
2257                     }
2258                 } else {
2259                     break;
2260                 }
2261             }
2262 
2263             references.push(TokenReference {
2264                 leading_trivia: leading_trivia.drain(..).collect(),
2265                 trailing_trivia: trailing_trivia.drain(..).collect(),
2266                 token,
2267             });
2268         }
2269     }
2270 
2271     references
2272 }
2273 
2274 #[cfg(test)]
2275 mod tests {
2276     use super::*;
2277     use crate::{parse, print, tokenizer::tokens, visitors::VisitorMut};
2278 
2279     #[test]
test_extract_token_references()2280     fn test_extract_token_references() {
2281         let tokens = tokens("print(1)\n-- hello world\nlocal foo -- this is the word foo").unwrap();
2282 
2283         let references = extract_token_references(tokens);
2284         assert_eq!(references.len(), 7);
2285 
2286         assert!(references[0].trailing_trivia.is_empty());
2287         assert_eq!(references[0].token.to_string(), "print");
2288         assert!(references[0].leading_trivia.is_empty());
2289 
2290         assert!(references[1].trailing_trivia.is_empty());
2291         assert_eq!(references[1].token.to_string(), "(");
2292         assert!(references[1].leading_trivia.is_empty());
2293 
2294         assert!(references[2].trailing_trivia.is_empty());
2295         assert_eq!(references[2].token.to_string(), "1");
2296         assert!(references[2].leading_trivia.is_empty());
2297 
2298         assert_eq!(references[3].trailing_trivia[0].to_string(), "\n");
2299         assert_eq!(references[3].token.to_string(), ")");
2300         assert!(references[3].leading_trivia.is_empty());
2301 
2302         assert_eq!(
2303             references[4].leading_trivia[0].to_string(),
2304             "-- hello world",
2305         );
2306 
2307         assert_eq!(references[4].leading_trivia[1].to_string(), "\n");
2308         assert_eq!(references[4].token.to_string(), "local");
2309         assert_eq!(references[4].trailing_trivia[0].to_string(), " ");
2310     }
2311 
2312     #[test]
test_with_eof_safety()2313     fn test_with_eof_safety() {
2314         let new_ast = {
2315             let ast = parse("local foo = 1").unwrap();
2316             let eof = ast.eof().clone();
2317             ast.with_eof(eof)
2318         };
2319 
2320         print(&new_ast);
2321     }
2322 
2323     #[test]
test_with_nodes_safety()2324     fn test_with_nodes_safety() {
2325         let new_ast = {
2326             let ast = parse("local foo = 1").unwrap();
2327             let nodes = ast.nodes().clone();
2328             ast.with_nodes(nodes)
2329         };
2330 
2331         print(&new_ast);
2332     }
2333 
2334     #[test]
test_with_visitor_safety()2335     fn test_with_visitor_safety() {
2336         let new_ast = {
2337             let ast = parse("local foo = 1").unwrap();
2338 
2339             struct SyntaxRewriter;
2340             impl VisitorMut for SyntaxRewriter {
2341                 fn visit_token(&mut self, token: Token) -> Token {
2342                     token
2343                 }
2344             }
2345 
2346             SyntaxRewriter.visit_ast(ast)
2347         };
2348 
2349         print(&new_ast);
2350     }
2351 
2352     // Tests AST nodes with new methods that call unwrap
2353     #[test]
test_new_validity()2354     fn test_new_validity() {
2355         let token: TokenReference = TokenReference::new(
2356             Vec::new(),
2357             Token::new(TokenType::Identifier {
2358                 identifier: "foo".into(),
2359             }),
2360             Vec::new(),
2361         );
2362 
2363         let expression = Expression::Value {
2364             value: Box::new(Value::Var(Var::Name(token.clone()))),
2365             #[cfg(feature = "roblox")]
2366             type_assertion: None,
2367         };
2368 
2369         Assignment::new(Punctuated::new(), Punctuated::new());
2370         Do::new();
2371         ElseIf::new(expression.clone());
2372         FunctionBody::new();
2373         FunctionCall::new(Prefix::Name(token.clone()));
2374         FunctionDeclaration::new(FunctionName::new(Punctuated::new()));
2375         GenericFor::new(Punctuated::new(), Punctuated::new());
2376         If::new(expression.clone());
2377         LocalAssignment::new(Punctuated::new());
2378         LocalFunction::new(token.clone());
2379         MethodCall::new(
2380             token.clone(),
2381             FunctionArgs::Parentheses {
2382                 arguments: Punctuated::new(),
2383                 parentheses: ContainedSpan::new(token.clone(), token.clone()),
2384             },
2385         );
2386         NumericFor::new(token.clone(), expression.clone(), expression.clone());
2387         Repeat::new(expression.clone());
2388         Return::new();
2389         TableConstructor::new();
2390         While::new(expression.clone());
2391     }
2392 }
2393