Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Ast/include/Luau/Parser.h
2727 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#pragma once
3
4
#include "Luau/Ast.h"
5
#include "Luau/Lexer.h"
6
#include "Luau/ParseOptions.h"
7
#include "Luau/ParseResult.h"
8
#include "Luau/StringUtils.h"
9
#include "Luau/DenseHash.h"
10
#include "Luau/Common.h"
11
#include "Luau/Cst.h"
12
13
#include <initializer_list>
14
#include <optional>
15
#include <tuple>
16
17
namespace Luau
18
{
19
20
template<typename T>
21
class TempVector
22
{
23
public:
24
explicit TempVector(std::vector<T>& storage);
25
26
~TempVector();
27
28
const T& operator[](std::size_t index) const;
29
30
const T& front() const;
31
32
const T& back() const;
33
34
bool empty() const;
35
36
std::size_t size() const;
37
38
void push_back(const T& item);
39
40
typename std::vector<T>::const_iterator begin() const
41
{
42
return storage.begin() + offset;
43
}
44
typename std::vector<T>::const_iterator end() const
45
{
46
return storage.begin() + offset + size_;
47
}
48
49
private:
50
std::vector<T>& storage;
51
size_t offset;
52
size_t size_;
53
};
54
55
class Parser
56
{
57
template<typename Node, typename F>
58
static ParseNodeResult<Node> runParse(
59
const char* buffer,
60
size_t bufferSize,
61
AstNameTable& names,
62
Allocator& allocator,
63
ParseOptions options,
64
F f
65
);
66
67
public:
68
static ParseResult parse(
69
const char* buffer,
70
std::size_t bufferSize,
71
AstNameTable& names,
72
Allocator& allocator,
73
ParseOptions options = ParseOptions()
74
);
75
76
static ParseNodeResult<AstExpr> parseExpr(
77
const char* buffer,
78
std::size_t bufferSize,
79
AstNameTable& names,
80
Allocator& allocator,
81
ParseOptions options = ParseOptions()
82
);
83
84
static ParseNodeResult<AstType> parseType(
85
const char* buffer,
86
std::size_t bufferSize,
87
AstNameTable& names,
88
Allocator& allocator,
89
ParseOptions options = {}
90
);
91
92
private:
93
struct Name;
94
struct Binding;
95
96
Parser(const char* buffer, std::size_t bufferSize, AstNameTable& names, Allocator& allocator, const ParseOptions& options);
97
98
bool blockFollow(const Lexeme& l);
99
100
AstStatBlock* parseChunk();
101
102
// chunk ::= {stat [`;']} [laststat [`;']]
103
// block ::= chunk
104
AstStatBlock* parseBlock();
105
106
AstStatBlock* parseBlockNoScope();
107
108
// stat ::=
109
// varlist `=' explist |
110
// functioncall |
111
// do block end |
112
// while exp do block end |
113
// repeat block until exp |
114
// if exp then block {elseif exp then block} [else block] end |
115
// for Name `=' exp `,' exp [`,' exp] do block end |
116
// for namelist in explist do block end |
117
// [attributes] function funcname funcbody |
118
// [attributes] local function Name funcbody |
119
// local namelist [`=' explist]
120
// laststat ::= return [explist] | break
121
AstStat* parseStat();
122
123
// if exp then block {elseif exp then block} [else block] end
124
AstStat* parseIf();
125
126
// while exp do block end
127
AstStat* parseWhile();
128
129
// repeat block until exp
130
AstStat* parseRepeat();
131
132
// do block end
133
AstStat* parseDo();
134
135
// break
136
AstStat* parseBreak();
137
138
// continue
139
AstStat* parseContinue(const Location& start);
140
141
// for Name `=' exp `,' exp [`,' exp] do block end |
142
// for namelist in explist do block end |
143
AstStat* parseFor();
144
145
// funcname ::= Name {`.' Name} [`:' Name]
146
AstExpr* parseFunctionName(bool& hasself, AstName& debugname);
147
148
// function funcname funcbody
149
LUAU_FORCEINLINE AstStat* parseFunctionStat(const AstArray<AstAttr*>& attributes = {nullptr, 0});
150
151
std::optional<AstAttr::Type> validateAttribute(
152
Location loc,
153
const char* attributeName,
154
const TempVector<AstAttr*>& attributes,
155
const AstArray<AstExpr*>& args
156
);
157
158
// attribute ::= '@' NAME
159
void parseAttribute(TempVector<AstAttr*>& attribute);
160
161
// attributes ::= {attribute}
162
AstArray<AstAttr*> parseAttributes();
163
164
// attributes local function Name funcbody
165
// attributes function funcname funcbody
166
// attributes `declare function' Name`(' [parlist] `)' [`:` Type]
167
// declare Name '{' Name ':' attributes `(' [parlist] `)' [`:` Type] '}'
168
AstStat* parseAttributeStat();
169
170
// local function Name funcbody |
171
// local namelist [`=' explist]
172
AstStat* parseLocal_DEPRECATED(const AstArray<AstAttr*>& attributes);
173
AstStat* parseLocal(const Location start, const Position keywordPosition, const AstArray<AstAttr*>& attributes, bool isConst);
174
175
// return [explist]
176
AstStat* parseReturn();
177
178
// type Name `=' Type
179
AstStat* parseTypeAlias(const Location& start, bool exported, Position typeKeywordPosition);
180
181
// type function Name ... end
182
AstStat* parseTypeFunction(const Location& start, bool exported, Position typeKeywordPosition);
183
184
AstDeclaredExternTypeProperty parseDeclaredExternTypeMethod(const AstArray<AstAttr*>& attributes);
185
AstDeclaredExternTypeProperty parseDeclaredExternTypeMethod_DEPRECATED();
186
187
188
// `declare global' Name: Type |
189
// `declare function' Name`(' [parlist] `)' [`:` Type]
190
AstStat* parseDeclaration(const Location& start, const AstArray<AstAttr*>& attributes);
191
192
// varlist `=' explist
193
AstStat* parseAssignment(AstExpr* initial);
194
195
// var [`+=' | `-=' | `*=' | `/=' | `%=' | `^=' | `..='] exp
196
AstStat* parseCompoundAssignment(AstExpr* initial, AstExprBinary::Op op);
197
198
std::pair<AstLocal*, AstArray<AstLocal*>> prepareFunctionArguments(const Location& start, bool hasself, const TempVector<Binding>& args);
199
200
// funcbodyhead ::= `(' [namelist [`,' `...'] | `...'] `)' [`:` Type]
201
// funcbody ::= funcbodyhead block end
202
std::pair<AstExprFunction*, AstLocal*> parseFunctionBody(
203
bool hasself,
204
const Lexeme& matchFunction,
205
const AstName& debugname,
206
const Name* localName,
207
const AstArray<AstAttr*>& attributes,
208
const bool isConst = false
209
);
210
211
// explist ::= {exp `,'} exp
212
void parseExprList(TempVector<AstExpr*>& result, TempVector<Position>* commaPositions = nullptr);
213
214
// binding ::= Name [`:` Type]
215
Binding parseBinding(bool isConst = false);
216
AstArray<Position> extractAnnotationColonPositions(const TempVector<Binding>& bindings);
217
218
// bindinglist ::= (binding | `...') {`,' bindinglist}
219
// Returns the location of the vararg ..., or std::nullopt if the function is not vararg.
220
std::tuple<bool, Location, AstTypePack*> parseBindingList(
221
TempVector<Binding>& result,
222
bool allowDot3 = false,
223
AstArray<Position>* commaPositions = nullptr,
224
Position* initialCommaPosition = nullptr,
225
Position* varargAnnotationColonPosition = nullptr,
226
bool isConst = false
227
);
228
229
AstType* parseOptionalType();
230
231
// TypeList ::= Type [`,' TypeList]
232
// ReturnType ::= Type | `(' TypeList `)'
233
// TableProp ::= Name `:' Type
234
// TableIndexer ::= `[' Type `]' `:' Type
235
// PropList ::= (TableProp | TableIndexer) [`,' PropList]
236
// Type
237
// ::= Name
238
// | `nil`
239
// | `{' [PropList] `}'
240
// | `(' [TypeList] `)' `->` ReturnType
241
242
// Returns the variadic annotation, if it exists.
243
AstTypePack* parseTypeList(
244
TempVector<AstType*>& result,
245
TempVector<std::optional<AstArgumentName>>& resultNames,
246
TempVector<Position>* commaPositions = nullptr,
247
TempVector<std::optional<Position>>* nameColonPositions = nullptr
248
);
249
250
AstTypePack* parseOptionalReturnType(Position* returnSpecifierPosition = nullptr);
251
AstTypePack* parseReturnType();
252
253
struct TableIndexerResult
254
{
255
AstTableIndexer* node;
256
Position indexerOpenPosition;
257
Position indexerClosePosition;
258
Position colonPosition;
259
};
260
261
TableIndexerResult parseTableIndexer(AstTableAccess access, std::optional<Location> accessLocation, Lexeme begin);
262
263
AstTypeOrPack parseFunctionType(bool allowPack, const AstArray<AstAttr*>& attributes);
264
AstType* parseFunctionTypeTail(
265
const Lexeme& begin,
266
const AstArray<AstAttr*>& attributes,
267
AstArray<AstGenericType*> generics,
268
AstArray<AstGenericTypePack*> genericPacks,
269
AstArray<AstType*> params,
270
AstArray<std::optional<AstArgumentName>> paramNames,
271
AstTypePack* varargAnnotation
272
);
273
274
AstType* parseTableType(bool inDeclarationContext = false);
275
AstTypeOrPack parseSimpleType(bool allowPack, bool inDeclarationContext = false);
276
277
AstTypeOrPack parseSimpleTypeOrPack();
278
AstType* parseType(bool inDeclarationContext = false);
279
280
AstTypePack* parseTypePack();
281
AstTypePack* parseVariadicArgumentTypePack();
282
283
AstType* parseTypeSuffix(AstType* type, const Location& begin);
284
285
static std::optional<AstExprUnary::Op> parseUnaryOp(const Lexeme& l);
286
static std::optional<AstExprBinary::Op> parseBinaryOp(const Lexeme& l);
287
static std::optional<AstExprBinary::Op> parseCompoundOp(const Lexeme& l);
288
289
struct BinaryOpPriority
290
{
291
unsigned char left, right;
292
};
293
294
std::optional<AstExprUnary::Op> checkUnaryConfusables();
295
std::optional<AstExprBinary::Op> checkBinaryConfusables(const BinaryOpPriority binaryPriority[], unsigned int limit);
296
297
// subexpr -> (asexp | unop subexpr) { binop subexpr }
298
// where `binop' is any binary operator with a priority higher than `limit'
299
AstExpr* parseExpr(unsigned int limit = 0);
300
301
// NAME
302
AstExpr* parseNameExpr(const char* context = nullptr);
303
304
// prefixexp -> NAME | '(' expr ')'
305
AstExpr* parsePrefixExpr();
306
307
// primaryexp -> prefixexp { `.' NAME | `[' exp `]' | TypeInstantiation | `:' NAME [TypeInstantiation] funcargs | funcargs }
308
AstExpr* parsePrimaryExpr(bool asStatement);
309
AstExpr* parseMethodCall(Position start, AstExpr* expr);
310
311
// asexp -> simpleexp [`::' Type]
312
AstExpr* parseAssertionExpr();
313
314
// simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | [attributes] FUNCTION body | primaryexp
315
AstExpr* parseSimpleExpr();
316
317
std::tuple<AstArray<AstExpr*>, Location, Location> parseCallList(TempVector<Position>* commaPositions);
318
// args ::= `(' [explist] `)' | tableconstructor | String
319
AstExpr* parseFunctionArgs(AstExpr* func, bool self);
320
321
std::optional<CstExprTable::Separator> tableSeparator();
322
323
// tableconstructor ::= `{' [fieldlist] `}'
324
// fieldlist ::= field {fieldsep field} [fieldsep]
325
// field ::= `[' exp `]' `=' exp | Name `=' exp | exp
326
// fieldsep ::= `,' | `;'
327
AstExpr* parseTableConstructor();
328
329
// TODO: Add grammar rules here?
330
AstExpr* parseIfElseExpr();
331
332
// stringinterp ::= <INTERP_BEGIN> exp {<INTERP_MID> exp} <INTERP_END>
333
AstExpr* parseInterpString();
334
335
// TypeInstantiation ::= `<' `<' [TypeList] `>' `>'
336
AstArray<AstTypeOrPack> parseTypeInstantiationExpr(CstTypeInstantiation* cstNodeOut = nullptr, Location* endLocationOut = nullptr);
337
338
AstExpr* parseExplicitTypeInstantiationExpr(Position start, AstExpr& basedOnExpr);
339
340
// Name
341
std::optional<Name> parseNameOpt(const char* context = nullptr);
342
Name parseName(const char* context = nullptr);
343
Name parseIndexName(const char* context, const Position& previous);
344
345
// `<' namelist `>'
346
std::pair<AstArray<AstGenericType*>, AstArray<AstGenericTypePack*>> parseGenericTypeList(
347
bool withDefaultValues,
348
Position* openPosition = nullptr,
349
AstArray<Position>* commaPositions = nullptr,
350
Position* closePosition = nullptr
351
);
352
353
// `<' Type[, ...] `>'
354
AstArray<AstTypeOrPack> parseTypeParams(
355
Position* openingPosition = nullptr,
356
TempVector<Position>* commaPositions = nullptr,
357
Position* closingPosition = nullptr
358
);
359
360
std::optional<AstArray<char>> parseCharArray(AstArray<char>* originalString = nullptr);
361
AstExpr* parseString();
362
AstExpr* parseNumber();
363
364
AstLocal* pushLocal(const Binding& binding);
365
366
unsigned int saveLocals();
367
368
void restoreLocals(unsigned int offset);
369
370
/// Returns string quote style and block depth
371
std::pair<CstExprConstantString::QuoteStyle, unsigned int> extractStringDetails();
372
373
// check that parser is at lexeme/symbol, move to next lexeme/symbol on success, report failure and continue on failure
374
bool expectAndConsume(char value, const char* context = nullptr);
375
bool expectAndConsume(Lexeme::Type type, const char* context = nullptr);
376
bool expectAndConsumeFailWithLookahead(Lexeme::Type type, const char* context);
377
void expectAndConsumeFail(Lexeme::Type type, const char* context);
378
379
struct MatchLexeme
380
{
381
MatchLexeme(const Lexeme& l)
382
: type(l.type)
383
, position(l.location.begin)
384
{
385
}
386
387
Lexeme::Type type;
388
Position position;
389
};
390
391
bool expectMatchAndConsume(char value, const MatchLexeme& begin, bool searchForMissing = false);
392
void expectMatchAndConsumeFail(Lexeme::Type type, const MatchLexeme& begin, const char* extra = nullptr);
393
bool expectMatchAndConsumeRecover(char value, const MatchLexeme& begin, bool searchForMissing);
394
395
bool expectMatchEndAndConsume(Lexeme::Type type, const MatchLexeme& begin);
396
bool expectMatchEndAndConsumeFailWithLookahead(Lexeme::Type type, const MatchLexeme& begin);
397
398
template<typename T>
399
AstArray<T> copy(const T* data, std::size_t size);
400
401
template<typename T>
402
AstArray<T> copy(const TempVector<T>& data);
403
404
template<typename T>
405
AstArray<T> copy(std::initializer_list<T> data);
406
407
AstArray<char> copy(const std::string& data);
408
409
void incrementRecursionCounter(const char* context);
410
411
void report(const Location& location, const char* format, va_list args);
412
void report(const Location& location, const char* format, ...) LUAU_PRINTF_ATTR(3, 4);
413
414
void reportNameError(const char* context);
415
416
AstStatError* reportStatError(
417
const Location& location,
418
const AstArray<AstExpr*>& expressions,
419
const AstArray<AstStat*>& statements,
420
const char* format,
421
...
422
) LUAU_PRINTF_ATTR(5, 6);
423
AstExprError* reportExprError(const Location& location, const AstArray<AstExpr*>& expressions, const char* format, ...) LUAU_PRINTF_ATTR(4, 5);
424
AstTypeError* reportTypeError(const Location& location, const AstArray<AstType*>& types, const char* format, ...) LUAU_PRINTF_ATTR(4, 5);
425
// `parseErrorLocation` is associated with the parser error
426
// `astErrorLocation` is associated with the AstTypeError created
427
// It can be useful to have different error locations so that the parse error can include the next lexeme, while the AstTypeError can precisely
428
// define the location (possibly of zero size) where a type annotation is expected.
429
AstTypeError* reportMissingTypeError(
430
const Location& parseErrorLocation,
431
const Location& astErrorLocation,
432
const char* format,
433
...
434
) LUAU_PRINTF_ATTR(4, 5);
435
436
AstExpr* reportFunctionArgsError(AstExpr* func, bool self);
437
void reportAmbiguousCallError();
438
439
void nextLexeme();
440
441
struct Function
442
{
443
bool vararg;
444
unsigned int loopDepth;
445
446
Function()
447
: vararg(false)
448
, loopDepth(0)
449
{
450
}
451
};
452
453
struct Local
454
{
455
AstLocal* local;
456
unsigned int offset;
457
458
Local()
459
: local(nullptr)
460
, offset(0)
461
{
462
}
463
};
464
465
struct Name
466
{
467
AstName name;
468
Location location;
469
470
Name(const AstName& name, const Location& location)
471
: name(name)
472
, location(location)
473
{
474
}
475
};
476
477
struct Binding
478
{
479
Name name;
480
AstType* annotation;
481
Position colonPosition;
482
bool isConst;
483
484
explicit Binding(const Name& name, AstType* annotation = nullptr, Position colonPosition = {0, 0}, bool isConst = false)
485
: name(name)
486
, annotation(annotation)
487
, colonPosition(colonPosition)
488
, isConst(isConst)
489
{
490
}
491
};
492
493
ParseOptions options;
494
495
Lexer lexer;
496
Allocator& allocator;
497
498
std::vector<Comment> commentLocations;
499
std::vector<HotComment> hotcomments;
500
501
bool hotcommentHeader = true;
502
503
unsigned int recursionCounter;
504
505
AstName nameSelf;
506
AstName nameNumber;
507
AstName nameError;
508
AstName nameNil;
509
510
MatchLexeme endMismatchSuspect;
511
512
std::vector<Function> functionStack;
513
size_t typeFunctionDepth = 0;
514
515
DenseHashMap<AstName, AstLocal*> localMap;
516
std::vector<AstLocal*> localStack;
517
518
std::vector<ParseError> parseErrors;
519
520
std::vector<unsigned int> matchRecoveryStopOnToken;
521
522
std::vector<AstAttr*> scratchAttr;
523
std::vector<AstStat*> scratchStat;
524
std::vector<AstArray<char>> scratchString;
525
std::vector<AstArray<char>> scratchString2;
526
std::vector<AstExpr*> scratchExpr;
527
std::vector<AstExpr*> scratchExprAux;
528
std::vector<AstName> scratchName;
529
std::vector<AstName> scratchPackName;
530
std::vector<Binding> scratchBinding;
531
std::vector<AstLocal*> scratchLocal;
532
std::vector<AstTableProp> scratchTableTypeProps;
533
std::vector<CstTypeTable::Item> scratchCstTableTypeProps;
534
std::vector<AstType*> scratchType;
535
std::vector<AstTypeOrPack> scratchTypeOrPack;
536
std::vector<AstDeclaredExternTypeProperty> scratchDeclaredClassProps;
537
std::vector<AstExprTable::Item> scratchItem;
538
std::vector<CstExprTable::Item> scratchCstItem;
539
std::vector<AstArgumentName> scratchArgName;
540
std::vector<AstGenericType*> scratchGenericTypes;
541
std::vector<AstGenericTypePack*> scratchGenericTypePacks;
542
std::vector<std::optional<AstArgumentName>> scratchOptArgName;
543
std::vector<Position> scratchPosition;
544
std::vector<std::optional<Position>> scratchOptPosition;
545
std::string scratchData;
546
547
CstNodeMap cstNodeMap;
548
};
549
550
} // namespace Luau
551
552