|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef frontend_Parser_h |
|
8 #define frontend_Parser_h |
|
9 |
|
10 /* |
|
11 * JS parser definitions. |
|
12 */ |
|
13 |
|
14 #include "jspubtd.h" |
|
15 |
|
16 #include "frontend/BytecodeCompiler.h" |
|
17 #include "frontend/FullParseHandler.h" |
|
18 #include "frontend/ParseMaps.h" |
|
19 #include "frontend/ParseNode.h" |
|
20 #include "frontend/SharedContext.h" |
|
21 #include "frontend/SyntaxParseHandler.h" |
|
22 |
|
23 namespace js { |
|
24 namespace frontend { |
|
25 |
|
26 struct StmtInfoPC : public StmtInfoBase { |
|
27 StmtInfoPC *down; /* info for enclosing statement */ |
|
28 StmtInfoPC *downScope; /* next enclosing lexical scope */ |
|
29 |
|
30 uint32_t blockid; /* for simplified dominance computation */ |
|
31 uint32_t innerBlockScopeDepth; /* maximum depth of nested block scopes, in slots */ |
|
32 |
|
33 StmtInfoPC(ExclusiveContext *cx) : StmtInfoBase(cx), innerBlockScopeDepth(0) {} |
|
34 }; |
|
35 |
|
36 typedef HashSet<JSAtom *> FuncStmtSet; |
|
37 class SharedContext; |
|
38 |
|
39 typedef Vector<Definition *, 16> DeclVector; |
|
40 |
|
41 struct GenericParseContext |
|
42 { |
|
43 // Enclosing function or global context. |
|
44 GenericParseContext *parent; |
|
45 |
|
46 // Context shared between parsing and bytecode generation. |
|
47 SharedContext *sc; |
|
48 |
|
49 // The following flags are set when a particular code feature is detected |
|
50 // in a function. |
|
51 |
|
52 // Function has 'return <expr>;' |
|
53 bool funHasReturnExpr:1; |
|
54 |
|
55 // Function has 'return;' |
|
56 bool funHasReturnVoid:1; |
|
57 |
|
58 // The following flags are set when parsing enters a particular region of |
|
59 // source code, and cleared when that region is exited. |
|
60 |
|
61 // true while parsing init expr of for; exclude 'in' |
|
62 bool parsingForInit:1; |
|
63 |
|
64 // true while we are within a with-statement in the current ParseContext |
|
65 // chain (which stops at the top-level or an eval() |
|
66 bool parsingWith:1; |
|
67 |
|
68 GenericParseContext(GenericParseContext *parent, SharedContext *sc) |
|
69 : parent(parent), |
|
70 sc(sc), |
|
71 funHasReturnExpr(false), |
|
72 funHasReturnVoid(false), |
|
73 parsingForInit(false), |
|
74 parsingWith(parent ? parent->parsingWith : false) |
|
75 {} |
|
76 }; |
|
77 |
|
78 template <typename ParseHandler> |
|
79 bool |
|
80 GenerateBlockId(TokenStream &ts, ParseContext<ParseHandler> *pc, uint32_t &blockid); |
|
81 |
|
82 /* |
|
83 * The struct ParseContext stores information about the current parsing context, |
|
84 * which is part of the parser state (see the field Parser::pc). The current |
|
85 * parsing context is either the global context, or the function currently being |
|
86 * parsed. When the parser encounters a function definition, it creates a new |
|
87 * ParseContext, makes it the new current context, and sets its parent to the |
|
88 * context in which it encountered the definition. |
|
89 */ |
|
90 template <typename ParseHandler> |
|
91 struct ParseContext : public GenericParseContext |
|
92 { |
|
93 typedef StmtInfoPC StmtInfo; |
|
94 typedef typename ParseHandler::Node Node; |
|
95 typedef typename ParseHandler::DefinitionNode DefinitionNode; |
|
96 |
|
97 uint32_t bodyid; /* block number of program/function body */ |
|
98 uint32_t blockidGen; /* preincremented block number generator */ |
|
99 |
|
100 StmtInfoPC *topStmt; /* top of statement info stack */ |
|
101 StmtInfoPC *topScopeStmt; /* top lexical scope statement */ |
|
102 Rooted<NestedScopeObject *> staticScope; /* compile time scope chain */ |
|
103 Node maybeFunction; /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */ |
|
104 |
|
105 const unsigned staticLevel; /* static compilation unit nesting level */ |
|
106 |
|
107 // lastYieldOffset stores the offset of the last yield that was parsed. |
|
108 // NoYieldOffset is its initial value. |
|
109 static const uint32_t NoYieldOffset = UINT32_MAX; |
|
110 uint32_t lastYieldOffset; |
|
111 |
|
112 // Most functions start off being parsed as non-generators. |
|
113 // Non-generators transition to LegacyGenerator on parsing "yield" in JS 1.7. |
|
114 // An ES6 generator is marked as a "star generator" before its body is parsed. |
|
115 GeneratorKind generatorKind() const { |
|
116 return sc->isFunctionBox() ? sc->asFunctionBox()->generatorKind() : NotGenerator; |
|
117 } |
|
118 bool isGenerator() const { return generatorKind() != NotGenerator; } |
|
119 bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; } |
|
120 bool isStarGenerator() const { return generatorKind() == StarGenerator; } |
|
121 |
|
122 bool isArrowFunction() const { |
|
123 return sc->isFunctionBox() && sc->asFunctionBox()->function()->isArrow(); |
|
124 } |
|
125 |
|
126 uint32_t blockScopeDepth; /* maximum depth of nested block scopes, in slots */ |
|
127 Node blockNode; /* parse node for a block with let declarations |
|
128 (block with its own lexical scope) */ |
|
129 private: |
|
130 AtomDecls<ParseHandler> decls_; /* function, const, and var declarations */ |
|
131 DeclVector args_; /* argument definitions */ |
|
132 DeclVector vars_; /* var/const definitions */ |
|
133 |
|
134 public: |
|
135 const AtomDecls<ParseHandler> &decls() const { |
|
136 return decls_; |
|
137 } |
|
138 |
|
139 uint32_t numArgs() const { |
|
140 JS_ASSERT(sc->isFunctionBox()); |
|
141 return args_.length(); |
|
142 } |
|
143 |
|
144 /* |
|
145 * This function adds a definition to the lexical scope represented by this |
|
146 * ParseContext. |
|
147 * |
|
148 * Pre-conditions: |
|
149 * + The caller must have already taken care of name collisions: |
|
150 * - For non-let definitions, this means 'name' isn't in 'decls'. |
|
151 * - For let definitions, this means 'name' isn't already a name in the |
|
152 * current block. |
|
153 * + The given 'pn' is either a placeholder (created by a previous unbound |
|
154 * use) or an un-bound un-linked name node. |
|
155 * + The given 'kind' is one of ARG, CONST, VAR, or LET. In particular, |
|
156 * NAMED_LAMBDA is handled in an ad hoc special case manner (see |
|
157 * LeaveFunction) that we should consider rewriting. |
|
158 * |
|
159 * Post-conditions: |
|
160 * + pc->decls().lookupFirst(name) == pn |
|
161 * + The given name 'pn' has been converted in-place into a |
|
162 * non-placeholder definition. |
|
163 * + If this is a function scope (sc->inFunction), 'pn' is bound to a |
|
164 * particular local/argument slot. |
|
165 * + PND_CONST is set for Definition::COSNT |
|
166 * + Pre-existing uses of pre-existing placeholders have been linked to |
|
167 * 'pn' if they are in the scope of 'pn'. |
|
168 * + Pre-existing placeholders in the scope of 'pn' have been removed. |
|
169 */ |
|
170 bool define(TokenStream &ts, HandlePropertyName name, Node pn, Definition::Kind); |
|
171 |
|
172 /* |
|
173 * Let definitions may shadow same-named definitions in enclosing scopes. |
|
174 * To represesent this, 'decls' is not a plain map, but actually: |
|
175 * decls :: name -> stack of definitions |
|
176 * New bindings are pushed onto the stack, name lookup always refers to the |
|
177 * top of the stack, and leaving a block scope calls popLetDecl for each |
|
178 * name in the block's scope. |
|
179 */ |
|
180 void popLetDecl(JSAtom *atom); |
|
181 |
|
182 /* See the sad story in defineArg. */ |
|
183 void prepareToAddDuplicateArg(HandlePropertyName name, DefinitionNode prevDecl); |
|
184 |
|
185 /* See the sad story in MakeDefIntoUse. */ |
|
186 void updateDecl(JSAtom *atom, Node newDecl); |
|
187 |
|
188 /* |
|
189 * After a function body has been parsed, the parser generates the |
|
190 * function's "bindings". Bindings are a data-structure, ultimately stored |
|
191 * in the compiled JSScript, that serve three purposes: |
|
192 * - After parsing, the ParseContext is destroyed and 'decls' along with |
|
193 * it. Mostly, the emitter just uses the binding information stored in |
|
194 * the use/def nodes, but the emitter occasionally needs 'bindings' for |
|
195 * various scope-related queries. |
|
196 * - Bindings provide the initial js::Shape to use when creating a dynamic |
|
197 * scope object (js::CallObject) for the function. This shape is used |
|
198 * during dynamic name lookup. |
|
199 * - Sometimes a script's bindings are accessed at runtime to retrieve the |
|
200 * contents of the lexical scope (e.g., from the debugger). |
|
201 */ |
|
202 bool generateFunctionBindings(ExclusiveContext *cx, TokenStream &ts, |
|
203 LifoAlloc &alloc, |
|
204 InternalHandle<Bindings*> bindings) const; |
|
205 |
|
206 private: |
|
207 ParseContext **parserPC; /* this points to the Parser's active pc |
|
208 and holds either |this| or one of |
|
209 |this|'s descendents */ |
|
210 |
|
211 // Value for parserPC to restore at the end. Use 'parent' instead for |
|
212 // information about the parse chain, this may be nullptr if |
|
213 // parent != nullptr. |
|
214 ParseContext<ParseHandler> *oldpc; |
|
215 |
|
216 public: |
|
217 OwnedAtomDefnMapPtr lexdeps; /* unresolved lexical name dependencies */ |
|
218 |
|
219 FuncStmtSet *funcStmts; /* Set of (non-top-level) function statements |
|
220 that will alias any top-level bindings with |
|
221 the same name. */ |
|
222 |
|
223 // All inner functions in this context. Only filled in when parsing syntax. |
|
224 AutoFunctionVector innerFunctions; |
|
225 |
|
226 // In a function context, points to a Directive struct that can be updated |
|
227 // to reflect new directives encountered in the Directive Prologue that |
|
228 // require reparsing the function. In global/module/generator-tail contexts, |
|
229 // we don't need to reparse when encountering a DirectivePrologue so this |
|
230 // pointer may be nullptr. |
|
231 Directives *newDirectives; |
|
232 |
|
233 // Set when parsing a declaration-like destructuring pattern. This flag |
|
234 // causes PrimaryExpr to create PN_NAME parse nodes for variable references |
|
235 // which are not hooked into any definition's use chain, added to any tree |
|
236 // context's AtomList, etc. etc. CheckDestructuring will do that work |
|
237 // later. |
|
238 // |
|
239 // The comments atop CheckDestructuring explain the distinction between |
|
240 // assignment-like and declaration-like destructuring patterns, and why |
|
241 // they need to be treated differently. |
|
242 bool inDeclDestructuring:1; |
|
243 |
|
244 ParseContext(Parser<ParseHandler> *prs, GenericParseContext *parent, |
|
245 Node maybeFunction, SharedContext *sc, |
|
246 Directives *newDirectives, |
|
247 unsigned staticLevel, uint32_t bodyid, uint32_t blockScopeDepth) |
|
248 : GenericParseContext(parent, sc), |
|
249 bodyid(0), // initialized in init() |
|
250 blockidGen(bodyid), // used to set |bodyid| and subsequently incremented in init() |
|
251 topStmt(nullptr), |
|
252 topScopeStmt(nullptr), |
|
253 staticScope(prs->context), |
|
254 maybeFunction(maybeFunction), |
|
255 staticLevel(staticLevel), |
|
256 lastYieldOffset(NoYieldOffset), |
|
257 blockScopeDepth(blockScopeDepth), |
|
258 blockNode(ParseHandler::null()), |
|
259 decls_(prs->context, prs->alloc), |
|
260 args_(prs->context), |
|
261 vars_(prs->context), |
|
262 parserPC(&prs->pc), |
|
263 oldpc(prs->pc), |
|
264 lexdeps(prs->context), |
|
265 funcStmts(nullptr), |
|
266 innerFunctions(prs->context), |
|
267 newDirectives(newDirectives), |
|
268 inDeclDestructuring(false) |
|
269 { |
|
270 prs->pc = this; |
|
271 } |
|
272 |
|
273 ~ParseContext(); |
|
274 |
|
275 bool init(TokenStream &ts); |
|
276 |
|
277 unsigned blockid() { return topStmt ? topStmt->blockid : bodyid; } |
|
278 |
|
279 // True if we are at the topmost level of a entire script or function body. |
|
280 // For example, while parsing this code we would encounter f1 and f2 at |
|
281 // body level, but we would not encounter f3 or f4 at body level: |
|
282 // |
|
283 // function f1() { function f2() { } } |
|
284 // if (cond) { function f3() { if (cond) { function f4() { } } } } |
|
285 // |
|
286 bool atBodyLevel() { return !topStmt; } |
|
287 |
|
288 // True if this is the ParseContext for the body of a function created by |
|
289 // the Function constructor. |
|
290 bool isFunctionConstructorBody() const { |
|
291 return sc->isFunctionBox() && staticLevel == 0; |
|
292 } |
|
293 |
|
294 inline bool useAsmOrInsideUseAsm() const { |
|
295 return sc->isFunctionBox() && sc->asFunctionBox()->useAsmOrInsideUseAsm(); |
|
296 } |
|
297 }; |
|
298 |
|
299 template <typename ParseHandler> |
|
300 inline |
|
301 Directives::Directives(ParseContext<ParseHandler> *parent) |
|
302 : strict_(parent->sc->strict), |
|
303 asmJS_(parent->useAsmOrInsideUseAsm()) |
|
304 {} |
|
305 |
|
306 template <typename ParseHandler> |
|
307 struct BindData; |
|
308 |
|
309 class CompExprTransplanter; |
|
310 |
|
311 enum LetContext { LetExpresion, LetStatement }; |
|
312 enum VarContext { HoistVars, DontHoistVars }; |
|
313 enum FunctionType { Getter, Setter, Normal }; |
|
314 |
|
315 template <typename ParseHandler> |
|
316 class Parser : private AutoGCRooter, public StrictModeGetter |
|
317 { |
|
318 public: |
|
319 ExclusiveContext *const context; |
|
320 LifoAlloc &alloc; |
|
321 |
|
322 TokenStream tokenStream; |
|
323 LifoAlloc::Mark tempPoolMark; |
|
324 |
|
325 /* list of parsed objects for GC tracing */ |
|
326 ObjectBox *traceListHead; |
|
327 |
|
328 /* innermost parse context (stack-allocated) */ |
|
329 ParseContext<ParseHandler> *pc; |
|
330 |
|
331 /* Compression token for aborting. */ |
|
332 SourceCompressionTask *sct; |
|
333 |
|
334 ScriptSource *ss; |
|
335 |
|
336 /* Root atoms and objects allocated for the parsed tree. */ |
|
337 AutoKeepAtoms keepAtoms; |
|
338 |
|
339 /* Perform constant-folding; must be true when interfacing with the emitter. */ |
|
340 const bool foldConstants:1; |
|
341 |
|
342 private: |
|
343 /* |
|
344 * Not all language constructs can be handled during syntax parsing. If it |
|
345 * is not known whether the parse succeeds or fails, this bit is set and |
|
346 * the parse will return false. |
|
347 */ |
|
348 bool abortedSyntaxParse:1; |
|
349 |
|
350 /* Unexpected end of input, i.e. TOK_EOF not at top-level. */ |
|
351 bool isUnexpectedEOF_:1; |
|
352 |
|
353 typedef typename ParseHandler::Node Node; |
|
354 typedef typename ParseHandler::DefinitionNode DefinitionNode; |
|
355 |
|
356 public: |
|
357 /* State specific to the kind of parse being performed. */ |
|
358 ParseHandler handler; |
|
359 |
|
360 private: |
|
361 bool reportHelper(ParseReportKind kind, bool strict, uint32_t offset, |
|
362 unsigned errorNumber, va_list args); |
|
363 public: |
|
364 bool report(ParseReportKind kind, bool strict, Node pn, unsigned errorNumber, ...); |
|
365 bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...); |
|
366 bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber, |
|
367 ...); |
|
368 |
|
369 Parser(ExclusiveContext *cx, LifoAlloc *alloc, const ReadOnlyCompileOptions &options, |
|
370 const jschar *chars, size_t length, bool foldConstants, |
|
371 Parser<SyntaxParseHandler> *syntaxParser, |
|
372 LazyScript *lazyOuterFunction); |
|
373 ~Parser(); |
|
374 |
|
375 // A Parser::Mark is the extension of the LifoAlloc::Mark to the entire |
|
376 // Parser's state. Note: clients must still take care that any ParseContext |
|
377 // that points into released ParseNodes is destroyed. |
|
378 class Mark |
|
379 { |
|
380 friend class Parser; |
|
381 LifoAlloc::Mark mark; |
|
382 ObjectBox *traceListHead; |
|
383 }; |
|
384 Mark mark() const { |
|
385 Mark m; |
|
386 m.mark = alloc.mark(); |
|
387 m.traceListHead = traceListHead; |
|
388 return m; |
|
389 } |
|
390 void release(Mark m) { |
|
391 alloc.release(m.mark); |
|
392 traceListHead = m.traceListHead; |
|
393 } |
|
394 |
|
395 friend void js::frontend::MarkParser(JSTracer *trc, AutoGCRooter *parser); |
|
396 |
|
397 const char *getFilename() const { return tokenStream.getFilename(); } |
|
398 JSVersion versionNumber() const { return tokenStream.versionNumber(); } |
|
399 |
|
400 /* |
|
401 * Parse a top-level JS script. |
|
402 */ |
|
403 Node parse(JSObject *chain); |
|
404 |
|
405 /* |
|
406 * Allocate a new parsed object or function container from |
|
407 * cx->tempLifoAlloc. |
|
408 */ |
|
409 ObjectBox *newObjectBox(JSObject *obj); |
|
410 FunctionBox *newFunctionBox(Node fn, JSFunction *fun, ParseContext<ParseHandler> *pc, |
|
411 Directives directives, GeneratorKind generatorKind); |
|
412 |
|
413 /* |
|
414 * Create a new function object given parse context (pc) and a name (which |
|
415 * is optional if this is a function expression). |
|
416 */ |
|
417 JSFunction *newFunction(GenericParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind, |
|
418 JSObject *proto = nullptr); |
|
419 |
|
420 void trace(JSTracer *trc); |
|
421 |
|
422 bool hadAbortedSyntaxParse() { |
|
423 return abortedSyntaxParse; |
|
424 } |
|
425 void clearAbortedSyntaxParse() { |
|
426 abortedSyntaxParse = false; |
|
427 } |
|
428 |
|
429 bool isUnexpectedEOF() const { return isUnexpectedEOF_; } |
|
430 |
|
431 private: |
|
432 Parser *thisForCtor() { return this; } |
|
433 |
|
434 Node stringLiteral(); |
|
435 inline Node newName(PropertyName *name); |
|
436 |
|
437 inline bool abortIfSyntaxParser(); |
|
438 |
|
439 public: |
|
440 |
|
441 /* Public entry points for parsing. */ |
|
442 Node statement(bool canHaveDirectives = false); |
|
443 bool maybeParseDirective(Node list, Node pn, bool *cont); |
|
444 |
|
445 // Parse a function, given only its body. Used for the Function and |
|
446 // Generator constructors. |
|
447 Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals, |
|
448 GeneratorKind generatorKind, |
|
449 Directives inheritedDirectives, Directives *newDirectives); |
|
450 |
|
451 // Parse a function, given only its arguments and body. Used for lazily |
|
452 // parsed functions. |
|
453 Node standaloneLazyFunction(HandleFunction fun, unsigned staticLevel, bool strict, |
|
454 GeneratorKind generatorKind); |
|
455 |
|
456 /* |
|
457 * Parse a function body. Pass StatementListBody if the body is a list of |
|
458 * statements; pass ExpressionBody if the body is a single expression. |
|
459 */ |
|
460 enum FunctionBodyType { StatementListBody, ExpressionBody }; |
|
461 Node functionBody(FunctionSyntaxKind kind, FunctionBodyType type); |
|
462 |
|
463 bool functionArgsAndBodyGeneric(Node pn, HandleFunction fun, FunctionType type, |
|
464 FunctionSyntaxKind kind, Directives *newDirectives); |
|
465 |
|
466 // Determine whether |yield| is a valid name in the current context, or |
|
467 // whether it's prohibited due to strictness, JS version, or occurrence |
|
468 // inside a star generator. |
|
469 bool checkYieldNameValidity(); |
|
470 |
|
471 virtual bool strictMode() { return pc->sc->strict; } |
|
472 |
|
473 const ReadOnlyCompileOptions &options() const { |
|
474 return tokenStream.options(); |
|
475 } |
|
476 |
|
477 private: |
|
478 /* |
|
479 * JS parsers, from lowest to highest precedence. |
|
480 * |
|
481 * Each parser must be called during the dynamic scope of a ParseContext |
|
482 * object, pointed to by this->pc. |
|
483 * |
|
484 * Each returns a parse node tree or null on error. |
|
485 * |
|
486 * Parsers whose name has a '1' suffix leave the TokenStream state |
|
487 * pointing to the token one past the end of the parsed fragment. For a |
|
488 * number of the parsers this is convenient and avoids a lot of |
|
489 * unnecessary ungetting and regetting of tokens. |
|
490 * |
|
491 * Some parsers have two versions: an always-inlined version (with an 'i' |
|
492 * suffix) and a never-inlined version (with an 'n' suffix). |
|
493 */ |
|
494 Node functionStmt(); |
|
495 Node functionExpr(); |
|
496 Node statements(); |
|
497 |
|
498 Node blockStatement(); |
|
499 Node ifStatement(); |
|
500 Node doWhileStatement(); |
|
501 Node whileStatement(); |
|
502 Node forStatement(); |
|
503 Node switchStatement(); |
|
504 Node continueStatement(); |
|
505 Node breakStatement(); |
|
506 Node returnStatement(); |
|
507 Node withStatement(); |
|
508 Node labeledStatement(); |
|
509 Node throwStatement(); |
|
510 Node tryStatement(); |
|
511 Node debuggerStatement(); |
|
512 |
|
513 Node letDeclaration(); |
|
514 Node letStatement(); |
|
515 Node importDeclaration(); |
|
516 Node exportDeclaration(); |
|
517 Node expressionStatement(); |
|
518 Node variables(ParseNodeKind kind, bool *psimple = nullptr, |
|
519 StaticBlockObject *blockObj = nullptr, |
|
520 VarContext varContext = HoistVars); |
|
521 Node expr(); |
|
522 Node assignExpr(); |
|
523 Node assignExprWithoutYield(unsigned err); |
|
524 Node yieldExpression(); |
|
525 Node condExpr1(); |
|
526 Node orExpr1(); |
|
527 Node unaryExpr(); |
|
528 Node memberExpr(TokenKind tt, bool allowCallSyntax); |
|
529 Node primaryExpr(TokenKind tt); |
|
530 Node parenExprOrGeneratorComprehension(); |
|
531 Node exprInParens(); |
|
532 |
|
533 /* |
|
534 * Additional JS parsers. |
|
535 */ |
|
536 bool functionArguments(FunctionSyntaxKind kind, Node *list, Node funcpn, bool *hasRest); |
|
537 |
|
538 Node functionDef(HandlePropertyName name, const TokenStream::Position &start, |
|
539 FunctionType type, FunctionSyntaxKind kind, GeneratorKind generatorKind); |
|
540 bool functionArgsAndBody(Node pn, HandleFunction fun, |
|
541 FunctionType type, FunctionSyntaxKind kind, |
|
542 GeneratorKind generatorKind, |
|
543 Directives inheritedDirectives, Directives *newDirectives); |
|
544 |
|
545 Node unaryOpExpr(ParseNodeKind kind, JSOp op, uint32_t begin); |
|
546 |
|
547 Node condition(); |
|
548 |
|
549 Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin, |
|
550 Node innerStmt); |
|
551 |
|
552 Node legacyComprehensionTail(Node kid, unsigned blockid, GeneratorKind comprehensionKind, |
|
553 ParseContext<ParseHandler> *outerpc, |
|
554 unsigned innerBlockScopeDepth); |
|
555 Node legacyArrayComprehension(Node array); |
|
556 Node legacyGeneratorExpr(Node kid); |
|
557 |
|
558 Node comprehensionTail(GeneratorKind comprehensionKind); |
|
559 Node comprehensionIf(GeneratorKind comprehensionKind); |
|
560 Node comprehensionFor(GeneratorKind comprehensionKind); |
|
561 Node comprehension(GeneratorKind comprehensionKind); |
|
562 Node arrayComprehension(uint32_t begin); |
|
563 Node generatorComprehension(uint32_t begin); |
|
564 |
|
565 bool argumentList(Node listNode, bool *isSpread); |
|
566 Node letBlock(LetContext letContext); |
|
567 Node destructuringExpr(BindData<ParseHandler> *data, TokenKind tt); |
|
568 |
|
569 Node identifierName(); |
|
570 |
|
571 bool matchLabel(MutableHandle<PropertyName*> label); |
|
572 |
|
573 bool allowsForEachIn() { |
|
574 #if !JS_HAS_FOR_EACH_IN |
|
575 return false; |
|
576 #else |
|
577 return versionNumber() >= JSVERSION_1_6; |
|
578 #endif |
|
579 } |
|
580 |
|
581 enum AssignmentFlavor { |
|
582 PlainAssignment, |
|
583 CompoundAssignment, |
|
584 KeyedDestructuringAssignment, |
|
585 IncDecAssignment |
|
586 }; |
|
587 |
|
588 bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor); |
|
589 bool matchInOrOf(bool *isForOfp); |
|
590 |
|
591 bool checkFunctionArguments(); |
|
592 bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom); |
|
593 bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind, |
|
594 bool *pbodyProcessed); |
|
595 bool finishFunctionDefinition(Node pn, FunctionBox *funbox, Node prelude, Node body); |
|
596 bool addFreeVariablesFromLazyFunction(JSFunction *fun, ParseContext<ParseHandler> *pc); |
|
597 |
|
598 bool isValidForStatementLHS(Node pn1, JSVersion version, bool forDecl, bool forEach, |
|
599 ParseNodeKind headKind); |
|
600 bool checkAndMarkAsIncOperand(Node kid, TokenKind tt, bool preorder); |
|
601 bool checkStrictAssignment(Node lhs, AssignmentFlavor flavor); |
|
602 bool checkStrictBinding(PropertyName *name, Node pn); |
|
603 bool defineArg(Node funcpn, HandlePropertyName name, |
|
604 bool disallowDuplicateArgs = false, Node *duplicatedArg = nullptr); |
|
605 Node pushLexicalScope(StmtInfoPC *stmt); |
|
606 Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt); |
|
607 Node pushLetScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt); |
|
608 bool noteNameUse(HandlePropertyName name, Node pn); |
|
609 Node objectLiteral(); |
|
610 Node arrayInitializer(); |
|
611 Node newRegExp(); |
|
612 |
|
613 Node newBindingNode(PropertyName *name, bool functionScope, VarContext varContext = HoistVars); |
|
614 bool checkDestructuring(BindData<ParseHandler> *data, Node left, bool toplevel = true); |
|
615 bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn); |
|
616 bool bindDestructuringLHS(Node pn); |
|
617 bool makeSetCall(Node pn, unsigned msg); |
|
618 Node cloneLeftHandSide(Node opn); |
|
619 Node cloneParseTree(Node opn); |
|
620 |
|
621 Node newNumber(const Token &tok) { |
|
622 return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos); |
|
623 } |
|
624 |
|
625 static bool |
|
626 bindDestructuringArg(BindData<ParseHandler> *data, |
|
627 HandlePropertyName name, Parser<ParseHandler> *parser); |
|
628 |
|
629 static bool |
|
630 bindLet(BindData<ParseHandler> *data, |
|
631 HandlePropertyName name, Parser<ParseHandler> *parser); |
|
632 |
|
633 static bool |
|
634 bindVarOrConst(BindData<ParseHandler> *data, |
|
635 HandlePropertyName name, Parser<ParseHandler> *parser); |
|
636 |
|
637 static Node null() { return ParseHandler::null(); } |
|
638 |
|
639 bool reportRedeclaration(Node pn, bool isConst, JSAtom *atom); |
|
640 bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum); |
|
641 bool checkFinalReturn(Node pn); |
|
642 DefinitionNode getOrCreateLexicalDependency(ParseContext<ParseHandler> *pc, JSAtom *atom); |
|
643 |
|
644 bool leaveFunction(Node fn, ParseContext<ParseHandler> *outerpc, |
|
645 FunctionSyntaxKind kind = Expression); |
|
646 |
|
647 TokenPos pos() const { return tokenStream.currentToken().pos; } |
|
648 |
|
649 bool asmJS(Node list); |
|
650 |
|
651 friend class LegacyCompExprTransplanter; |
|
652 friend struct BindData<ParseHandler>; |
|
653 }; |
|
654 |
|
655 /* Declare some required template specializations. */ |
|
656 |
|
657 template <> |
|
658 bool |
|
659 Parser<FullParseHandler>::checkAndMarkAsAssignmentLhs(ParseNode *pn, AssignmentFlavor flavor); |
|
660 |
|
661 template <> |
|
662 bool |
|
663 Parser<SyntaxParseHandler>::checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor); |
|
664 |
|
665 } /* namespace frontend */ |
|
666 } /* namespace js */ |
|
667 |
|
668 /* |
|
669 * Convenience macro to access Parser.tokenStream as a pointer. |
|
670 */ |
|
671 #define TS(p) (&(p)->tokenStream) |
|
672 |
|
673 #endif /* frontend_Parser_h */ |