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