darin | 7bca198 | 2006-03-06 05:29:48 +0000 | [diff] [blame] | 1 | /* |
darin | 7bca198 | 2006-03-06 05:29:48 +0000 | [diff] [blame] | 2 | * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) |
| 3 | * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
mark.lam@apple.com | faa5393 | 2013-03-20 09:09:38 +0000 | [diff] [blame] | 4 | * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. |
darin | 7bca198 | 2006-03-06 05:29:48 +0000 | [diff] [blame] | 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Library General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Library General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Library General Public License |
| 17 | * along with this library; see the file COPYING.LIB. If not, write to |
| 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 19 | * Boston, MA 02110-1301, USA. |
| 20 | * |
| 21 | */ |
| 22 | |
| 23 | #include "config.h" |
| 24 | #include "Parser.h" |
| 25 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 26 | #include "ASTBuilder.h" |
| 27 | #include "CodeBlock.h" |
cwzwarich@webkit.org | a691b5a | 2008-10-31 05:56:58 +0000 | [diff] [blame] | 28 | #include "Debugger.h" |
ggaren@apple.com | 81c68cc | 2013-04-27 06:43:33 +0000 | [diff] [blame] | 29 | #include "JSCJSValueInlines.h" |
cwzwarich@webkit.org | 3ff0e6a | 2008-11-07 00:18:07 +0000 | [diff] [blame] | 30 | #include "Lexer.h" |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 31 | #include "NodeInfo.h" |
| 32 | #include "SourceProvider.h" |
ggaren@apple.com | 81c68cc | 2013-04-27 06:43:33 +0000 | [diff] [blame] | 33 | #include "VM.h" |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 34 | #include <utility> |
| 35 | #include <wtf/HashFunctions.h> |
| 36 | #include <wtf/OwnPtr.h> |
commit-queue@webkit.org | ad641af | 2013-02-26 09:07:57 +0000 | [diff] [blame] | 37 | #include <wtf/WTFThreadData.h> |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 38 | |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 39 | #define fail() do { if (!hasError()) updateErrorMessage(); return 0; } while (0) |
| 40 | #define failWithToken(tok) do { if (!hasError()) updateErrorMessage(tok); return 0; } while (0) |
| 41 | #define failWithMessage(msg) do { if (!hasError()) updateErrorMessage(msg); return 0; } while (0) |
| 42 | #define failWithNameAndMessage(before, name, after) do { if (!hasError()) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0) |
| 43 | #define failWithStackOverflow() do { updateErrorMessage("Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0) |
andersca@apple.com | 150e5ae | 2012-10-12 23:48:18 +0000 | [diff] [blame] | 44 | #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0) |
| 45 | #define failIfFalseWithMessage(cond, msg) do { if (!(cond)) failWithMessage(msg); } while (0) |
| 46 | #define failIfFalseWithNameAndMessage(cond, before, name, msg) do { if (!(cond)) failWithNameAndMessage(before, name, msg); } while (0) |
| 47 | #define failIfTrue(cond) do { if ((cond)) fail(); } while (0) |
| 48 | #define failIfTrueWithMessage(cond, msg) do { if ((cond)) failWithMessage(msg); } while (0) |
| 49 | #define failIfTrueWithNameAndMessage(cond, before, name, msg) do { if ((cond)) failWithNameAndMessage(before, name, msg); } while (0) |
| 50 | #define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0) |
| 51 | #define failIfTrueIfStrictWithMessage(cond, msg) do { if ((cond) && strictMode()) failWithMessage(msg); } while (0) |
| 52 | #define failIfTrueIfStrictWithNameAndMessage(cond, before, name, after) do { if ((cond) && strictMode()) failWithNameAndMessage(before, name, after); } while (0) |
| 53 | #define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0) |
| 54 | #define failIfFalseIfStrictWithMessage(cond, msg) do { if ((!(cond)) && strictMode()) failWithMessage(msg); } while (0) |
| 55 | #define failIfFalseIfStrictWithNameAndMessage(cond, before, name, after) do { if ((!(cond)) && strictMode()) failWithNameAndMessage(before, name, after); } while (0) |
| 56 | #define consumeOrFail(tokenType) do { if (!consume(tokenType)) failWithToken(tokenType); } while (0) |
| 57 | #define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) failWithToken(tokenType); } while (0) |
| 58 | #define matchOrFail(tokenType) do { if (!match(tokenType)) failWithToken(tokenType); } while (0) |
mark.lam@apple.com | 8b97fde | 2012-10-22 22:09:58 +0000 | [diff] [blame] | 59 | #define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0) |
andersca@apple.com | 150e5ae | 2012-10-12 23:48:18 +0000 | [diff] [blame] | 60 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 61 | using namespace std; |
mrowe@apple.com | cf11a5d | 2007-11-16 07:47:52 +0000 | [diff] [blame] | 62 | |
cwzwarich@webkit.org | 3f782f6 | 2008-09-08 01:28:33 +0000 | [diff] [blame] | 63 | namespace JSC { |
darin | 7bca198 | 2006-03-06 05:29:48 +0000 | [diff] [blame] | 64 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 65 | template <typename LexerType> |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 66 | Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode) |
| 67 | : m_vm(vm) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 68 | , m_source(&source) |
mark.lam@apple.com | bd1385d | 2013-06-21 23:58:52 +0000 | [diff] [blame] | 69 | , m_stack(*vm, wtfThreadData().stack()) |
mark.lam@apple.com | 8b97fde | 2012-10-22 22:09:58 +0000 | [diff] [blame] | 70 | , m_hasStackOverflow(false) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 71 | , m_allowsIn(true) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 72 | , m_assignmentCount(0) |
| 73 | , m_nonLHSCount(0) |
| 74 | , m_syntaxAlreadyValidated(source.provider()->isValid()) |
| 75 | , m_statementDepth(0) |
| 76 | , m_nonTrivialExpressionCount(0) |
| 77 | , m_lastIdentifier(0) |
| 78 | , m_sourceElements(0) |
ggaren@apple.com | 7dc06ff | 2007-11-16 06:54:09 +0000 | [diff] [blame] | 79 | { |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 80 | m_lexer = adoptPtr(new LexerType(vm)); |
| 81 | m_arena = m_vm->parserArena.get(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 82 | m_lexer->setCode(source, m_arena); |
mark.lam@apple.com | f097260 | 2013-08-07 00:19:28 +0000 | [diff] [blame] | 83 | m_token.m_location.line = source.firstLine(); |
| 84 | m_token.m_location.startOffset = source.startOffset(); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 85 | m_token.m_location.endOffset = source.startOffset(); |
| 86 | m_token.m_location.lineStartOffset = source.startOffset(); |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 87 | m_functionCache = vm->addSourceProviderCache(source.provider()); |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 88 | ScopeRef scope = pushScope(); |
wingo@igalia.com | 0700f68 | 2012-03-09 12:06:48 +0000 | [diff] [blame] | 89 | if (parserMode == JSParseFunctionCode) |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 90 | scope->setIsFunction(); |
| 91 | if (strictness == JSParseStrict) |
| 92 | scope->setStrictMode(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 93 | if (parameters) { |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 94 | for (unsigned i = 0; i < parameters->size(); i++) { |
| 95 | auto parameter = parameters->at(i); |
| 96 | if (!parameter->isBindingNode()) |
| 97 | continue; |
| 98 | scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty()); |
| 99 | } |
darin | 7bca198 | 2006-03-06 05:29:48 +0000 | [diff] [blame] | 100 | } |
ggaren@apple.com | f820008 | 2012-09-07 01:42:53 +0000 | [diff] [blame] | 101 | if (!name.isNull()) |
| 102 | scope->declareCallee(&name); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 103 | next(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 104 | } |
| 105 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 106 | template <typename LexerType> |
| 107 | Parser<LexerType>::~Parser() |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 108 | { |
| 109 | } |
| 110 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 111 | template <typename LexerType> |
benjamin@webkit.org | cff06e4 | 2012-08-30 21:23:51 +0000 | [diff] [blame] | 112 | String Parser<LexerType>::parseInner() |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 113 | { |
benjamin@webkit.org | cff06e4 | 2012-08-30 21:23:51 +0000 | [diff] [blame] | 114 | String parseError = String(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 115 | |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 116 | ASTBuilder context(const_cast<VM*>(m_vm), const_cast<SourceCode*>(m_source)); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 117 | if (m_lexer->isReparsing()) |
| 118 | m_statementDepth--; |
| 119 | ScopeRef scope = currentScope(); |
| 120 | SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 121 | if (!sourceElements || !consume(EOFTOK)) { |
| 122 | if (hasError()) |
| 123 | parseError = m_errorMessage; |
| 124 | else |
| 125 | parseError = ASCIILiteral("Parser error"); |
| 126 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 127 | |
| 128 | IdentifierSet capturedVariables; |
oliver@apple.com | 2cfd376 | 2013-08-06 21:20:10 +0000 | [diff] [blame] | 129 | bool modifiedParameter = false; |
| 130 | scope->getCapturedVariables(capturedVariables, modifiedParameter); |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 131 | CodeFeatures features = context.features(); |
| 132 | if (scope->strictMode()) |
| 133 | features |= StrictModeFeature; |
| 134 | if (scope->shadowsArguments()) |
| 135 | features |= ShadowsArgumentsFeature; |
oliver@apple.com | 2cfd376 | 2013-08-06 21:20:10 +0000 | [diff] [blame] | 136 | if (modifiedParameter) |
| 137 | features |= ModifiedParameterFeature; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 138 | |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 139 | didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 140 | context.numConstants(), capturedVariables); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 141 | |
| 142 | return parseError; |
darin | 7bca198 | 2006-03-06 05:29:48 +0000 | [diff] [blame] | 143 | } |
| 144 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 145 | template <typename LexerType> |
| 146 | void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 147 | ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars) |
ggaren@apple.com | 0195b0b | 2007-12-21 02:18:11 +0000 | [diff] [blame] | 148 | { |
mrowe@apple.com | 2f6dfdf | 2008-05-22 01:20:45 +0000 | [diff] [blame] | 149 | m_sourceElements = sourceElements; |
ggaren@apple.com | 0195b0b | 2007-12-21 02:18:11 +0000 | [diff] [blame] | 150 | m_varDeclarations = varStack; |
| 151 | m_funcDeclarations = funcStack; |
oliver@apple.com | 09ed6d0 | 2010-09-16 00:05:13 +0000 | [diff] [blame] | 152 | m_capturedVariables.swap(capturedVars); |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 153 | m_features = features; |
cwzwarich@webkit.org | 300bb75 | 2008-08-06 10:37:34 +0000 | [diff] [blame] | 154 | m_numConstants = numConstants; |
ggaren@apple.com | 0195b0b | 2007-12-21 02:18:11 +0000 | [diff] [blame] | 155 | } |
| 156 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 157 | template <typename LexerType> |
| 158 | bool Parser<LexerType>::allowAutomaticSemicolon() |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 159 | { |
| 160 | return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator(); |
| 161 | } |
| 162 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 163 | template <typename LexerType> |
| 164 | template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 165 | { |
ariya@webkit.org | 1664b94 | 2011-11-08 02:25:20 +0000 | [diff] [blame] | 166 | const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 167 | TreeSourceElements sourceElements = context.createSourceElements(); |
| 168 | bool seenNonDirective = false; |
| 169 | const Identifier* directive = 0; |
ariya@webkit.org | 1664b94 | 2011-11-08 02:25:20 +0000 | [diff] [blame] | 170 | unsigned directiveLiteralLength = 0; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 171 | unsigned startOffset = m_token.m_location.startOffset; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 172 | unsigned startLineStartOffset = m_token.m_location.lineStartOffset; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 173 | unsigned oldLastLineNumber = m_lexer->lastLineNumber(); |
| 174 | unsigned oldLineNumber = m_lexer->lineNumber(); |
| 175 | bool hasSetStrict = false; |
ariya@webkit.org | 1664b94 | 2011-11-08 02:25:20 +0000 | [diff] [blame] | 176 | while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) { |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 177 | if (mode == CheckForStrictMode && !seenNonDirective) { |
| 178 | if (directive) { |
ariya@webkit.org | 1664b94 | 2011-11-08 02:25:20 +0000 | [diff] [blame] | 179 | // "use strict" must be the exact literal without escape sequences or line continuation. |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 180 | if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) { |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 181 | setStrictMode(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 182 | hasSetStrict = true; |
| 183 | failIfFalse(isValidStrictMode()); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 184 | m_lexer->setOffset(startOffset, startLineStartOffset); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 185 | next(); |
| 186 | m_lexer->setLastLineNumber(oldLastLineNumber); |
| 187 | m_lexer->setLineNumber(oldLineNumber); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 188 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 189 | continue; |
| 190 | } |
| 191 | } else |
| 192 | seenNonDirective = true; |
| 193 | } |
| 194 | context.appendStatement(sourceElements, statement); |
| 195 | } |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 196 | |
| 197 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 198 | return sourceElements; |
| 199 | } |
| 200 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 201 | template <typename LexerType> |
| 202 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 203 | { |
| 204 | ASSERT(match(VAR)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 205 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 206 | int start = tokenLine(); |
| 207 | int end = 0; |
| 208 | int scratch; |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 209 | TreeDeconstructionPattern scratch1 = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 210 | TreeExpression scratch2 = 0; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 211 | JSTextPosition scratch3; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 212 | TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 213 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 214 | failIfFalse(autoSemiColon()); |
| 215 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 216 | return context.createVarStatement(location, varDecls, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 217 | } |
| 218 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 219 | template <typename LexerType> |
| 220 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 221 | { |
| 222 | ASSERT(match(CONSTTOKEN)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 223 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 224 | int start = tokenLine(); |
| 225 | int end = 0; |
| 226 | TreeConstDeclList constDecls = parseConstDeclarationList(context); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 227 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 228 | failIfFalse(autoSemiColon()); |
| 229 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 230 | return context.createConstStatement(location, constDecls, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 231 | } |
| 232 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 233 | template <typename LexerType> |
| 234 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 235 | { |
| 236 | ASSERT(match(DO)); |
| 237 | int startLine = tokenLine(); |
| 238 | next(); |
| 239 | const Identifier* unused = 0; |
| 240 | startLoop(); |
| 241 | TreeStatement statement = parseStatement(context, unused); |
| 242 | endLoop(); |
| 243 | failIfFalse(statement); |
| 244 | int endLine = tokenLine(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 245 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 246 | consumeOrFail(WHILE); |
| 247 | consumeOrFail(OPENPAREN); |
| 248 | TreeExpression expr = parseExpression(context); |
| 249 | failIfFalse(expr); |
| 250 | consumeOrFail(CLOSEPAREN); |
| 251 | if (match(SEMICOLON)) |
| 252 | next(); // Always performs automatic semicolon insertion. |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 253 | return context.createDoWhileStatement(location, statement, expr, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 254 | } |
| 255 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 256 | template <typename LexerType> |
| 257 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 258 | { |
| 259 | ASSERT(match(WHILE)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 260 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 261 | int startLine = tokenLine(); |
| 262 | next(); |
| 263 | consumeOrFail(OPENPAREN); |
| 264 | TreeExpression expr = parseExpression(context); |
| 265 | failIfFalse(expr); |
| 266 | int endLine = tokenLine(); |
| 267 | consumeOrFail(CLOSEPAREN); |
| 268 | const Identifier* unused = 0; |
| 269 | startLoop(); |
| 270 | TreeStatement statement = parseStatement(context, unused); |
| 271 | endLoop(); |
| 272 | failIfFalse(statement); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 273 | return context.createWhileStatement(location, expr, statement, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 274 | } |
| 275 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 276 | template <typename LexerType> |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 277 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 278 | { |
| 279 | TreeExpression varDecls = 0; |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 280 | const Identifier* lastIdent; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 281 | do { |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 282 | lastIdent = 0; |
| 283 | lastPattern = 0; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 284 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 285 | next(); |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 286 | TreeExpression node = 0; |
| 287 | declarations++; |
| 288 | bool hasInitializer = false; |
| 289 | if (match(IDENT)) { |
| 290 | JSTextPosition varStart = tokenStartPosition(); |
| 291 | identStart = varStart; |
| 292 | const Identifier* name = m_token.m_data.ident; |
| 293 | lastIdent = name; |
| 294 | next(); |
| 295 | hasInitializer = match(EQUAL); |
| 296 | failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode."); |
oliver@apple.com | 20a9bf0 | 2013-10-04 20:35:24 +0000 | [diff] [blame] | 297 | context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0); |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 298 | if (hasInitializer) { |
| 299 | JSTextPosition varDivot = tokenStartPosition() + 1; |
| 300 | initStart = tokenStartPosition(); |
| 301 | next(TreeBuilder::DontBuildStrings); // consume '=' |
| 302 | TreeExpression initializer = parseAssignmentExpression(context); |
| 303 | initEnd = lastTokenEndPosition(); |
| 304 | lastInitializer = initializer; |
| 305 | failIfFalse(initializer); |
| 306 | |
| 307 | node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition()); |
| 308 | } |
| 309 | } else { |
| 310 | lastIdent = 0; |
| 311 | auto pattern = parseDeconstructionPattern<DeconstructToVariables>(context); |
| 312 | failIfFalse(pattern); |
| 313 | hasInitializer = match(EQUAL); |
| 314 | lastPattern = pattern; |
| 315 | if (hasInitializer) { |
| 316 | next(TreeBuilder::DontBuildStrings); // consume '=' |
| 317 | TreeExpression rhs = parseExpression(context); |
| 318 | node = context.createDeconstructingAssignment(location, pattern, rhs); |
| 319 | } |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 320 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 321 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 322 | if (hasInitializer) { |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 323 | if (!varDecls) |
| 324 | varDecls = node; |
| 325 | else |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 326 | varDecls = context.combineCommaNodes(location, varDecls, node); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 327 | } |
| 328 | } while (match(COMMA)); |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 329 | if (lastIdent) |
| 330 | lastPattern = createBindingPattern<DeconstructToVariables>(context, *lastIdent, 0); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 331 | return varDecls; |
| 332 | } |
| 333 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 334 | template <typename LexerType> |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 335 | template <DeconstructionKind kind, class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, const Identifier& name, int depth) |
| 336 | { |
| 337 | ASSERT(!name.isEmpty()); |
| 338 | ASSERT(!name.isNull()); |
| 339 | |
| 340 | ASSERT(name.impl()->isIdentifier()); |
| 341 | if (depth) { |
| 342 | if (kind == DeconstructToVariables) |
| 343 | failIfFalseIfStrictWithNameAndMessage(declareVariable(&name), "Cannot deconstruct to a variable named", name.impl(), "."); |
| 344 | if (kind == DeconstructToParameters) { |
| 345 | auto bindingResult = declareBoundParameter(&name); |
| 346 | failIfFalseIfStrictWithNameAndMessage(bindingResult != Scope::StrictBindingFailed, "Cannot deconstruct to a parameter named", name.impl(), "in strict mode."); |
| 347 | failIfFalseWithNameAndMessage(bindingResult != Scope::BindingFailed, "Cannot deconstruct to a parameter named", name.impl(), "."); |
| 348 | } |
| 349 | context.addVar(&name, kind == DeconstructToParameters ? 0 : DeclarationStacks::HasInitializer); |
| 350 | } else { |
| 351 | if (kind == DeconstructToVariables) { |
| 352 | failIfFalseIfStrictWithNameAndMessage(declareVariable(&name), "Cannot declare a variable named", name.impl(), "in strict mode."); |
| 353 | context.addVar(&name, DeclarationStacks::HasInitializer); |
| 354 | } |
| 355 | |
| 356 | if (kind == DeconstructToParameters) |
| 357 | failIfFalseIfStrictWithNameAndMessage(declareParameter(&name), "Cannot declare a parameter named", name.impl(), "in strict mode."); |
| 358 | } |
| 359 | return context.createBindingLocation(m_token.m_location, name, m_token.m_endPosition, m_token.m_startPosition, m_token.m_endPosition); |
| 360 | } |
| 361 | |
| 362 | template <typename LexerType> |
| 363 | template <DeconstructionKind kind, class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::parseDeconstructionPattern(TreeBuilder& context, int depth) |
| 364 | { |
| 365 | failIfStackOverflow(); |
| 366 | int nonLHSCount = m_nonLHSCount; |
| 367 | TreeDeconstructionPattern pattern; |
| 368 | switch (m_token.m_type) { |
| 369 | case OPENBRACKET: { |
| 370 | auto arrayPattern = context.createArrayPattern(m_token.m_location); |
| 371 | next(); |
| 372 | do { |
| 373 | while (match(COMMA)) { |
| 374 | context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location); |
| 375 | next(); |
| 376 | } |
| 377 | failIfTrue(hasError()); |
| 378 | JSTokenLocation location = m_token.m_location; |
| 379 | auto innerPattern = parseDeconstructionPattern<kind>(context, depth + 1); |
| 380 | failIfFalse(innerPattern); |
| 381 | context.appendArrayPatternEntry(arrayPattern, location, innerPattern); |
| 382 | } while (consume(COMMA)); |
| 383 | consumeOrFail(CLOSEBRACKET); |
| 384 | pattern = arrayPattern; |
| 385 | break; |
| 386 | } |
| 387 | case OPENBRACE: { |
| 388 | next(); |
| 389 | auto objectPattern = context.createObjectPattern(m_token.m_location); |
| 390 | bool wasString = false; |
| 391 | do { |
| 392 | Identifier propertyName; |
| 393 | TreeDeconstructionPattern innerPattern = 0; |
| 394 | JSTokenLocation location = m_token.m_location; |
| 395 | if (match(IDENT)) { |
| 396 | propertyName = *m_token.m_data.ident; |
| 397 | next(); |
| 398 | if (consume(COLON)) |
| 399 | innerPattern = parseDeconstructionPattern<kind>(context, depth + 1); |
| 400 | else |
| 401 | innerPattern = createBindingPattern<kind>(context, propertyName, depth); |
| 402 | } else { |
| 403 | switch (m_token.m_type) { |
| 404 | case NUMBER: |
| 405 | propertyName = Identifier::from(m_vm, m_token.m_data.doubleValue); |
| 406 | break; |
| 407 | case STRING: |
| 408 | propertyName = *m_token.m_data.ident; |
| 409 | wasString = true; |
| 410 | break; |
| 411 | default: |
| 412 | failIfTrue(!(m_token.m_type & KeywordTokenFlag)); |
| 413 | propertyName = *m_token.m_data.ident; |
| 414 | break; |
| 415 | } |
| 416 | next(); |
| 417 | consumeOrFail(COLON); |
| 418 | innerPattern = parseDeconstructionPattern<kind>(context, depth + 1); |
| 419 | } |
| 420 | failIfFalse(innerPattern); |
| 421 | context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern); |
| 422 | } while (consume(COMMA)); |
| 423 | consumeOrFail(CLOSEBRACE); |
| 424 | pattern = objectPattern; |
| 425 | break; |
| 426 | } |
| 427 | |
| 428 | default: { |
| 429 | matchOrFail(IDENT); |
| 430 | pattern = createBindingPattern<kind>(context, *m_token.m_data.ident, depth); |
| 431 | next(); |
| 432 | break; |
| 433 | } |
| 434 | } |
| 435 | m_nonLHSCount = nonLHSCount; |
| 436 | return pattern; |
| 437 | } |
| 438 | |
| 439 | template <typename LexerType> |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 440 | template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 441 | { |
| 442 | failIfTrue(strictMode()); |
| 443 | TreeConstDeclList constDecls = 0; |
| 444 | TreeConstDeclList tail = 0; |
| 445 | do { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 446 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 447 | next(); |
| 448 | matchOrFail(IDENT); |
| 449 | const Identifier* name = m_token.m_data.ident; |
| 450 | next(); |
| 451 | bool hasInitializer = match(EQUAL); |
| 452 | declareVariable(name); |
| 453 | context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 454 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 455 | TreeExpression initializer = 0; |
| 456 | if (hasInitializer) { |
| 457 | next(TreeBuilder::DontBuildStrings); // consume '=' |
| 458 | initializer = parseAssignmentExpression(context); |
| 459 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 460 | tail = context.appendConstDecl(location, tail, name, initializer); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 461 | if (!constDecls) |
| 462 | constDecls = tail; |
| 463 | } while (match(COMMA)); |
| 464 | return constDecls; |
| 465 | } |
| 466 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 467 | template <typename LexerType> |
| 468 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 469 | { |
| 470 | ASSERT(match(FOR)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 471 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 472 | int startLine = tokenLine(); |
| 473 | next(); |
| 474 | consumeOrFail(OPENPAREN); |
| 475 | int nonLHSCount = m_nonLHSCount; |
| 476 | int declarations = 0; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 477 | JSTextPosition declsStart; |
| 478 | JSTextPosition declsEnd; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 479 | TreeExpression decls = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 480 | if (match(VAR)) { |
| 481 | /* |
| 482 | for (var IDENT in expression) statement |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 483 | for (var varDeclarationList; expressionOpt; expressionOpt) |
| 484 | */ |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 485 | TreeDeconstructionPattern forInTarget = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 486 | TreeExpression forInInitializer = 0; |
| 487 | m_allowsIn = false; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 488 | JSTextPosition initStart; |
| 489 | JSTextPosition initEnd; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 490 | decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd); |
| 491 | m_allowsIn = true; |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 492 | failIfTrue(hasError()); |
| 493 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 494 | // Remainder of a standard for loop is handled identically |
| 495 | if (match(SEMICOLON)) |
| 496 | goto standardForLoop; |
| 497 | |
| 498 | failIfFalse(declarations == 1); |
oliver@apple.com | 8788100 | 2013-09-13 21:19:38 +0000 | [diff] [blame] | 499 | failIfTrueWithMessage(forInInitializer, "Cannot use initialiser syntax in a for-in loop"); |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 500 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 501 | // Handle for-in with var declaration |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 502 | JSTextPosition inLocation = tokenStartPosition(); |
oliver@apple.com | 20a9bf0 | 2013-10-04 20:35:24 +0000 | [diff] [blame] | 503 | bool isOfEnumeration = false; |
| 504 | if (!consume(INTOKEN)) { |
| 505 | failIfFalseWithMessage(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax"); |
| 506 | isOfEnumeration = true; |
| 507 | next(); |
| 508 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 509 | |
| 510 | TreeExpression expr = parseExpression(context); |
| 511 | failIfFalse(expr); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 512 | JSTextPosition exprEnd = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 513 | |
| 514 | int endLine = tokenLine(); |
| 515 | consumeOrFail(CLOSEPAREN); |
| 516 | |
| 517 | const Identifier* unused = 0; |
| 518 | startLoop(); |
| 519 | TreeStatement statement = parseStatement(context, unused); |
| 520 | endLoop(); |
| 521 | failIfFalse(statement); |
oliver@apple.com | 20a9bf0 | 2013-10-04 20:35:24 +0000 | [diff] [blame] | 522 | if (isOfEnumeration) |
| 523 | return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine); |
oliver@apple.com | 8788100 | 2013-09-13 21:19:38 +0000 | [diff] [blame] | 524 | return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 525 | } |
| 526 | |
| 527 | if (!match(SEMICOLON)) { |
| 528 | m_allowsIn = false; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 529 | declsStart = tokenStartPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 530 | decls = parseExpression(context); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 531 | declsEnd = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 532 | m_allowsIn = true; |
| 533 | failIfFalse(decls); |
| 534 | } |
| 535 | |
| 536 | if (match(SEMICOLON)) { |
| 537 | standardForLoop: |
| 538 | // Standard for loop |
| 539 | next(); |
| 540 | TreeExpression condition = 0; |
| 541 | |
| 542 | if (!match(SEMICOLON)) { |
| 543 | condition = parseExpression(context); |
| 544 | failIfFalse(condition); |
| 545 | } |
| 546 | consumeOrFail(SEMICOLON); |
| 547 | |
| 548 | TreeExpression increment = 0; |
| 549 | if (!match(CLOSEPAREN)) { |
| 550 | increment = parseExpression(context); |
| 551 | failIfFalse(increment); |
| 552 | } |
| 553 | int endLine = tokenLine(); |
| 554 | consumeOrFail(CLOSEPAREN); |
| 555 | const Identifier* unused = 0; |
| 556 | startLoop(); |
| 557 | TreeStatement statement = parseStatement(context, unused); |
| 558 | endLoop(); |
| 559 | failIfFalse(statement); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 560 | return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 561 | } |
| 562 | |
| 563 | // For-in loop |
| 564 | failIfFalse(nonLHSCount == m_nonLHSCount); |
oliver@apple.com | 20a9bf0 | 2013-10-04 20:35:24 +0000 | [diff] [blame] | 565 | bool isOfEnumeration = false; |
| 566 | if (!consume(INTOKEN)) { |
| 567 | failIfFalseWithMessage(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax"); |
| 568 | isOfEnumeration = true; |
| 569 | next(); |
| 570 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 571 | TreeExpression expr = parseExpression(context); |
| 572 | failIfFalse(expr); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 573 | JSTextPosition exprEnd = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 574 | int endLine = tokenLine(); |
| 575 | consumeOrFail(CLOSEPAREN); |
| 576 | const Identifier* unused = 0; |
| 577 | startLoop(); |
| 578 | TreeStatement statement = parseStatement(context, unused); |
| 579 | endLoop(); |
| 580 | failIfFalse(statement); |
oliver@apple.com | 20a9bf0 | 2013-10-04 20:35:24 +0000 | [diff] [blame] | 581 | if (isOfEnumeration) |
| 582 | return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 583 | return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 584 | } |
| 585 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 586 | template <typename LexerType> |
| 587 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 588 | { |
| 589 | ASSERT(match(BREAK)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 590 | JSTokenLocation location(tokenLocation()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 591 | JSTextPosition start = tokenStartPosition(); |
| 592 | JSTextPosition end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 593 | next(); |
| 594 | |
| 595 | if (autoSemiColon()) { |
| 596 | failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement"); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 597 | return context.createBreakStatement(location, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 598 | } |
| 599 | matchOrFail(IDENT); |
| 600 | const Identifier* ident = m_token.m_data.ident; |
| 601 | failIfFalseWithNameAndMessage(getLabel(ident), "Label", ident->impl(), "is not defined"); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 602 | end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 603 | next(); |
| 604 | failIfFalse(autoSemiColon()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 605 | return context.createBreakStatement(location, ident, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 606 | } |
| 607 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 608 | template <typename LexerType> |
| 609 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 610 | { |
| 611 | ASSERT(match(CONTINUE)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 612 | JSTokenLocation location(tokenLocation()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 613 | JSTextPosition start = tokenStartPosition(); |
| 614 | JSTextPosition end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 615 | next(); |
| 616 | |
| 617 | if (autoSemiColon()) { |
| 618 | failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement"); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 619 | return context.createContinueStatement(location, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 620 | } |
| 621 | matchOrFail(IDENT); |
| 622 | const Identifier* ident = m_token.m_data.ident; |
| 623 | ScopeLabelInfo* label = getLabel(ident); |
| 624 | failIfFalseWithNameAndMessage(label, "Label", ident->impl(), "is not defined"); |
| 625 | failIfFalseWithMessage(label->m_isLoop, "'continue' is only valid inside a loop statement"); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 626 | end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 627 | next(); |
| 628 | failIfFalse(autoSemiColon()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 629 | return context.createContinueStatement(location, ident, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 630 | } |
| 631 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 632 | template <typename LexerType> |
| 633 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 634 | { |
| 635 | ASSERT(match(RETURN)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 636 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 637 | failIfFalse(currentScope()->isFunction()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 638 | JSTextPosition start = tokenStartPosition(); |
| 639 | JSTextPosition end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 640 | next(); |
| 641 | // We do the auto semicolon check before attempting to parse an expression |
| 642 | // as we need to ensure the a line break after the return correctly terminates |
| 643 | // the statement |
| 644 | if (match(SEMICOLON)) |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 645 | end = tokenEndPosition(); |
| 646 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 647 | if (autoSemiColon()) |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 648 | return context.createReturnStatement(location, 0, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 649 | TreeExpression expr = parseExpression(context); |
| 650 | failIfFalse(expr); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 651 | end = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 652 | if (match(SEMICOLON)) |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 653 | end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 654 | failIfFalse(autoSemiColon()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 655 | return context.createReturnStatement(location, expr, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 656 | } |
| 657 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 658 | template <typename LexerType> |
| 659 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 660 | { |
| 661 | ASSERT(match(THROW)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 662 | JSTokenLocation location(tokenLocation()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 663 | JSTextPosition start = tokenStartPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 664 | next(); |
| 665 | |
| 666 | failIfTrue(autoSemiColon()); |
| 667 | |
| 668 | TreeExpression expr = parseExpression(context); |
| 669 | failIfFalse(expr); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 670 | JSTextPosition end = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 671 | failIfFalse(autoSemiColon()); |
| 672 | |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 673 | return context.createThrowStatement(location, expr, start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 674 | } |
| 675 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 676 | template <typename LexerType> |
| 677 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 678 | { |
| 679 | ASSERT(match(WITH)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 680 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 681 | failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode"); |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 682 | currentScope()->setNeedsFullActivation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 683 | int startLine = tokenLine(); |
| 684 | next(); |
| 685 | consumeOrFail(OPENPAREN); |
| 686 | int start = tokenStart(); |
| 687 | TreeExpression expr = parseExpression(context); |
| 688 | failIfFalse(expr); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 689 | JSTextPosition end = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 690 | int endLine = tokenLine(); |
| 691 | consumeOrFail(CLOSEPAREN); |
| 692 | const Identifier* unused = 0; |
| 693 | TreeStatement statement = parseStatement(context, unused); |
| 694 | failIfFalse(statement); |
| 695 | |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 696 | return context.createWithStatement(location, expr, statement, start, end, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 697 | } |
| 698 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 699 | template <typename LexerType> |
| 700 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 701 | { |
| 702 | ASSERT(match(SWITCH)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 703 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 704 | int startLine = tokenLine(); |
| 705 | next(); |
| 706 | consumeOrFail(OPENPAREN); |
| 707 | TreeExpression expr = parseExpression(context); |
| 708 | failIfFalse(expr); |
| 709 | int endLine = tokenLine(); |
| 710 | consumeOrFail(CLOSEPAREN); |
| 711 | consumeOrFail(OPENBRACE); |
| 712 | startSwitch(); |
| 713 | TreeClauseList firstClauses = parseSwitchClauses(context); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 714 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 715 | |
| 716 | TreeClause defaultClause = parseSwitchDefaultClause(context); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 717 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 718 | |
| 719 | TreeClauseList secondClauses = parseSwitchClauses(context); |
benjamin@webkit.org | 7438521 | 2013-04-11 03:17:08 +0000 | [diff] [blame] | 720 | failIfTrue(hasError()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 721 | endSwitch(); |
| 722 | consumeOrFail(CLOSEBRACE); |
| 723 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 724 | return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 725 | |
| 726 | } |
| 727 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 728 | template <typename LexerType> |
| 729 | template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 730 | { |
| 731 | if (!match(CASE)) |
| 732 | return 0; |
| 733 | next(); |
| 734 | TreeExpression condition = parseExpression(context); |
| 735 | failIfFalse(condition); |
| 736 | consumeOrFail(COLON); |
| 737 | TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context); |
| 738 | failIfFalse(statements); |
| 739 | TreeClause clause = context.createClause(condition, statements); |
| 740 | TreeClauseList clauseList = context.createClauseList(clause); |
| 741 | TreeClauseList tail = clauseList; |
| 742 | |
| 743 | while (match(CASE)) { |
| 744 | next(); |
| 745 | TreeExpression condition = parseExpression(context); |
| 746 | failIfFalse(condition); |
| 747 | consumeOrFail(COLON); |
| 748 | TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context); |
| 749 | failIfFalse(statements); |
| 750 | clause = context.createClause(condition, statements); |
| 751 | tail = context.createClauseList(tail, clause); |
| 752 | } |
| 753 | return clauseList; |
| 754 | } |
| 755 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 756 | template <typename LexerType> |
| 757 | template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 758 | { |
| 759 | if (!match(DEFAULT)) |
| 760 | return 0; |
| 761 | next(); |
| 762 | consumeOrFail(COLON); |
| 763 | TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context); |
| 764 | failIfFalse(statements); |
| 765 | return context.createClause(0, statements); |
| 766 | } |
| 767 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 768 | template <typename LexerType> |
| 769 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 770 | { |
| 771 | ASSERT(match(TRY)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 772 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 773 | TreeStatement tryBlock = 0; |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 774 | const Identifier* ident = &m_vm->propertyNames->nullIdentifier; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 775 | TreeStatement catchBlock = 0; |
| 776 | TreeStatement finallyBlock = 0; |
| 777 | int firstLine = tokenLine(); |
| 778 | next(); |
| 779 | matchOrFail(OPENBRACE); |
| 780 | |
| 781 | tryBlock = parseBlockStatement(context); |
| 782 | failIfFalse(tryBlock); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 783 | int lastLine = m_lastTokenEndPosition.line; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 784 | |
| 785 | if (match(CATCH)) { |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 786 | currentScope()->setNeedsFullActivation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 787 | next(); |
| 788 | consumeOrFail(OPENPAREN); |
| 789 | matchOrFail(IDENT); |
| 790 | ident = m_token.m_data.ident; |
| 791 | next(); |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 792 | AutoPopScopeRef catchScope(this, pushScope()); |
commit-queue@webkit.org | 4c5567d | 2011-12-15 13:45:56 +0000 | [diff] [blame] | 793 | failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode"); |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 794 | catchScope->preventNewDecls(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 795 | consumeOrFail(CLOSEPAREN); |
| 796 | matchOrFail(OPENBRACE); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 797 | catchBlock = parseBlockStatement(context); |
| 798 | failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block"); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 799 | failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo)); |
| 800 | } |
| 801 | |
| 802 | if (match(FINALLY)) { |
| 803 | next(); |
| 804 | matchOrFail(OPENBRACE); |
| 805 | finallyBlock = parseBlockStatement(context); |
| 806 | failIfFalse(finallyBlock); |
| 807 | } |
| 808 | failIfFalse(catchBlock || finallyBlock); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 809 | return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 810 | } |
| 811 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 812 | template <typename LexerType> |
| 813 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 814 | { |
| 815 | ASSERT(match(DEBUGGER)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 816 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 817 | int startLine = tokenLine(); |
| 818 | int endLine = startLine; |
| 819 | next(); |
| 820 | if (match(SEMICOLON)) |
| 821 | startLine = tokenLine(); |
| 822 | failIfFalse(autoSemiColon()); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 823 | return context.createDebugger(location, startLine, endLine); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 824 | } |
| 825 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 826 | template <typename LexerType> |
| 827 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 828 | { |
| 829 | ASSERT(match(OPENBRACE)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 830 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 831 | int start = tokenLine(); |
| 832 | next(); |
| 833 | if (match(CLOSEBRACE)) { |
| 834 | next(); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 835 | return context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 836 | } |
| 837 | TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context); |
| 838 | failIfFalse(subtree); |
| 839 | matchOrFail(CLOSEBRACE); |
| 840 | next(); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 841 | return context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 842 | } |
| 843 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 844 | template <typename LexerType> |
| 845 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 846 | { |
| 847 | DepthManager statementDepth(&m_statementDepth); |
| 848 | m_statementDepth++; |
| 849 | directive = 0; |
| 850 | int nonTrivialExpressionCount = 0; |
| 851 | failIfStackOverflow(); |
| 852 | switch (m_token.m_type) { |
| 853 | case OPENBRACE: |
| 854 | return parseBlockStatement(context); |
| 855 | case VAR: |
| 856 | return parseVarDeclaration(context); |
| 857 | case CONSTTOKEN: |
| 858 | return parseConstDeclaration(context); |
| 859 | case FUNCTION: |
| 860 | failIfFalseIfStrictWithMessage(m_statementDepth == 1, "Functions cannot be declared in a nested block in strict mode"); |
| 861 | return parseFunctionDeclaration(context); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 862 | case SEMICOLON: { |
| 863 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 864 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 865 | return context.createEmptyStatement(location); |
| 866 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 867 | case IF: |
| 868 | return parseIfStatement(context); |
| 869 | case DO: |
| 870 | return parseDoWhileStatement(context); |
| 871 | case WHILE: |
| 872 | return parseWhileStatement(context); |
| 873 | case FOR: |
| 874 | return parseForStatement(context); |
| 875 | case CONTINUE: |
| 876 | return parseContinueStatement(context); |
| 877 | case BREAK: |
| 878 | return parseBreakStatement(context); |
| 879 | case RETURN: |
| 880 | return parseReturnStatement(context); |
| 881 | case WITH: |
| 882 | return parseWithStatement(context); |
| 883 | case SWITCH: |
| 884 | return parseSwitchStatement(context); |
| 885 | case THROW: |
| 886 | return parseThrowStatement(context); |
| 887 | case TRY: |
| 888 | return parseTryStatement(context); |
| 889 | case DEBUGGER: |
| 890 | return parseDebuggerStatement(context); |
| 891 | case EOFTOK: |
| 892 | case CASE: |
| 893 | case CLOSEBRACE: |
| 894 | case DEFAULT: |
| 895 | // These tokens imply the end of a set of source elements |
| 896 | return 0; |
| 897 | case IDENT: |
| 898 | return parseExpressionOrLabelStatement(context); |
| 899 | case STRING: |
| 900 | directive = m_token.m_data.ident; |
ariya@webkit.org | 1664b94 | 2011-11-08 02:25:20 +0000 | [diff] [blame] | 901 | if (directiveLiteralLength) |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 902 | *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 903 | nonTrivialExpressionCount = m_nonTrivialExpressionCount; |
| 904 | default: |
| 905 | TreeStatement exprStatement = parseExpressionStatement(context); |
| 906 | if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount) |
| 907 | directive = 0; |
| 908 | return exprStatement; |
| 909 | } |
| 910 | } |
| 911 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 912 | template <typename LexerType> |
| 913 | template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 914 | { |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 915 | auto parameter = parseDeconstructionPattern<DeconstructToParameters>(context); |
| 916 | failIfFalse(parameter); |
| 917 | TreeFormalParameterList list = context.createFormalParameterList(parameter); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 918 | TreeFormalParameterList tail = list; |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 919 | while (consume(COMMA)) { |
| 920 | parameter = parseDeconstructionPattern<DeconstructToParameters>(context); |
| 921 | failIfFalse(parameter); |
| 922 | tail = context.createFormalParameterList(tail, parameter); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 923 | } |
| 924 | return list; |
| 925 | } |
| 926 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 927 | template <typename LexerType> |
| 928 | template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 929 | { |
mark.lam@apple.com | faa5393 | 2013-03-20 09:09:38 +0000 | [diff] [blame] | 930 | JSTokenLocation startLocation(tokenLocation()); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 931 | unsigned startColumn = tokenColumn(); |
mark.lam@apple.com | faa5393 | 2013-03-20 09:09:38 +0000 | [diff] [blame] | 932 | next(); |
| 933 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 934 | if (match(CLOSEBRACE)) |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 935 | return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 936 | DepthManager statementDepth(&m_statementDepth); |
| 937 | m_statementDepth = 0; |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 938 | typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 939 | failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder)); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 940 | return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 941 | } |
| 942 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 943 | template <typename LexerType> |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 944 | template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 945 | { |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 946 | AutoPopScopeRef functionScope(this, pushScope()); |
| 947 | functionScope->setIsFunction(); |
oliver@apple.com | d6b8be4 | 2012-11-28 21:11:53 +0000 | [diff] [blame] | 948 | int functionStart = m_token.m_location.startOffset; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 949 | if (match(IDENT)) { |
| 950 | name = m_token.m_data.ident; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 951 | next(); |
| 952 | if (!nameIsInContainingScope) |
| 953 | failIfFalseIfStrict(functionScope->declareVariable(name)); |
| 954 | } else if (requirements == FunctionNeedsName) |
| 955 | return false; |
| 956 | consumeOrFail(OPENPAREN); |
| 957 | if (!match(CLOSEPAREN)) { |
| 958 | parameters = parseFormalParameters(context); |
| 959 | failIfFalse(parameters); |
| 960 | } |
| 961 | consumeOrFail(CLOSEPAREN); |
| 962 | matchOrFail(OPENBRACE); |
| 963 | |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 964 | openBraceOffset = m_token.m_data.offset; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 965 | bodyStartLine = tokenLine(); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 966 | bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; |
mark.lam@apple.com | faa5393 | 2013-03-20 09:09:38 +0000 | [diff] [blame] | 967 | JSTokenLocation startLocation(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 968 | |
| 969 | // If we know about this function already, we can use the cached info and skip the parser to the end of the function. |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 970 | if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 0) { |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 971 | // If we're in a strict context, the cached function info must say it was strict too. |
oliver@apple.com | 6bc1137 | 2012-05-07 23:35:52 +0000 | [diff] [blame] | 972 | ASSERT(!strictMode() || cachedInfo->strictMode); |
mark.lam@apple.com | 0d5fdb9 | 2013-07-24 00:41:46 +0000 | [diff] [blame] | 973 | JSTokenLocation endLocation; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 974 | |
mark.lam@apple.com | faa5393 | 2013-03-20 09:09:38 +0000 | [diff] [blame] | 975 | endLocation.line = cachedInfo->closeBraceLine; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 976 | endLocation.startOffset = cachedInfo->closeBraceOffset; |
| 977 | endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset; |
| 978 | ASSERT(endLocation.startOffset >= endLocation.lineStartOffset); |
| 979 | |
| 980 | body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, cachedInfo->strictMode); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 981 | |
akling@apple.com | e93cba9 | 2013-01-28 06:34:03 +0000 | [diff] [blame] | 982 | functionScope->restoreFromSourceProviderCache(cachedInfo); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 983 | failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); |
| 984 | |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 985 | closeBraceOffset = cachedInfo->closeBraceOffset; |
| 986 | |
oliver@apple.com | 924afcb | 2012-12-06 19:34:27 +0000 | [diff] [blame] | 987 | context.setFunctionStart(body, functionStart); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 988 | m_token = cachedInfo->closeBraceToken(); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 989 | |
| 990 | m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 991 | m_lexer->setLineNumber(m_token.m_location.line); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 992 | |
| 993 | next(); |
| 994 | return true; |
| 995 | } |
| 996 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 997 | body = parseFunctionBody(context); |
| 998 | failIfFalse(body); |
| 999 | if (functionScope->strictMode() && name) { |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1000 | failIfTrueWithNameAndMessage(m_vm->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode"); |
| 1001 | failIfTrueWithNameAndMessage(m_vm->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode"); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1002 | } |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1003 | closeBraceOffset = m_token.m_data.offset; |
| 1004 | unsigned closeBraceLine = m_token.m_data.line; |
| 1005 | unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1006 | |
| 1007 | // Cache the tokenizer state and the function scope the first time the function is parsed. |
| 1008 | // Any future reparsing can then skip the function. |
ggaren@apple.com | d17e17e | 2013-02-19 01:39:12 +0000 | [diff] [blame] | 1009 | static const int minimumFunctionLengthToCache = 16; |
andersca@apple.com | 2a6c489 | 2013-09-26 20:44:02 +0000 | [diff] [blame] | 1010 | std::unique_ptr<SourceProviderCacheItem> newInfo; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1011 | int functionLength = closeBraceOffset - openBraceOffset; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1012 | if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { |
akling@apple.com | e93cba9 | 2013-01-28 06:34:03 +0000 | [diff] [blame] | 1013 | SourceProviderCacheItemCreationParameters parameters; |
| 1014 | parameters.functionStart = functionStart; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1015 | parameters.closeBraceLine = closeBraceLine; |
| 1016 | parameters.closeBraceOffset = closeBraceOffset; |
| 1017 | parameters.closeBraceLineStartOffset = closeBraceLineStartOffset; |
akling@apple.com | e93cba9 | 2013-01-28 06:34:03 +0000 | [diff] [blame] | 1018 | functionScope->fillParametersForSourceProviderCache(parameters); |
| 1019 | newInfo = SourceProviderCacheItem::create(parameters); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1020 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1021 | } |
oliver@apple.com | 924afcb | 2012-12-06 19:34:27 +0000 | [diff] [blame] | 1022 | context.setFunctionStart(body, functionStart); |
oliver@apple.com | 30b760c | 2012-12-06 19:26:20 +0000 | [diff] [blame] | 1023 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1024 | failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); |
| 1025 | matchOrFail(CLOSEBRACE); |
| 1026 | |
ggaren@apple.com | d17e17e | 2013-02-19 01:39:12 +0000 | [diff] [blame] | 1027 | if (newInfo) |
andersca@apple.com | 2a6c489 | 2013-09-26 20:44:02 +0000 | [diff] [blame] | 1028 | m_functionCache->add(openBraceOffset, std::move(newInfo)); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1029 | |
| 1030 | next(); |
| 1031 | return true; |
| 1032 | } |
| 1033 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1034 | template <typename LexerType> |
| 1035 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1036 | { |
| 1037 | ASSERT(match(FUNCTION)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1038 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1039 | next(); |
| 1040 | const Identifier* name = 0; |
| 1041 | TreeFormalParameterList parameters = 0; |
| 1042 | TreeFunctionBody body = 0; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1043 | unsigned openBraceOffset = 0; |
| 1044 | unsigned closeBraceOffset = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1045 | int bodyStartLine = 0; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1046 | unsigned bodyStartColumn = 0; |
| 1047 | failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn))); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1048 | failIfFalse(name); |
| 1049 | failIfFalseIfStrict(declareVariable(name)); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1050 | return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1051 | } |
| 1052 | |
| 1053 | struct LabelInfo { |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1054 | LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1055 | : m_ident(ident) |
| 1056 | , m_start(start) |
| 1057 | , m_end(end) |
| 1058 | { |
| 1059 | } |
| 1060 | |
| 1061 | const Identifier* m_ident; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1062 | JSTextPosition m_start; |
| 1063 | JSTextPosition m_end; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1064 | }; |
| 1065 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1066 | template <typename LexerType> |
| 1067 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1068 | { |
| 1069 | |
| 1070 | /* Expression and Label statements are ambiguous at LL(1), so we have a |
| 1071 | * special case that looks for a colon as the next character in the input. |
| 1072 | */ |
| 1073 | Vector<LabelInfo> labels; |
mark.lam@apple.com | 0d5fdb9 | 2013-07-24 00:41:46 +0000 | [diff] [blame] | 1074 | JSTokenLocation location; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1075 | do { |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1076 | JSTextPosition start = tokenStartPosition(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1077 | location = tokenLocation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1078 | if (!nextTokenIsColon()) { |
| 1079 | // If we hit this path we're making a expression statement, which |
| 1080 | // by definition can't make use of continue/break so we can just |
| 1081 | // ignore any labels we might have accumulated. |
| 1082 | TreeExpression expression = parseExpression(context); |
| 1083 | failIfFalse(expression); |
| 1084 | failIfFalse(autoSemiColon()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1085 | return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1086 | } |
| 1087 | const Identifier* ident = m_token.m_data.ident; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1088 | JSTextPosition end = tokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1089 | next(); |
| 1090 | consumeOrFail(COLON); |
| 1091 | if (!m_syntaxAlreadyValidated) { |
| 1092 | // This is O(N^2) over the current list of consecutive labels, but I |
| 1093 | // have never seen more than one label in a row in the real world. |
| 1094 | for (size_t i = 0; i < labels.size(); i++) |
| 1095 | failIfTrue(ident->impl() == labels[i].m_ident->impl()); |
| 1096 | failIfTrue(getLabel(ident)); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1097 | labels.append(LabelInfo(ident, start, end)); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1098 | } |
| 1099 | } while (match(IDENT)); |
| 1100 | bool isLoop = false; |
| 1101 | switch (m_token.m_type) { |
| 1102 | case FOR: |
| 1103 | case WHILE: |
| 1104 | case DO: |
| 1105 | isLoop = true; |
| 1106 | break; |
| 1107 | |
| 1108 | default: |
| 1109 | break; |
| 1110 | } |
| 1111 | const Identifier* unused = 0; |
| 1112 | if (!m_syntaxAlreadyValidated) { |
| 1113 | for (size_t i = 0; i < labels.size(); i++) |
| 1114 | pushLabel(labels[i].m_ident, isLoop); |
| 1115 | } |
| 1116 | TreeStatement statement = parseStatement(context, unused); |
| 1117 | if (!m_syntaxAlreadyValidated) { |
| 1118 | for (size_t i = 0; i < labels.size(); i++) |
| 1119 | popLabel(); |
| 1120 | } |
| 1121 | failIfFalse(statement); |
| 1122 | for (size_t i = 0; i < labels.size(); i++) { |
| 1123 | const LabelInfo& info = labels[labels.size() - i - 1]; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1124 | statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1125 | } |
| 1126 | return statement; |
| 1127 | } |
| 1128 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1129 | template <typename LexerType> |
| 1130 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1131 | { |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1132 | JSTextPosition start = tokenStartPosition(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1133 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1134 | TreeExpression expression = parseExpression(context); |
| 1135 | failIfFalse(expression); |
| 1136 | failIfFalse(autoSemiColon()); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1137 | return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1138 | } |
| 1139 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1140 | template <typename LexerType> |
| 1141 | template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1142 | { |
| 1143 | ASSERT(match(IF)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1144 | JSTokenLocation ifLocation(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1145 | int start = tokenLine(); |
| 1146 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1147 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1148 | consumeOrFail(OPENPAREN); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1149 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1150 | TreeExpression condition = parseExpression(context); |
| 1151 | failIfFalse(condition); |
| 1152 | int end = tokenLine(); |
| 1153 | consumeOrFail(CLOSEPAREN); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1154 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1155 | const Identifier* unused = 0; |
| 1156 | TreeStatement trueBlock = parseStatement(context, unused); |
| 1157 | failIfFalse(trueBlock); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1158 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1159 | if (!match(ELSE)) |
ggaren@apple.com | 81c68cc | 2013-04-27 06:43:33 +0000 | [diff] [blame] | 1160 | return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1161 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1162 | Vector<TreeExpression> exprStack; |
andersca@apple.com | c3523f8 | 2013-10-18 23:41:24 +0000 | [diff] [blame] | 1163 | Vector<pair<int, int>> posStack; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1164 | Vector<JSTokenLocation> tokenLocationStack; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1165 | Vector<TreeStatement> statementStack; |
| 1166 | bool trailingElse = false; |
| 1167 | do { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1168 | JSTokenLocation tempLocation = tokenLocation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1169 | next(); |
| 1170 | if (!match(IF)) { |
| 1171 | const Identifier* unused = 0; |
| 1172 | TreeStatement block = parseStatement(context, unused); |
| 1173 | failIfFalse(block); |
| 1174 | statementStack.append(block); |
| 1175 | trailingElse = true; |
| 1176 | break; |
| 1177 | } |
| 1178 | int innerStart = tokenLine(); |
| 1179 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1180 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1181 | consumeOrFail(OPENPAREN); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1182 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1183 | TreeExpression innerCondition = parseExpression(context); |
| 1184 | failIfFalse(innerCondition); |
| 1185 | int innerEnd = tokenLine(); |
| 1186 | consumeOrFail(CLOSEPAREN); |
| 1187 | const Identifier* unused = 0; |
| 1188 | TreeStatement innerTrueBlock = parseStatement(context, unused); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1189 | failIfFalse(innerTrueBlock); |
| 1190 | tokenLocationStack.append(tempLocation); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1191 | exprStack.append(innerCondition); |
| 1192 | posStack.append(make_pair(innerStart, innerEnd)); |
| 1193 | statementStack.append(innerTrueBlock); |
| 1194 | } while (match(ELSE)); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1195 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1196 | if (!trailingElse) { |
| 1197 | TreeExpression condition = exprStack.last(); |
| 1198 | exprStack.removeLast(); |
| 1199 | TreeStatement trueBlock = statementStack.last(); |
| 1200 | statementStack.removeLast(); |
| 1201 | pair<int, int> pos = posStack.last(); |
| 1202 | posStack.removeLast(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1203 | JSTokenLocation elseLocation = tokenLocationStack.last(); |
| 1204 | tokenLocationStack.removeLast(); |
ggaren@apple.com | 81c68cc | 2013-04-27 06:43:33 +0000 | [diff] [blame] | 1205 | statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second)); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1206 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1207 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1208 | while (!exprStack.isEmpty()) { |
| 1209 | TreeExpression condition = exprStack.last(); |
| 1210 | exprStack.removeLast(); |
| 1211 | TreeStatement falseBlock = statementStack.last(); |
| 1212 | statementStack.removeLast(); |
| 1213 | TreeStatement trueBlock = statementStack.last(); |
| 1214 | statementStack.removeLast(); |
| 1215 | pair<int, int> pos = posStack.last(); |
| 1216 | posStack.removeLast(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1217 | JSTokenLocation elseLocation = tokenLocationStack.last(); |
| 1218 | tokenLocationStack.removeLast(); |
| 1219 | statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second)); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1220 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1221 | |
| 1222 | return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1223 | } |
| 1224 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1225 | template <typename LexerType> |
| 1226 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1227 | { |
| 1228 | failIfStackOverflow(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1229 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1230 | TreeExpression node = parseAssignmentExpression(context); |
| 1231 | failIfFalse(node); |
| 1232 | if (!match(COMMA)) |
| 1233 | return node; |
| 1234 | next(); |
| 1235 | m_nonTrivialExpressionCount++; |
| 1236 | m_nonLHSCount++; |
| 1237 | TreeExpression right = parseAssignmentExpression(context); |
| 1238 | failIfFalse(right); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1239 | typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1240 | while (match(COMMA)) { |
| 1241 | next(TreeBuilder::DontBuildStrings); |
| 1242 | right = parseAssignmentExpression(context); |
| 1243 | failIfFalse(right); |
| 1244 | context.appendToComma(commaNode, right); |
| 1245 | } |
| 1246 | return commaNode; |
| 1247 | } |
| 1248 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1249 | template <typename LexerType> |
| 1250 | template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1251 | { |
| 1252 | failIfStackOverflow(); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1253 | JSTextPosition start = tokenStartPosition(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1254 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1255 | int initialAssignmentCount = m_assignmentCount; |
| 1256 | int initialNonLHSCount = m_nonLHSCount; |
| 1257 | TreeExpression lhs = parseConditionalExpression(context); |
| 1258 | failIfFalse(lhs); |
| 1259 | if (initialNonLHSCount != m_nonLHSCount) |
| 1260 | return lhs; |
| 1261 | |
| 1262 | int assignmentStack = 0; |
| 1263 | Operator op; |
| 1264 | bool hadAssignment = false; |
| 1265 | while (true) { |
| 1266 | switch (m_token.m_type) { |
| 1267 | case EQUAL: op = OpEqual; break; |
| 1268 | case PLUSEQUAL: op = OpPlusEq; break; |
| 1269 | case MINUSEQUAL: op = OpMinusEq; break; |
| 1270 | case MULTEQUAL: op = OpMultEq; break; |
| 1271 | case DIVEQUAL: op = OpDivEq; break; |
| 1272 | case LSHIFTEQUAL: op = OpLShift; break; |
| 1273 | case RSHIFTEQUAL: op = OpRShift; break; |
| 1274 | case URSHIFTEQUAL: op = OpURShift; break; |
| 1275 | case ANDEQUAL: op = OpAndEq; break; |
| 1276 | case XOREQUAL: op = OpXOrEq; break; |
| 1277 | case OREQUAL: op = OpOrEq; break; |
| 1278 | case MODEQUAL: op = OpModEq; break; |
| 1279 | default: |
| 1280 | goto end; |
| 1281 | } |
| 1282 | m_nonTrivialExpressionCount++; |
| 1283 | hadAssignment = true; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1284 | context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op); |
| 1285 | start = tokenStartPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1286 | m_assignmentCount++; |
| 1287 | next(TreeBuilder::DontBuildStrings); |
| 1288 | if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) { |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1289 | failIfTrueIfStrictWithMessage(m_vm->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode"); |
| 1290 | failIfTrueIfStrictWithMessage(m_vm->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode"); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1291 | declareWrite(m_lastIdentifier); |
| 1292 | m_lastIdentifier = 0; |
| 1293 | } |
oliver@apple.com | d055db6 | 2013-10-02 19:11:04 +0000 | [diff] [blame] | 1294 | lhs = parseAssignmentExpression(context); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1295 | failIfFalse(lhs); |
| 1296 | if (initialNonLHSCount != m_nonLHSCount) |
| 1297 | break; |
| 1298 | } |
| 1299 | end: |
| 1300 | if (hadAssignment) |
| 1301 | m_nonLHSCount++; |
| 1302 | |
| 1303 | if (!TreeBuilder::CreatesAST) |
| 1304 | return lhs; |
| 1305 | |
| 1306 | while (assignmentStack) |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1307 | lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1308 | |
| 1309 | return lhs; |
| 1310 | } |
| 1311 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1312 | template <typename LexerType> |
| 1313 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1314 | { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1315 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1316 | TreeExpression cond = parseBinaryExpression(context); |
| 1317 | failIfFalse(cond); |
| 1318 | if (!match(QUESTION)) |
| 1319 | return cond; |
| 1320 | m_nonTrivialExpressionCount++; |
| 1321 | m_nonLHSCount++; |
| 1322 | next(TreeBuilder::DontBuildStrings); |
| 1323 | TreeExpression lhs = parseAssignmentExpression(context); |
| 1324 | consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings); |
| 1325 | |
| 1326 | TreeExpression rhs = parseAssignmentExpression(context); |
| 1327 | failIfFalse(rhs); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1328 | return context.createConditionalExpr(location, cond, lhs, rhs); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1329 | } |
| 1330 | |
| 1331 | ALWAYS_INLINE static bool isUnaryOp(JSTokenType token) |
| 1332 | { |
| 1333 | return token & UnaryOpTokenFlag; |
| 1334 | } |
| 1335 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1336 | template <typename LexerType> |
| 1337 | int Parser<LexerType>::isBinaryOperator(JSTokenType token) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1338 | { |
| 1339 | if (m_allowsIn) |
| 1340 | return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift); |
| 1341 | return token & BinaryOpTokenPrecedenceMask; |
| 1342 | } |
| 1343 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1344 | template <typename LexerType> |
| 1345 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1346 | { |
| 1347 | |
| 1348 | int operandStackDepth = 0; |
| 1349 | int operatorStackDepth = 0; |
| 1350 | typename TreeBuilder::BinaryExprContext binaryExprContext(context); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1351 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1352 | while (true) { |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1353 | JSTextPosition exprStart = tokenStartPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1354 | int initialAssignments = m_assignmentCount; |
| 1355 | TreeExpression current = parseUnaryExpression(context); |
| 1356 | failIfFalse(current); |
| 1357 | |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1358 | context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1359 | int precedence = isBinaryOperator(m_token.m_type); |
| 1360 | if (!precedence) |
| 1361 | break; |
| 1362 | m_nonTrivialExpressionCount++; |
| 1363 | m_nonLHSCount++; |
| 1364 | int operatorToken = m_token.m_type; |
| 1365 | next(TreeBuilder::DontBuildStrings); |
| 1366 | |
| 1367 | while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) { |
| 1368 | ASSERT(operandStackDepth > 1); |
| 1369 | |
| 1370 | typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1); |
| 1371 | typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2); |
| 1372 | context.shrinkOperandStackBy(operandStackDepth, 2); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1373 | context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1374 | context.operatorStackPop(operatorStackDepth); |
| 1375 | } |
| 1376 | context.operatorStackAppend(operatorStackDepth, operatorToken, precedence); |
| 1377 | } |
| 1378 | while (operatorStackDepth) { |
| 1379 | ASSERT(operandStackDepth > 1); |
| 1380 | |
| 1381 | typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1); |
| 1382 | typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2); |
| 1383 | context.shrinkOperandStackBy(operandStackDepth, 2); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1384 | context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1385 | context.operatorStackPop(operatorStackDepth); |
| 1386 | } |
| 1387 | return context.popOperandStack(operandStackDepth); |
| 1388 | } |
| 1389 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1390 | template <typename LexerType> |
| 1391 | template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1392 | { |
| 1393 | bool wasIdent = false; |
| 1394 | switch (m_token.m_type) { |
| 1395 | namedProperty: |
| 1396 | case IDENT: |
| 1397 | wasIdent = true; |
| 1398 | case STRING: { |
| 1399 | const Identifier* ident = m_token.m_data.ident; |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1400 | if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set))) |
msaboff@apple.com | 11c2e64 | 2011-11-07 17:54:15 +0000 | [diff] [blame] | 1401 | nextExpectIdentifier(LexerFlagsIgnoreReservedWords); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1402 | else |
msaboff@apple.com | 11c2e64 | 2011-11-07 17:54:15 +0000 | [diff] [blame] | 1403 | nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1404 | |
| 1405 | if (match(COLON)) { |
| 1406 | next(); |
| 1407 | TreeExpression node = parseAssignmentExpression(context); |
| 1408 | failIfFalse(node); |
| 1409 | return context.template createProperty<complete>(ident, node, PropertyNode::Constant); |
| 1410 | } |
| 1411 | failIfFalse(wasIdent); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1412 | const Identifier* accessorName = 0; |
| 1413 | TreeFormalParameterList parameters = 0; |
| 1414 | TreeFunctionBody body = 0; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1415 | unsigned openBraceOffset = 0; |
| 1416 | unsigned closeBraceOffset = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1417 | int bodyStartLine = 0; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1418 | unsigned bodyStartColumn = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1419 | PropertyNode::Type type; |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1420 | if (*ident == m_vm->propertyNames->get) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1421 | type = PropertyNode::Getter; |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1422 | else if (*ident == m_vm->propertyNames->set) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1423 | type = PropertyNode::Setter; |
| 1424 | else |
| 1425 | fail(); |
commit-queue@webkit.org | 54da5c2 | 2012-02-26 22:51:38 +0000 | [diff] [blame] | 1426 | const Identifier* stringPropertyName = 0; |
| 1427 | double numericPropertyName = 0; |
| 1428 | if (m_token.m_type == IDENT || m_token.m_type == STRING) |
| 1429 | stringPropertyName = m_token.m_data.ident; |
| 1430 | else if (m_token.m_type == NUMBER) |
| 1431 | numericPropertyName = m_token.m_data.doubleValue; |
| 1432 | else |
| 1433 | fail(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1434 | JSTokenLocation location(tokenLocation()); |
commit-queue@webkit.org | 54da5c2 | 2012-02-26 22:51:38 +0000 | [diff] [blame] | 1435 | next(); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1436 | failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn))); |
commit-queue@webkit.org | 54da5c2 | 2012-02-26 22:51:38 +0000 | [diff] [blame] | 1437 | if (stringPropertyName) |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1438 | return context.template createGetterOrSetterProperty<complete>(location, type, stringPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); |
| 1439 | return context.template createGetterOrSetterProperty<complete>(const_cast<VM*>(m_vm), location, type, numericPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1440 | } |
| 1441 | case NUMBER: { |
| 1442 | double propertyName = m_token.m_data.doubleValue; |
| 1443 | next(); |
| 1444 | consumeOrFail(COLON); |
| 1445 | TreeExpression node = parseAssignmentExpression(context); |
| 1446 | failIfFalse(node); |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1447 | return context.template createProperty<complete>(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1448 | } |
| 1449 | default: |
| 1450 | failIfFalse(m_token.m_type & KeywordTokenFlag); |
| 1451 | goto namedProperty; |
| 1452 | } |
| 1453 | } |
| 1454 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1455 | template <typename LexerType> |
| 1456 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1457 | { |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1458 | int startOffset = m_token.m_data.offset; |
| 1459 | unsigned oldLineStartOffset = m_lexer->currentLineStartOffset(); |
oliver@apple.com | c800ee0 | 2012-02-02 21:19:53 +0000 | [diff] [blame] | 1460 | unsigned oldLastLineNumber = m_lexer->lastLineNumber(); |
| 1461 | unsigned oldLineNumber = m_lexer->lineNumber(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1462 | consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1463 | JSTokenLocation location(tokenLocation()); |
| 1464 | |
oliver@apple.com | f8ef147 | 2012-04-05 00:56:54 +0000 | [diff] [blame] | 1465 | int oldNonLHSCount = m_nonLHSCount; |
| 1466 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1467 | if (match(CLOSEBRACE)) { |
| 1468 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1469 | return context.createObjectLiteral(location); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1470 | } |
| 1471 | |
| 1472 | TreeProperty property = parseProperty<false>(context); |
| 1473 | failIfFalse(property); |
| 1474 | if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1475 | m_lexer->setOffset(startOffset, oldLineStartOffset); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1476 | next(); |
oliver@apple.com | c800ee0 | 2012-02-02 21:19:53 +0000 | [diff] [blame] | 1477 | m_lexer->setLastLineNumber(oldLastLineNumber); |
| 1478 | m_lexer->setLineNumber(oldLineNumber); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1479 | return parseStrictObjectLiteral(context); |
| 1480 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1481 | TreePropertyList propertyList = context.createPropertyList(location, property); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1482 | TreePropertyList tail = propertyList; |
| 1483 | while (match(COMMA)) { |
| 1484 | next(TreeBuilder::DontBuildStrings); |
| 1485 | // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 |
| 1486 | if (match(CLOSEBRACE)) |
| 1487 | break; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1488 | JSTokenLocation propertyLocation(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1489 | property = parseProperty<false>(context); |
| 1490 | failIfFalse(property); |
| 1491 | if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1492 | m_lexer->setOffset(startOffset, oldLineStartOffset); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1493 | next(); |
oliver@apple.com | c800ee0 | 2012-02-02 21:19:53 +0000 | [diff] [blame] | 1494 | m_lexer->setLastLineNumber(oldLastLineNumber); |
| 1495 | m_lexer->setLineNumber(oldLineNumber); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1496 | return parseStrictObjectLiteral(context); |
| 1497 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1498 | tail = context.createPropertyList(propertyLocation, property, tail); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1499 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1500 | |
| 1501 | location = tokenLocation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1502 | consumeOrFail(CLOSEBRACE); |
| 1503 | |
oliver@apple.com | f8ef147 | 2012-04-05 00:56:54 +0000 | [diff] [blame] | 1504 | m_nonLHSCount = oldNonLHSCount; |
| 1505 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1506 | return context.createObjectLiteral(location, propertyList); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1507 | } |
| 1508 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1509 | template <typename LexerType> |
| 1510 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1511 | { |
| 1512 | consumeOrFail(OPENBRACE); |
| 1513 | |
oliver@apple.com | f8ef147 | 2012-04-05 00:56:54 +0000 | [diff] [blame] | 1514 | int oldNonLHSCount = m_nonLHSCount; |
| 1515 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1516 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1517 | if (match(CLOSEBRACE)) { |
| 1518 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1519 | return context.createObjectLiteral(location); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1520 | } |
| 1521 | |
| 1522 | TreeProperty property = parseProperty<true>(context); |
| 1523 | failIfFalse(property); |
| 1524 | |
| 1525 | typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap; |
| 1526 | ObjectValidationMap objectValidator; |
| 1527 | // Add the first property |
| 1528 | if (!m_syntaxAlreadyValidated) |
| 1529 | objectValidator.add(context.getName(property).impl(), context.getType(property)); |
| 1530 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1531 | TreePropertyList propertyList = context.createPropertyList(location, property); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1532 | TreePropertyList tail = propertyList; |
| 1533 | while (match(COMMA)) { |
| 1534 | next(); |
| 1535 | // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 |
| 1536 | if (match(CLOSEBRACE)) |
| 1537 | break; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1538 | JSTokenLocation propertyLocation(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1539 | property = parseProperty<true>(context); |
| 1540 | failIfFalse(property); |
| 1541 | if (!m_syntaxAlreadyValidated) { |
caio.oliveira@openbossa.org | 4c11ee0 | 2012-03-29 18:48:23 +0000 | [diff] [blame] | 1542 | ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property).impl(), context.getType(property)); |
| 1543 | if (!propertyEntry.isNewEntry) { |
benjamin@webkit.org | ee55405 | 2012-10-07 23:12:07 +0000 | [diff] [blame] | 1544 | failIfTrue(propertyEntry.iterator->value == PropertyNode::Constant); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1545 | failIfTrue(context.getType(property) == PropertyNode::Constant); |
benjamin@webkit.org | ee55405 | 2012-10-07 23:12:07 +0000 | [diff] [blame] | 1546 | failIfTrue(context.getType(property) & propertyEntry.iterator->value); |
| 1547 | propertyEntry.iterator->value |= context.getType(property); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1548 | } |
| 1549 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1550 | tail = context.createPropertyList(propertyLocation, property, tail); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1551 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1552 | |
| 1553 | location = tokenLocation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1554 | consumeOrFail(CLOSEBRACE); |
oliver@apple.com | f8ef147 | 2012-04-05 00:56:54 +0000 | [diff] [blame] | 1555 | |
| 1556 | m_nonLHSCount = oldNonLHSCount; |
| 1557 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1558 | return context.createObjectLiteral(location, propertyList); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1559 | } |
| 1560 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1561 | template <typename LexerType> |
| 1562 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1563 | { |
| 1564 | consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings); |
| 1565 | |
oliver@apple.com | f8ef147 | 2012-04-05 00:56:54 +0000 | [diff] [blame] | 1566 | int oldNonLHSCount = m_nonLHSCount; |
| 1567 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1568 | int elisions = 0; |
| 1569 | while (match(COMMA)) { |
| 1570 | next(TreeBuilder::DontBuildStrings); |
| 1571 | elisions++; |
| 1572 | } |
| 1573 | if (match(CLOSEBRACKET)) { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1574 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1575 | next(TreeBuilder::DontBuildStrings); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1576 | return context.createArray(location, elisions); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1577 | } |
| 1578 | |
oliver@apple.com | 72f8a82 | 2013-10-17 01:02:34 +0000 | [diff] [blame] | 1579 | TreeExpression elem; |
| 1580 | if (UNLIKELY(match(DOTDOTDOT))) { |
| 1581 | auto spreadLocation = m_token.m_location; |
| 1582 | auto start = m_token.m_startPosition; |
| 1583 | auto divot = m_token.m_endPosition; |
| 1584 | next(); |
| 1585 | auto spreadExpr = parseAssignmentExpression(context); |
| 1586 | failIfFalse(spreadExpr); |
| 1587 | elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition); |
| 1588 | } else |
| 1589 | elem = parseAssignmentExpression(context); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1590 | failIfFalse(elem); |
| 1591 | typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem); |
| 1592 | typename TreeBuilder::ElementList tail = elementList; |
| 1593 | elisions = 0; |
| 1594 | while (match(COMMA)) { |
| 1595 | next(TreeBuilder::DontBuildStrings); |
| 1596 | elisions = 0; |
| 1597 | |
| 1598 | while (match(COMMA)) { |
| 1599 | next(); |
| 1600 | elisions++; |
| 1601 | } |
| 1602 | |
| 1603 | if (match(CLOSEBRACKET)) { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1604 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1605 | next(TreeBuilder::DontBuildStrings); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1606 | return context.createArray(location, elisions, elementList); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1607 | } |
oliver@apple.com | 72f8a82 | 2013-10-17 01:02:34 +0000 | [diff] [blame] | 1608 | if (UNLIKELY(match(DOTDOTDOT))) { |
| 1609 | auto spreadLocation = m_token.m_location; |
| 1610 | auto start = m_token.m_startPosition; |
| 1611 | auto divot = m_token.m_endPosition; |
| 1612 | next(); |
| 1613 | TreeExpression elem = parseAssignmentExpression(context); |
| 1614 | failIfFalse(elem); |
| 1615 | auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition); |
| 1616 | tail = context.createElementList(tail, elisions, spread); |
| 1617 | continue; |
| 1618 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1619 | TreeExpression elem = parseAssignmentExpression(context); |
| 1620 | failIfFalse(elem); |
| 1621 | tail = context.createElementList(tail, elisions, elem); |
| 1622 | } |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1623 | |
| 1624 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1625 | consumeOrFail(CLOSEBRACKET); |
| 1626 | |
oliver@apple.com | f8ef147 | 2012-04-05 00:56:54 +0000 | [diff] [blame] | 1627 | m_nonLHSCount = oldNonLHSCount; |
| 1628 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1629 | return context.createArray(location, elementList); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1630 | } |
| 1631 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1632 | template <typename LexerType> |
| 1633 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1634 | { |
| 1635 | failIfStackOverflow(); |
| 1636 | switch (m_token.m_type) { |
| 1637 | case OPENBRACE: |
| 1638 | if (strictMode()) |
| 1639 | return parseStrictObjectLiteral(context); |
| 1640 | return parseObjectLiteral(context); |
| 1641 | case OPENBRACKET: |
| 1642 | return parseArrayLiteral(context); |
| 1643 | case OPENPAREN: { |
| 1644 | next(); |
| 1645 | int oldNonLHSCount = m_nonLHSCount; |
| 1646 | TreeExpression result = parseExpression(context); |
| 1647 | m_nonLHSCount = oldNonLHSCount; |
| 1648 | consumeOrFail(CLOSEPAREN); |
| 1649 | |
| 1650 | return result; |
| 1651 | } |
| 1652 | case THISTOKEN: { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1653 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1654 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1655 | return context.thisExpr(location); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1656 | } |
| 1657 | case IDENT: { |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1658 | JSTextPosition start = tokenStartPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1659 | const Identifier* ident = m_token.m_data.ident; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1660 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1661 | next(); |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1662 | currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1663 | m_lastIdentifier = ident; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1664 | return context.createResolve(location, ident, start); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1665 | } |
| 1666 | case STRING: { |
| 1667 | const Identifier* ident = m_token.m_data.ident; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1668 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1669 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1670 | return context.createString(location, ident); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1671 | } |
| 1672 | case NUMBER: { |
| 1673 | double d = m_token.m_data.doubleValue; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1674 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1675 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1676 | return context.createNumberExpr(location, d); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1677 | } |
| 1678 | case NULLTOKEN: { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1679 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1680 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1681 | return context.createNull(location); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1682 | } |
| 1683 | case TRUETOKEN: { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1684 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1685 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1686 | return context.createBoolean(location, true); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1687 | } |
| 1688 | case FALSETOKEN: { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1689 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1690 | next(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1691 | return context.createBoolean(location, false); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1692 | } |
| 1693 | case DIVEQUAL: |
| 1694 | case DIVIDE: { |
| 1695 | /* regexp */ |
| 1696 | const Identifier* pattern; |
| 1697 | const Identifier* flags; |
| 1698 | if (match(DIVEQUAL)) |
| 1699 | failIfFalse(m_lexer->scanRegExp(pattern, flags, '=')); |
| 1700 | else |
| 1701 | failIfFalse(m_lexer->scanRegExp(pattern, flags)); |
| 1702 | |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1703 | JSTextPosition start = tokenStartPosition(); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1704 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1705 | next(); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1706 | TreeExpression re = context.createRegExp(location, *pattern, *flags, start); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1707 | if (!re) { |
benjamin@webkit.org | c9b7a20 | 2012-09-08 05:46:29 +0000 | [diff] [blame] | 1708 | const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1709 | failWithMessage(yarrErrorMsg); |
| 1710 | } |
| 1711 | return re; |
| 1712 | } |
| 1713 | default: |
| 1714 | fail(); |
| 1715 | } |
| 1716 | } |
| 1717 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1718 | template <typename LexerType> |
oliver@apple.com | 72f8a82 | 2013-10-17 01:02:34 +0000 | [diff] [blame] | 1719 | template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1720 | { |
| 1721 | consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1722 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1723 | if (match(CLOSEPAREN)) { |
| 1724 | next(TreeBuilder::DontBuildStrings); |
| 1725 | return context.createArguments(); |
| 1726 | } |
oliver@apple.com | 72f8a82 | 2013-10-17 01:02:34 +0000 | [diff] [blame] | 1727 | if (match(DOTDOTDOT) && mode == AllowSpread) { |
| 1728 | JSTokenLocation spreadLocation(tokenLocation()); |
| 1729 | auto start = m_token.m_startPosition; |
| 1730 | auto divot = m_token.m_endPosition; |
| 1731 | next(); |
| 1732 | auto spreadExpr = parseAssignmentExpression(context); |
| 1733 | auto end = m_lastTokenEndPosition; |
| 1734 | if (!spreadExpr) |
| 1735 | failWithMessage("Invalid spread expression."); |
| 1736 | consumeOrFail(CLOSEPAREN); |
| 1737 | auto spread = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end); |
| 1738 | TreeArgumentsList argList = context.createArgumentsList(location, spread); |
| 1739 | return context.createArguments(argList); |
| 1740 | } |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1741 | TreeExpression firstArg = parseAssignmentExpression(context); |
| 1742 | failIfFalse(firstArg); |
| 1743 | |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1744 | TreeArgumentsList argList = context.createArgumentsList(location, firstArg); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1745 | TreeArgumentsList tail = argList; |
| 1746 | while (match(COMMA)) { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1747 | JSTokenLocation argumentLocation(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1748 | next(TreeBuilder::DontBuildStrings); |
| 1749 | TreeExpression arg = parseAssignmentExpression(context); |
| 1750 | failIfFalse(arg); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1751 | tail = context.createArgumentsList(argumentLocation, tail, arg); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1752 | } |
| 1753 | consumeOrFail(CLOSEPAREN); |
| 1754 | return context.createArguments(argList); |
| 1755 | } |
| 1756 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1757 | template <typename LexerType> |
| 1758 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1759 | { |
| 1760 | TreeExpression base = 0; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1761 | JSTextPosition expressionStart = tokenStartPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1762 | int newCount = 0; |
mark.lam@apple.com | 0d5fdb9 | 2013-07-24 00:41:46 +0000 | [diff] [blame] | 1763 | JSTokenLocation location; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1764 | while (match(NEW)) { |
| 1765 | next(); |
| 1766 | newCount++; |
| 1767 | } |
| 1768 | |
| 1769 | if (match(FUNCTION)) { |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1770 | const Identifier* name = &m_vm->propertyNames->nullIdentifier; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1771 | TreeFormalParameterList parameters = 0; |
| 1772 | TreeFunctionBody body = 0; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1773 | unsigned openBraceOffset = 0; |
| 1774 | unsigned closeBraceOffset = 0; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1775 | int bodyStartLine = 0; |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1776 | unsigned bodyStartColumn = 0; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1777 | location = tokenLocation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1778 | next(); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1779 | failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn))); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1780 | base = context.createFunctionExpr(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1781 | } else |
| 1782 | base = parsePrimaryExpression(context); |
| 1783 | |
| 1784 | failIfFalse(base); |
| 1785 | while (true) { |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1786 | location = tokenLocation(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1787 | switch (m_token.m_type) { |
| 1788 | case OPENBRACKET: { |
| 1789 | m_nonTrivialExpressionCount++; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1790 | JSTextPosition expressionEnd = lastTokenEndPosition(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1791 | next(); |
| 1792 | int nonLHSCount = m_nonLHSCount; |
| 1793 | int initialAssignments = m_assignmentCount; |
| 1794 | TreeExpression property = parseExpression(context); |
| 1795 | failIfFalse(property); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1796 | base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1797 | consumeOrFail(CLOSEBRACKET); |
| 1798 | m_nonLHSCount = nonLHSCount; |
| 1799 | break; |
| 1800 | } |
| 1801 | case OPENPAREN: { |
| 1802 | m_nonTrivialExpressionCount++; |
oliver@apple.com | 2ea1fd1 | 2012-01-30 23:59:20 +0000 | [diff] [blame] | 1803 | int nonLHSCount = m_nonLHSCount; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1804 | if (newCount) { |
| 1805 | newCount--; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1806 | JSTextPosition expressionEnd = lastTokenEndPosition(); |
oliver@apple.com | 72f8a82 | 2013-10-17 01:02:34 +0000 | [diff] [blame] | 1807 | TreeArguments arguments = parseArguments(context, DontAllowSpread); |
oliver@apple.com | 2ea1fd1 | 2012-01-30 23:59:20 +0000 | [diff] [blame] | 1808 | failIfFalse(arguments); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1809 | base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1810 | } else { |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1811 | JSTextPosition expressionEnd = lastTokenEndPosition(); |
oliver@apple.com | 72f8a82 | 2013-10-17 01:02:34 +0000 | [diff] [blame] | 1812 | TreeArguments arguments = parseArguments(context, AllowSpread); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1813 | failIfFalse(arguments); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1814 | base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1815 | } |
oliver@apple.com | 2ea1fd1 | 2012-01-30 23:59:20 +0000 | [diff] [blame] | 1816 | m_nonLHSCount = nonLHSCount; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1817 | break; |
| 1818 | } |
| 1819 | case DOT: { |
| 1820 | m_nonTrivialExpressionCount++; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1821 | JSTextPosition expressionEnd = lastTokenEndPosition(); |
msaboff@apple.com | 11c2e64 | 2011-11-07 17:54:15 +0000 | [diff] [blame] | 1822 | nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1823 | matchOrFail(IDENT); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1824 | base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1825 | next(); |
| 1826 | break; |
| 1827 | } |
| 1828 | default: |
| 1829 | goto endMemberExpression; |
| 1830 | } |
| 1831 | } |
| 1832 | endMemberExpression: |
| 1833 | while (newCount--) |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1834 | base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1835 | return base; |
| 1836 | } |
| 1837 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1838 | template <typename LexerType> |
| 1839 | template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context) |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1840 | { |
| 1841 | typename TreeBuilder::UnaryExprContext unaryExprContext(context); |
| 1842 | AllowInOverride allowInOverride(this); |
| 1843 | int tokenStackDepth = 0; |
| 1844 | bool modifiesExpr = false; |
| 1845 | bool requiresLExpr = false; |
| 1846 | while (isUnaryOp(m_token.m_type)) { |
| 1847 | if (strictMode()) { |
| 1848 | switch (m_token.m_type) { |
| 1849 | case PLUSPLUS: |
| 1850 | case MINUSMINUS: |
| 1851 | case AUTOPLUSPLUS: |
| 1852 | case AUTOMINUSMINUS: |
| 1853 | failIfTrue(requiresLExpr); |
| 1854 | modifiesExpr = true; |
| 1855 | requiresLExpr = true; |
| 1856 | break; |
| 1857 | case DELETETOKEN: |
| 1858 | failIfTrue(requiresLExpr); |
| 1859 | requiresLExpr = true; |
| 1860 | break; |
| 1861 | default: |
| 1862 | failIfTrue(requiresLExpr); |
| 1863 | break; |
| 1864 | } |
| 1865 | } |
| 1866 | m_nonLHSCount++; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1867 | context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1868 | next(); |
| 1869 | m_nonTrivialExpressionCount++; |
| 1870 | } |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1871 | JSTextPosition subExprStart = tokenStartPosition(); |
| 1872 | ASSERT(subExprStart.offset >= subExprStart.lineStartOffset); |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1873 | JSTokenLocation location(tokenLocation()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1874 | TreeExpression expr = parseMemberExpression(context); |
| 1875 | failIfFalse(expr); |
| 1876 | bool isEvalOrArguments = false; |
| 1877 | if (strictMode() && !m_syntaxAlreadyValidated) { |
| 1878 | if (context.isResolve(expr)) |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 1879 | isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments; |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1880 | } |
| 1881 | failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments && modifiesExpr, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); |
| 1882 | switch (m_token.m_type) { |
| 1883 | case PLUSPLUS: |
| 1884 | m_nonTrivialExpressionCount++; |
| 1885 | m_nonLHSCount++; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1886 | expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1887 | m_assignmentCount++; |
| 1888 | failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); |
| 1889 | failIfTrueIfStrict(requiresLExpr); |
| 1890 | next(); |
| 1891 | break; |
| 1892 | case MINUSMINUS: |
| 1893 | m_nonTrivialExpressionCount++; |
| 1894 | m_nonLHSCount++; |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1895 | expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition()); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1896 | m_assignmentCount++; |
| 1897 | failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); |
| 1898 | failIfTrueIfStrict(requiresLExpr); |
| 1899 | next(); |
| 1900 | break; |
| 1901 | default: |
| 1902 | break; |
| 1903 | } |
| 1904 | |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1905 | JSTextPosition end = lastTokenEndPosition(); |
mark.lam@apple.com | 5b45f90 | 2013-07-09 16:15:12 +0000 | [diff] [blame] | 1906 | |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1907 | if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode())) |
| 1908 | return expr; |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1909 | |
| 1910 | location = tokenLocation(); |
| 1911 | location.line = m_lexer->lastLineNumber(); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1912 | while (tokenStackDepth) { |
| 1913 | switch (context.unaryTokenStackLastType(tokenStackDepth)) { |
| 1914 | case EXCLAMATION: |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1915 | expr = context.createLogicalNot(location, expr); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1916 | break; |
| 1917 | case TILDE: |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1918 | expr = context.makeBitwiseNotNode(location, expr); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1919 | break; |
| 1920 | case MINUS: |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1921 | expr = context.makeNegateNode(location, expr); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1922 | break; |
| 1923 | case PLUS: |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1924 | expr = context.createUnaryPlus(location, expr); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1925 | break; |
| 1926 | case PLUSPLUS: |
| 1927 | case AUTOPLUSPLUS: |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1928 | expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1929 | m_assignmentCount++; |
| 1930 | break; |
| 1931 | case MINUSMINUS: |
| 1932 | case AUTOMINUSMINUS: |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1933 | expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1934 | m_assignmentCount++; |
| 1935 | break; |
| 1936 | case TYPEOF: |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1937 | expr = context.makeTypeOfNode(location, expr); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1938 | break; |
| 1939 | case VOIDTOKEN: |
commit-queue@webkit.org | 1b331cb | 2012-08-06 03:16:46 +0000 | [diff] [blame] | 1940 | expr = context.createVoid(location, expr); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1941 | break; |
| 1942 | case DELETETOKEN: |
| 1943 | failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode"); |
mark.lam@apple.com | 3b256ca | 2013-07-30 17:01:40 +0000 | [diff] [blame] | 1944 | expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); |
msaboff@apple.com | 2e5003e | 2011-10-31 22:13:01 +0000 | [diff] [blame] | 1945 | break; |
| 1946 | default: |
| 1947 | // If we get here something has gone horribly horribly wrong |
| 1948 | CRASH(); |
| 1949 | } |
| 1950 | subExprStart = context.unaryTokenStackLastStart(tokenStackDepth); |
| 1951 | context.unaryTokenStackRemoveLast(tokenStackDepth); |
| 1952 | } |
| 1953 | return expr; |
| 1954 | } |
| 1955 | |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1956 | // Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h |
andersca@apple.com | c3523f8 | 2013-10-18 23:41:24 +0000 | [diff] [blame] | 1957 | template class Parser<Lexer<LChar>>; |
| 1958 | template class Parser<Lexer<UChar>>; |
msaboff@apple.com | 831599f | 2011-11-08 22:49:27 +0000 | [diff] [blame] | 1959 | |
cwzwarich@webkit.org | 3f782f6 | 2008-09-08 01:28:33 +0000 | [diff] [blame] | 1960 | } // namespace JSC |