1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/frontend/Parser.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,673 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef frontend_Parser_h 1.11 +#define frontend_Parser_h 1.12 + 1.13 +/* 1.14 + * JS parser definitions. 1.15 + */ 1.16 + 1.17 +#include "jspubtd.h" 1.18 + 1.19 +#include "frontend/BytecodeCompiler.h" 1.20 +#include "frontend/FullParseHandler.h" 1.21 +#include "frontend/ParseMaps.h" 1.22 +#include "frontend/ParseNode.h" 1.23 +#include "frontend/SharedContext.h" 1.24 +#include "frontend/SyntaxParseHandler.h" 1.25 + 1.26 +namespace js { 1.27 +namespace frontend { 1.28 + 1.29 +struct StmtInfoPC : public StmtInfoBase { 1.30 + StmtInfoPC *down; /* info for enclosing statement */ 1.31 + StmtInfoPC *downScope; /* next enclosing lexical scope */ 1.32 + 1.33 + uint32_t blockid; /* for simplified dominance computation */ 1.34 + uint32_t innerBlockScopeDepth; /* maximum depth of nested block scopes, in slots */ 1.35 + 1.36 + StmtInfoPC(ExclusiveContext *cx) : StmtInfoBase(cx), innerBlockScopeDepth(0) {} 1.37 +}; 1.38 + 1.39 +typedef HashSet<JSAtom *> FuncStmtSet; 1.40 +class SharedContext; 1.41 + 1.42 +typedef Vector<Definition *, 16> DeclVector; 1.43 + 1.44 +struct GenericParseContext 1.45 +{ 1.46 + // Enclosing function or global context. 1.47 + GenericParseContext *parent; 1.48 + 1.49 + // Context shared between parsing and bytecode generation. 1.50 + SharedContext *sc; 1.51 + 1.52 + // The following flags are set when a particular code feature is detected 1.53 + // in a function. 1.54 + 1.55 + // Function has 'return <expr>;' 1.56 + bool funHasReturnExpr:1; 1.57 + 1.58 + // Function has 'return;' 1.59 + bool funHasReturnVoid:1; 1.60 + 1.61 + // The following flags are set when parsing enters a particular region of 1.62 + // source code, and cleared when that region is exited. 1.63 + 1.64 + // true while parsing init expr of for; exclude 'in' 1.65 + bool parsingForInit:1; 1.66 + 1.67 + // true while we are within a with-statement in the current ParseContext 1.68 + // chain (which stops at the top-level or an eval() 1.69 + bool parsingWith:1; 1.70 + 1.71 + GenericParseContext(GenericParseContext *parent, SharedContext *sc) 1.72 + : parent(parent), 1.73 + sc(sc), 1.74 + funHasReturnExpr(false), 1.75 + funHasReturnVoid(false), 1.76 + parsingForInit(false), 1.77 + parsingWith(parent ? parent->parsingWith : false) 1.78 + {} 1.79 +}; 1.80 + 1.81 +template <typename ParseHandler> 1.82 +bool 1.83 +GenerateBlockId(TokenStream &ts, ParseContext<ParseHandler> *pc, uint32_t &blockid); 1.84 + 1.85 +/* 1.86 + * The struct ParseContext stores information about the current parsing context, 1.87 + * which is part of the parser state (see the field Parser::pc). The current 1.88 + * parsing context is either the global context, or the function currently being 1.89 + * parsed. When the parser encounters a function definition, it creates a new 1.90 + * ParseContext, makes it the new current context, and sets its parent to the 1.91 + * context in which it encountered the definition. 1.92 + */ 1.93 +template <typename ParseHandler> 1.94 +struct ParseContext : public GenericParseContext 1.95 +{ 1.96 + typedef StmtInfoPC StmtInfo; 1.97 + typedef typename ParseHandler::Node Node; 1.98 + typedef typename ParseHandler::DefinitionNode DefinitionNode; 1.99 + 1.100 + uint32_t bodyid; /* block number of program/function body */ 1.101 + uint32_t blockidGen; /* preincremented block number generator */ 1.102 + 1.103 + StmtInfoPC *topStmt; /* top of statement info stack */ 1.104 + StmtInfoPC *topScopeStmt; /* top lexical scope statement */ 1.105 + Rooted<NestedScopeObject *> staticScope; /* compile time scope chain */ 1.106 + Node maybeFunction; /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */ 1.107 + 1.108 + const unsigned staticLevel; /* static compilation unit nesting level */ 1.109 + 1.110 + // lastYieldOffset stores the offset of the last yield that was parsed. 1.111 + // NoYieldOffset is its initial value. 1.112 + static const uint32_t NoYieldOffset = UINT32_MAX; 1.113 + uint32_t lastYieldOffset; 1.114 + 1.115 + // Most functions start off being parsed as non-generators. 1.116 + // Non-generators transition to LegacyGenerator on parsing "yield" in JS 1.7. 1.117 + // An ES6 generator is marked as a "star generator" before its body is parsed. 1.118 + GeneratorKind generatorKind() const { 1.119 + return sc->isFunctionBox() ? sc->asFunctionBox()->generatorKind() : NotGenerator; 1.120 + } 1.121 + bool isGenerator() const { return generatorKind() != NotGenerator; } 1.122 + bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; } 1.123 + bool isStarGenerator() const { return generatorKind() == StarGenerator; } 1.124 + 1.125 + bool isArrowFunction() const { 1.126 + return sc->isFunctionBox() && sc->asFunctionBox()->function()->isArrow(); 1.127 + } 1.128 + 1.129 + uint32_t blockScopeDepth; /* maximum depth of nested block scopes, in slots */ 1.130 + Node blockNode; /* parse node for a block with let declarations 1.131 + (block with its own lexical scope) */ 1.132 + private: 1.133 + AtomDecls<ParseHandler> decls_; /* function, const, and var declarations */ 1.134 + DeclVector args_; /* argument definitions */ 1.135 + DeclVector vars_; /* var/const definitions */ 1.136 + 1.137 + public: 1.138 + const AtomDecls<ParseHandler> &decls() const { 1.139 + return decls_; 1.140 + } 1.141 + 1.142 + uint32_t numArgs() const { 1.143 + JS_ASSERT(sc->isFunctionBox()); 1.144 + return args_.length(); 1.145 + } 1.146 + 1.147 + /* 1.148 + * This function adds a definition to the lexical scope represented by this 1.149 + * ParseContext. 1.150 + * 1.151 + * Pre-conditions: 1.152 + * + The caller must have already taken care of name collisions: 1.153 + * - For non-let definitions, this means 'name' isn't in 'decls'. 1.154 + * - For let definitions, this means 'name' isn't already a name in the 1.155 + * current block. 1.156 + * + The given 'pn' is either a placeholder (created by a previous unbound 1.157 + * use) or an un-bound un-linked name node. 1.158 + * + The given 'kind' is one of ARG, CONST, VAR, or LET. In particular, 1.159 + * NAMED_LAMBDA is handled in an ad hoc special case manner (see 1.160 + * LeaveFunction) that we should consider rewriting. 1.161 + * 1.162 + * Post-conditions: 1.163 + * + pc->decls().lookupFirst(name) == pn 1.164 + * + The given name 'pn' has been converted in-place into a 1.165 + * non-placeholder definition. 1.166 + * + If this is a function scope (sc->inFunction), 'pn' is bound to a 1.167 + * particular local/argument slot. 1.168 + * + PND_CONST is set for Definition::COSNT 1.169 + * + Pre-existing uses of pre-existing placeholders have been linked to 1.170 + * 'pn' if they are in the scope of 'pn'. 1.171 + * + Pre-existing placeholders in the scope of 'pn' have been removed. 1.172 + */ 1.173 + bool define(TokenStream &ts, HandlePropertyName name, Node pn, Definition::Kind); 1.174 + 1.175 + /* 1.176 + * Let definitions may shadow same-named definitions in enclosing scopes. 1.177 + * To represesent this, 'decls' is not a plain map, but actually: 1.178 + * decls :: name -> stack of definitions 1.179 + * New bindings are pushed onto the stack, name lookup always refers to the 1.180 + * top of the stack, and leaving a block scope calls popLetDecl for each 1.181 + * name in the block's scope. 1.182 + */ 1.183 + void popLetDecl(JSAtom *atom); 1.184 + 1.185 + /* See the sad story in defineArg. */ 1.186 + void prepareToAddDuplicateArg(HandlePropertyName name, DefinitionNode prevDecl); 1.187 + 1.188 + /* See the sad story in MakeDefIntoUse. */ 1.189 + void updateDecl(JSAtom *atom, Node newDecl); 1.190 + 1.191 + /* 1.192 + * After a function body has been parsed, the parser generates the 1.193 + * function's "bindings". Bindings are a data-structure, ultimately stored 1.194 + * in the compiled JSScript, that serve three purposes: 1.195 + * - After parsing, the ParseContext is destroyed and 'decls' along with 1.196 + * it. Mostly, the emitter just uses the binding information stored in 1.197 + * the use/def nodes, but the emitter occasionally needs 'bindings' for 1.198 + * various scope-related queries. 1.199 + * - Bindings provide the initial js::Shape to use when creating a dynamic 1.200 + * scope object (js::CallObject) for the function. This shape is used 1.201 + * during dynamic name lookup. 1.202 + * - Sometimes a script's bindings are accessed at runtime to retrieve the 1.203 + * contents of the lexical scope (e.g., from the debugger). 1.204 + */ 1.205 + bool generateFunctionBindings(ExclusiveContext *cx, TokenStream &ts, 1.206 + LifoAlloc &alloc, 1.207 + InternalHandle<Bindings*> bindings) const; 1.208 + 1.209 + private: 1.210 + ParseContext **parserPC; /* this points to the Parser's active pc 1.211 + and holds either |this| or one of 1.212 + |this|'s descendents */ 1.213 + 1.214 + // Value for parserPC to restore at the end. Use 'parent' instead for 1.215 + // information about the parse chain, this may be nullptr if 1.216 + // parent != nullptr. 1.217 + ParseContext<ParseHandler> *oldpc; 1.218 + 1.219 + public: 1.220 + OwnedAtomDefnMapPtr lexdeps; /* unresolved lexical name dependencies */ 1.221 + 1.222 + FuncStmtSet *funcStmts; /* Set of (non-top-level) function statements 1.223 + that will alias any top-level bindings with 1.224 + the same name. */ 1.225 + 1.226 + // All inner functions in this context. Only filled in when parsing syntax. 1.227 + AutoFunctionVector innerFunctions; 1.228 + 1.229 + // In a function context, points to a Directive struct that can be updated 1.230 + // to reflect new directives encountered in the Directive Prologue that 1.231 + // require reparsing the function. In global/module/generator-tail contexts, 1.232 + // we don't need to reparse when encountering a DirectivePrologue so this 1.233 + // pointer may be nullptr. 1.234 + Directives *newDirectives; 1.235 + 1.236 + // Set when parsing a declaration-like destructuring pattern. This flag 1.237 + // causes PrimaryExpr to create PN_NAME parse nodes for variable references 1.238 + // which are not hooked into any definition's use chain, added to any tree 1.239 + // context's AtomList, etc. etc. CheckDestructuring will do that work 1.240 + // later. 1.241 + // 1.242 + // The comments atop CheckDestructuring explain the distinction between 1.243 + // assignment-like and declaration-like destructuring patterns, and why 1.244 + // they need to be treated differently. 1.245 + bool inDeclDestructuring:1; 1.246 + 1.247 + ParseContext(Parser<ParseHandler> *prs, GenericParseContext *parent, 1.248 + Node maybeFunction, SharedContext *sc, 1.249 + Directives *newDirectives, 1.250 + unsigned staticLevel, uint32_t bodyid, uint32_t blockScopeDepth) 1.251 + : GenericParseContext(parent, sc), 1.252 + bodyid(0), // initialized in init() 1.253 + blockidGen(bodyid), // used to set |bodyid| and subsequently incremented in init() 1.254 + topStmt(nullptr), 1.255 + topScopeStmt(nullptr), 1.256 + staticScope(prs->context), 1.257 + maybeFunction(maybeFunction), 1.258 + staticLevel(staticLevel), 1.259 + lastYieldOffset(NoYieldOffset), 1.260 + blockScopeDepth(blockScopeDepth), 1.261 + blockNode(ParseHandler::null()), 1.262 + decls_(prs->context, prs->alloc), 1.263 + args_(prs->context), 1.264 + vars_(prs->context), 1.265 + parserPC(&prs->pc), 1.266 + oldpc(prs->pc), 1.267 + lexdeps(prs->context), 1.268 + funcStmts(nullptr), 1.269 + innerFunctions(prs->context), 1.270 + newDirectives(newDirectives), 1.271 + inDeclDestructuring(false) 1.272 + { 1.273 + prs->pc = this; 1.274 + } 1.275 + 1.276 + ~ParseContext(); 1.277 + 1.278 + bool init(TokenStream &ts); 1.279 + 1.280 + unsigned blockid() { return topStmt ? topStmt->blockid : bodyid; } 1.281 + 1.282 + // True if we are at the topmost level of a entire script or function body. 1.283 + // For example, while parsing this code we would encounter f1 and f2 at 1.284 + // body level, but we would not encounter f3 or f4 at body level: 1.285 + // 1.286 + // function f1() { function f2() { } } 1.287 + // if (cond) { function f3() { if (cond) { function f4() { } } } } 1.288 + // 1.289 + bool atBodyLevel() { return !topStmt; } 1.290 + 1.291 + // True if this is the ParseContext for the body of a function created by 1.292 + // the Function constructor. 1.293 + bool isFunctionConstructorBody() const { 1.294 + return sc->isFunctionBox() && staticLevel == 0; 1.295 + } 1.296 + 1.297 + inline bool useAsmOrInsideUseAsm() const { 1.298 + return sc->isFunctionBox() && sc->asFunctionBox()->useAsmOrInsideUseAsm(); 1.299 + } 1.300 +}; 1.301 + 1.302 +template <typename ParseHandler> 1.303 +inline 1.304 +Directives::Directives(ParseContext<ParseHandler> *parent) 1.305 + : strict_(parent->sc->strict), 1.306 + asmJS_(parent->useAsmOrInsideUseAsm()) 1.307 +{} 1.308 + 1.309 +template <typename ParseHandler> 1.310 +struct BindData; 1.311 + 1.312 +class CompExprTransplanter; 1.313 + 1.314 +enum LetContext { LetExpresion, LetStatement }; 1.315 +enum VarContext { HoistVars, DontHoistVars }; 1.316 +enum FunctionType { Getter, Setter, Normal }; 1.317 + 1.318 +template <typename ParseHandler> 1.319 +class Parser : private AutoGCRooter, public StrictModeGetter 1.320 +{ 1.321 + public: 1.322 + ExclusiveContext *const context; 1.323 + LifoAlloc &alloc; 1.324 + 1.325 + TokenStream tokenStream; 1.326 + LifoAlloc::Mark tempPoolMark; 1.327 + 1.328 + /* list of parsed objects for GC tracing */ 1.329 + ObjectBox *traceListHead; 1.330 + 1.331 + /* innermost parse context (stack-allocated) */ 1.332 + ParseContext<ParseHandler> *pc; 1.333 + 1.334 + /* Compression token for aborting. */ 1.335 + SourceCompressionTask *sct; 1.336 + 1.337 + ScriptSource *ss; 1.338 + 1.339 + /* Root atoms and objects allocated for the parsed tree. */ 1.340 + AutoKeepAtoms keepAtoms; 1.341 + 1.342 + /* Perform constant-folding; must be true when interfacing with the emitter. */ 1.343 + const bool foldConstants:1; 1.344 + 1.345 + private: 1.346 + /* 1.347 + * Not all language constructs can be handled during syntax parsing. If it 1.348 + * is not known whether the parse succeeds or fails, this bit is set and 1.349 + * the parse will return false. 1.350 + */ 1.351 + bool abortedSyntaxParse:1; 1.352 + 1.353 + /* Unexpected end of input, i.e. TOK_EOF not at top-level. */ 1.354 + bool isUnexpectedEOF_:1; 1.355 + 1.356 + typedef typename ParseHandler::Node Node; 1.357 + typedef typename ParseHandler::DefinitionNode DefinitionNode; 1.358 + 1.359 + public: 1.360 + /* State specific to the kind of parse being performed. */ 1.361 + ParseHandler handler; 1.362 + 1.363 + private: 1.364 + bool reportHelper(ParseReportKind kind, bool strict, uint32_t offset, 1.365 + unsigned errorNumber, va_list args); 1.366 + public: 1.367 + bool report(ParseReportKind kind, bool strict, Node pn, unsigned errorNumber, ...); 1.368 + bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...); 1.369 + bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber, 1.370 + ...); 1.371 + 1.372 + Parser(ExclusiveContext *cx, LifoAlloc *alloc, const ReadOnlyCompileOptions &options, 1.373 + const jschar *chars, size_t length, bool foldConstants, 1.374 + Parser<SyntaxParseHandler> *syntaxParser, 1.375 + LazyScript *lazyOuterFunction); 1.376 + ~Parser(); 1.377 + 1.378 + // A Parser::Mark is the extension of the LifoAlloc::Mark to the entire 1.379 + // Parser's state. Note: clients must still take care that any ParseContext 1.380 + // that points into released ParseNodes is destroyed. 1.381 + class Mark 1.382 + { 1.383 + friend class Parser; 1.384 + LifoAlloc::Mark mark; 1.385 + ObjectBox *traceListHead; 1.386 + }; 1.387 + Mark mark() const { 1.388 + Mark m; 1.389 + m.mark = alloc.mark(); 1.390 + m.traceListHead = traceListHead; 1.391 + return m; 1.392 + } 1.393 + void release(Mark m) { 1.394 + alloc.release(m.mark); 1.395 + traceListHead = m.traceListHead; 1.396 + } 1.397 + 1.398 + friend void js::frontend::MarkParser(JSTracer *trc, AutoGCRooter *parser); 1.399 + 1.400 + const char *getFilename() const { return tokenStream.getFilename(); } 1.401 + JSVersion versionNumber() const { return tokenStream.versionNumber(); } 1.402 + 1.403 + /* 1.404 + * Parse a top-level JS script. 1.405 + */ 1.406 + Node parse(JSObject *chain); 1.407 + 1.408 + /* 1.409 + * Allocate a new parsed object or function container from 1.410 + * cx->tempLifoAlloc. 1.411 + */ 1.412 + ObjectBox *newObjectBox(JSObject *obj); 1.413 + FunctionBox *newFunctionBox(Node fn, JSFunction *fun, ParseContext<ParseHandler> *pc, 1.414 + Directives directives, GeneratorKind generatorKind); 1.415 + 1.416 + /* 1.417 + * Create a new function object given parse context (pc) and a name (which 1.418 + * is optional if this is a function expression). 1.419 + */ 1.420 + JSFunction *newFunction(GenericParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind, 1.421 + JSObject *proto = nullptr); 1.422 + 1.423 + void trace(JSTracer *trc); 1.424 + 1.425 + bool hadAbortedSyntaxParse() { 1.426 + return abortedSyntaxParse; 1.427 + } 1.428 + void clearAbortedSyntaxParse() { 1.429 + abortedSyntaxParse = false; 1.430 + } 1.431 + 1.432 + bool isUnexpectedEOF() const { return isUnexpectedEOF_; } 1.433 + 1.434 + private: 1.435 + Parser *thisForCtor() { return this; } 1.436 + 1.437 + Node stringLiteral(); 1.438 + inline Node newName(PropertyName *name); 1.439 + 1.440 + inline bool abortIfSyntaxParser(); 1.441 + 1.442 + public: 1.443 + 1.444 + /* Public entry points for parsing. */ 1.445 + Node statement(bool canHaveDirectives = false); 1.446 + bool maybeParseDirective(Node list, Node pn, bool *cont); 1.447 + 1.448 + // Parse a function, given only its body. Used for the Function and 1.449 + // Generator constructors. 1.450 + Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals, 1.451 + GeneratorKind generatorKind, 1.452 + Directives inheritedDirectives, Directives *newDirectives); 1.453 + 1.454 + // Parse a function, given only its arguments and body. Used for lazily 1.455 + // parsed functions. 1.456 + Node standaloneLazyFunction(HandleFunction fun, unsigned staticLevel, bool strict, 1.457 + GeneratorKind generatorKind); 1.458 + 1.459 + /* 1.460 + * Parse a function body. Pass StatementListBody if the body is a list of 1.461 + * statements; pass ExpressionBody if the body is a single expression. 1.462 + */ 1.463 + enum FunctionBodyType { StatementListBody, ExpressionBody }; 1.464 + Node functionBody(FunctionSyntaxKind kind, FunctionBodyType type); 1.465 + 1.466 + bool functionArgsAndBodyGeneric(Node pn, HandleFunction fun, FunctionType type, 1.467 + FunctionSyntaxKind kind, Directives *newDirectives); 1.468 + 1.469 + // Determine whether |yield| is a valid name in the current context, or 1.470 + // whether it's prohibited due to strictness, JS version, or occurrence 1.471 + // inside a star generator. 1.472 + bool checkYieldNameValidity(); 1.473 + 1.474 + virtual bool strictMode() { return pc->sc->strict; } 1.475 + 1.476 + const ReadOnlyCompileOptions &options() const { 1.477 + return tokenStream.options(); 1.478 + } 1.479 + 1.480 + private: 1.481 + /* 1.482 + * JS parsers, from lowest to highest precedence. 1.483 + * 1.484 + * Each parser must be called during the dynamic scope of a ParseContext 1.485 + * object, pointed to by this->pc. 1.486 + * 1.487 + * Each returns a parse node tree or null on error. 1.488 + * 1.489 + * Parsers whose name has a '1' suffix leave the TokenStream state 1.490 + * pointing to the token one past the end of the parsed fragment. For a 1.491 + * number of the parsers this is convenient and avoids a lot of 1.492 + * unnecessary ungetting and regetting of tokens. 1.493 + * 1.494 + * Some parsers have two versions: an always-inlined version (with an 'i' 1.495 + * suffix) and a never-inlined version (with an 'n' suffix). 1.496 + */ 1.497 + Node functionStmt(); 1.498 + Node functionExpr(); 1.499 + Node statements(); 1.500 + 1.501 + Node blockStatement(); 1.502 + Node ifStatement(); 1.503 + Node doWhileStatement(); 1.504 + Node whileStatement(); 1.505 + Node forStatement(); 1.506 + Node switchStatement(); 1.507 + Node continueStatement(); 1.508 + Node breakStatement(); 1.509 + Node returnStatement(); 1.510 + Node withStatement(); 1.511 + Node labeledStatement(); 1.512 + Node throwStatement(); 1.513 + Node tryStatement(); 1.514 + Node debuggerStatement(); 1.515 + 1.516 + Node letDeclaration(); 1.517 + Node letStatement(); 1.518 + Node importDeclaration(); 1.519 + Node exportDeclaration(); 1.520 + Node expressionStatement(); 1.521 + Node variables(ParseNodeKind kind, bool *psimple = nullptr, 1.522 + StaticBlockObject *blockObj = nullptr, 1.523 + VarContext varContext = HoistVars); 1.524 + Node expr(); 1.525 + Node assignExpr(); 1.526 + Node assignExprWithoutYield(unsigned err); 1.527 + Node yieldExpression(); 1.528 + Node condExpr1(); 1.529 + Node orExpr1(); 1.530 + Node unaryExpr(); 1.531 + Node memberExpr(TokenKind tt, bool allowCallSyntax); 1.532 + Node primaryExpr(TokenKind tt); 1.533 + Node parenExprOrGeneratorComprehension(); 1.534 + Node exprInParens(); 1.535 + 1.536 + /* 1.537 + * Additional JS parsers. 1.538 + */ 1.539 + bool functionArguments(FunctionSyntaxKind kind, Node *list, Node funcpn, bool *hasRest); 1.540 + 1.541 + Node functionDef(HandlePropertyName name, const TokenStream::Position &start, 1.542 + FunctionType type, FunctionSyntaxKind kind, GeneratorKind generatorKind); 1.543 + bool functionArgsAndBody(Node pn, HandleFunction fun, 1.544 + FunctionType type, FunctionSyntaxKind kind, 1.545 + GeneratorKind generatorKind, 1.546 + Directives inheritedDirectives, Directives *newDirectives); 1.547 + 1.548 + Node unaryOpExpr(ParseNodeKind kind, JSOp op, uint32_t begin); 1.549 + 1.550 + Node condition(); 1.551 + 1.552 + Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin, 1.553 + Node innerStmt); 1.554 + 1.555 + Node legacyComprehensionTail(Node kid, unsigned blockid, GeneratorKind comprehensionKind, 1.556 + ParseContext<ParseHandler> *outerpc, 1.557 + unsigned innerBlockScopeDepth); 1.558 + Node legacyArrayComprehension(Node array); 1.559 + Node legacyGeneratorExpr(Node kid); 1.560 + 1.561 + Node comprehensionTail(GeneratorKind comprehensionKind); 1.562 + Node comprehensionIf(GeneratorKind comprehensionKind); 1.563 + Node comprehensionFor(GeneratorKind comprehensionKind); 1.564 + Node comprehension(GeneratorKind comprehensionKind); 1.565 + Node arrayComprehension(uint32_t begin); 1.566 + Node generatorComprehension(uint32_t begin); 1.567 + 1.568 + bool argumentList(Node listNode, bool *isSpread); 1.569 + Node letBlock(LetContext letContext); 1.570 + Node destructuringExpr(BindData<ParseHandler> *data, TokenKind tt); 1.571 + 1.572 + Node identifierName(); 1.573 + 1.574 + bool matchLabel(MutableHandle<PropertyName*> label); 1.575 + 1.576 + bool allowsForEachIn() { 1.577 +#if !JS_HAS_FOR_EACH_IN 1.578 + return false; 1.579 +#else 1.580 + return versionNumber() >= JSVERSION_1_6; 1.581 +#endif 1.582 + } 1.583 + 1.584 + enum AssignmentFlavor { 1.585 + PlainAssignment, 1.586 + CompoundAssignment, 1.587 + KeyedDestructuringAssignment, 1.588 + IncDecAssignment 1.589 + }; 1.590 + 1.591 + bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor); 1.592 + bool matchInOrOf(bool *isForOfp); 1.593 + 1.594 + bool checkFunctionArguments(); 1.595 + bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom); 1.596 + bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind, 1.597 + bool *pbodyProcessed); 1.598 + bool finishFunctionDefinition(Node pn, FunctionBox *funbox, Node prelude, Node body); 1.599 + bool addFreeVariablesFromLazyFunction(JSFunction *fun, ParseContext<ParseHandler> *pc); 1.600 + 1.601 + bool isValidForStatementLHS(Node pn1, JSVersion version, bool forDecl, bool forEach, 1.602 + ParseNodeKind headKind); 1.603 + bool checkAndMarkAsIncOperand(Node kid, TokenKind tt, bool preorder); 1.604 + bool checkStrictAssignment(Node lhs, AssignmentFlavor flavor); 1.605 + bool checkStrictBinding(PropertyName *name, Node pn); 1.606 + bool defineArg(Node funcpn, HandlePropertyName name, 1.607 + bool disallowDuplicateArgs = false, Node *duplicatedArg = nullptr); 1.608 + Node pushLexicalScope(StmtInfoPC *stmt); 1.609 + Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt); 1.610 + Node pushLetScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt); 1.611 + bool noteNameUse(HandlePropertyName name, Node pn); 1.612 + Node objectLiteral(); 1.613 + Node arrayInitializer(); 1.614 + Node newRegExp(); 1.615 + 1.616 + Node newBindingNode(PropertyName *name, bool functionScope, VarContext varContext = HoistVars); 1.617 + bool checkDestructuring(BindData<ParseHandler> *data, Node left, bool toplevel = true); 1.618 + bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn); 1.619 + bool bindDestructuringLHS(Node pn); 1.620 + bool makeSetCall(Node pn, unsigned msg); 1.621 + Node cloneLeftHandSide(Node opn); 1.622 + Node cloneParseTree(Node opn); 1.623 + 1.624 + Node newNumber(const Token &tok) { 1.625 + return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos); 1.626 + } 1.627 + 1.628 + static bool 1.629 + bindDestructuringArg(BindData<ParseHandler> *data, 1.630 + HandlePropertyName name, Parser<ParseHandler> *parser); 1.631 + 1.632 + static bool 1.633 + bindLet(BindData<ParseHandler> *data, 1.634 + HandlePropertyName name, Parser<ParseHandler> *parser); 1.635 + 1.636 + static bool 1.637 + bindVarOrConst(BindData<ParseHandler> *data, 1.638 + HandlePropertyName name, Parser<ParseHandler> *parser); 1.639 + 1.640 + static Node null() { return ParseHandler::null(); } 1.641 + 1.642 + bool reportRedeclaration(Node pn, bool isConst, JSAtom *atom); 1.643 + bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum); 1.644 + bool checkFinalReturn(Node pn); 1.645 + DefinitionNode getOrCreateLexicalDependency(ParseContext<ParseHandler> *pc, JSAtom *atom); 1.646 + 1.647 + bool leaveFunction(Node fn, ParseContext<ParseHandler> *outerpc, 1.648 + FunctionSyntaxKind kind = Expression); 1.649 + 1.650 + TokenPos pos() const { return tokenStream.currentToken().pos; } 1.651 + 1.652 + bool asmJS(Node list); 1.653 + 1.654 + friend class LegacyCompExprTransplanter; 1.655 + friend struct BindData<ParseHandler>; 1.656 +}; 1.657 + 1.658 +/* Declare some required template specializations. */ 1.659 + 1.660 +template <> 1.661 +bool 1.662 +Parser<FullParseHandler>::checkAndMarkAsAssignmentLhs(ParseNode *pn, AssignmentFlavor flavor); 1.663 + 1.664 +template <> 1.665 +bool 1.666 +Parser<SyntaxParseHandler>::checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor); 1.667 + 1.668 +} /* namespace frontend */ 1.669 +} /* namespace js */ 1.670 + 1.671 +/* 1.672 + * Convenience macro to access Parser.tokenStream as a pointer. 1.673 + */ 1.674 +#define TS(p) (&(p)->tokenStream) 1.675 + 1.676 +#endif /* frontend_Parser_h */