blob: d77ff4895e45ce30d107b9b064e40dbeb2cb9131 [file] [log] [blame]
darin7bca1982006-03-06 05:29:48 +00001/*
darin7bca1982006-03-06 05:29:48 +00002 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
mark.lam@apple.comfaa53932013-03-20 09:09:38 +00004 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
darin7bca1982006-03-06 05:29:48 +00005 *
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.com2e5003e2011-10-31 22:13:01 +000026#include "ASTBuilder.h"
27#include "CodeBlock.h"
cwzwarich@webkit.orga691b5a2008-10-31 05:56:58 +000028#include "Debugger.h"
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000029#include "JSCJSValueInlines.h"
cwzwarich@webkit.org3ff0e6a2008-11-07 00:18:07 +000030#include "Lexer.h"
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000031#include "NodeInfo.h"
32#include "SourceProvider.h"
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000033#include "VM.h"
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000034#include <utility>
35#include <wtf/HashFunctions.h>
36#include <wtf/OwnPtr.h>
commit-queue@webkit.orgad641af2013-02-26 09:07:57 +000037#include <wtf/WTFThreadData.h>
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000038
benjamin@webkit.org74385212013-04-11 03:17:08 +000039#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.com150e5ae2012-10-12 23:48:18 +000044#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.com8b97fde2012-10-22 22:09:58 +000059#define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
andersca@apple.com150e5ae2012-10-12 23:48:18 +000060
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000061using namespace std;
mrowe@apple.comcf11a5d2007-11-16 07:47:52 +000062
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000063namespace JSC {
darin7bca1982006-03-06 05:29:48 +000064
msaboff@apple.com831599f2011-11-08 22:49:27 +000065template <typename LexerType>
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000066Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
67 : m_vm(vm)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000068 , m_source(&source)
mark.lam@apple.combd1385d2013-06-21 23:58:52 +000069 , m_stack(*vm, wtfThreadData().stack())
mark.lam@apple.com8b97fde2012-10-22 22:09:58 +000070 , m_hasStackOverflow(false)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000071 , m_allowsIn(true)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000072 , 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.com7dc06ff2007-11-16 06:54:09 +000079{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000080 m_lexer = adoptPtr(new LexerType(vm));
81 m_arena = m_vm->parserArena.get();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000082 m_lexer->setCode(source, m_arena);
mark.lam@apple.comf0972602013-08-07 00:19:28 +000083 m_token.m_location.line = source.firstLine();
84 m_token.m_location.startOffset = source.startOffset();
mark.lam@apple.com5b45f902013-07-09 16:15:12 +000085 m_token.m_location.endOffset = source.startOffset();
86 m_token.m_location.lineStartOffset = source.startOffset();
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000087 m_functionCache = vm->addSourceProviderCache(source.provider());
oliver@apple.com6bc11372012-05-07 23:35:52 +000088 ScopeRef scope = pushScope();
wingo@igalia.com0700f682012-03-09 12:06:48 +000089 if (parserMode == JSParseFunctionCode)
oliver@apple.com6bc11372012-05-07 23:35:52 +000090 scope->setIsFunction();
91 if (strictness == JSParseStrict)
92 scope->setStrictMode();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +000093 if (parameters) {
oliver@apple.comd055db62013-10-02 19:11:04 +000094 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 }
darin7bca1982006-03-06 05:29:48 +0000100 }
ggaren@apple.comf8200082012-09-07 01:42:53 +0000101 if (!name.isNull())
102 scope->declareCallee(&name);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000103 next();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000104}
105
msaboff@apple.com831599f2011-11-08 22:49:27 +0000106template <typename LexerType>
107Parser<LexerType>::~Parser()
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000108{
109}
110
msaboff@apple.com831599f2011-11-08 22:49:27 +0000111template <typename LexerType>
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000112String Parser<LexerType>::parseInner()
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000113{
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000114 String parseError = String();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000115
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000116 ASTBuilder context(const_cast<VM*>(m_vm), const_cast<SourceCode*>(m_source));
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000117 if (m_lexer->isReparsing())
118 m_statementDepth--;
119 ScopeRef scope = currentScope();
120 SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
benjamin@webkit.org74385212013-04-11 03:17:08 +0000121 if (!sourceElements || !consume(EOFTOK)) {
122 if (hasError())
123 parseError = m_errorMessage;
124 else
125 parseError = ASCIILiteral("Parser error");
126 }
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000127
128 IdentifierSet capturedVariables;
oliver@apple.com2cfd3762013-08-06 21:20:10 +0000129 bool modifiedParameter = false;
130 scope->getCapturedVariables(capturedVariables, modifiedParameter);
oliver@apple.com6bc11372012-05-07 23:35:52 +0000131 CodeFeatures features = context.features();
132 if (scope->strictMode())
133 features |= StrictModeFeature;
134 if (scope->shadowsArguments())
135 features |= ShadowsArgumentsFeature;
oliver@apple.com2cfd3762013-08-06 21:20:10 +0000136 if (modifiedParameter)
137 features |= ModifiedParameterFeature;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000138
oliver@apple.com6bc11372012-05-07 23:35:52 +0000139 didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000140 context.numConstants(), capturedVariables);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000141
142 return parseError;
darin7bca1982006-03-06 05:29:48 +0000143}
144
msaboff@apple.com831599f2011-11-08 22:49:27 +0000145template <typename LexerType>
146void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack,
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000147 ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars)
ggaren@apple.com0195b0b2007-12-21 02:18:11 +0000148{
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000149 m_sourceElements = sourceElements;
ggaren@apple.com0195b0b2007-12-21 02:18:11 +0000150 m_varDeclarations = varStack;
151 m_funcDeclarations = funcStack;
oliver@apple.com09ed6d02010-09-16 00:05:13 +0000152 m_capturedVariables.swap(capturedVars);
oliver@apple.com6bc11372012-05-07 23:35:52 +0000153 m_features = features;
cwzwarich@webkit.org300bb752008-08-06 10:37:34 +0000154 m_numConstants = numConstants;
ggaren@apple.com0195b0b2007-12-21 02:18:11 +0000155}
156
msaboff@apple.com831599f2011-11-08 22:49:27 +0000157template <typename LexerType>
158bool Parser<LexerType>::allowAutomaticSemicolon()
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000159{
160 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
161}
162
msaboff@apple.com831599f2011-11-08 22:49:27 +0000163template <typename LexerType>
164template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000165{
ariya@webkit.org1664b942011-11-08 02:25:20 +0000166 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000167 TreeSourceElements sourceElements = context.createSourceElements();
168 bool seenNonDirective = false;
169 const Identifier* directive = 0;
ariya@webkit.org1664b942011-11-08 02:25:20 +0000170 unsigned directiveLiteralLength = 0;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000171 unsigned startOffset = m_token.m_location.startOffset;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000172 unsigned startLineStartOffset = m_token.m_location.lineStartOffset;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000173 unsigned oldLastLineNumber = m_lexer->lastLineNumber();
174 unsigned oldLineNumber = m_lexer->lineNumber();
175 bool hasSetStrict = false;
ariya@webkit.org1664b942011-11-08 02:25:20 +0000176 while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000177 if (mode == CheckForStrictMode && !seenNonDirective) {
178 if (directive) {
ariya@webkit.org1664b942011-11-08 02:25:20 +0000179 // "use strict" must be the exact literal without escape sequences or line continuation.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000180 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
oliver@apple.com6bc11372012-05-07 23:35:52 +0000181 setStrictMode();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000182 hasSetStrict = true;
183 failIfFalse(isValidStrictMode());
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000184 m_lexer->setOffset(startOffset, startLineStartOffset);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000185 next();
186 m_lexer->setLastLineNumber(oldLastLineNumber);
187 m_lexer->setLineNumber(oldLineNumber);
benjamin@webkit.org74385212013-04-11 03:17:08 +0000188 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000189 continue;
190 }
191 } else
192 seenNonDirective = true;
193 }
194 context.appendStatement(sourceElements, statement);
195 }
benjamin@webkit.org74385212013-04-11 03:17:08 +0000196
197 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000198 return sourceElements;
199}
200
msaboff@apple.com831599f2011-11-08 22:49:27 +0000201template <typename LexerType>
202template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaration(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000203{
204 ASSERT(match(VAR));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000205 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000206 int start = tokenLine();
207 int end = 0;
208 int scratch;
oliver@apple.comd055db62013-10-02 19:11:04 +0000209 TreeDeconstructionPattern scratch1 = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000210 TreeExpression scratch2 = 0;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000211 JSTextPosition scratch3;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000212 TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
benjamin@webkit.org74385212013-04-11 03:17:08 +0000213 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000214 failIfFalse(autoSemiColon());
215
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000216 return context.createVarStatement(location, varDecls, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000217}
218
msaboff@apple.com831599f2011-11-08 22:49:27 +0000219template <typename LexerType>
220template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000221{
222 ASSERT(match(CONSTTOKEN));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000223 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000224 int start = tokenLine();
225 int end = 0;
226 TreeConstDeclList constDecls = parseConstDeclarationList(context);
benjamin@webkit.org74385212013-04-11 03:17:08 +0000227 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000228 failIfFalse(autoSemiColon());
229
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000230 return context.createConstStatement(location, constDecls, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000231}
232
msaboff@apple.com831599f2011-11-08 22:49:27 +0000233template <typename LexerType>
234template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000235{
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.org1b331cb2012-08-06 03:16:46 +0000245 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000246 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.org1b331cb2012-08-06 03:16:46 +0000253 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000254}
255
msaboff@apple.com831599f2011-11-08 22:49:27 +0000256template <typename LexerType>
257template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000258{
259 ASSERT(match(WHILE));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000260 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000261 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.org1b331cb2012-08-06 03:16:46 +0000273 return context.createWhileStatement(location, expr, statement, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000274}
275
msaboff@apple.com831599f2011-11-08 22:49:27 +0000276template <typename LexerType>
oliver@apple.comd055db62013-10-02 19:11:04 +0000277template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarationList(TreeBuilder& context, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000278{
279 TreeExpression varDecls = 0;
oliver@apple.comd055db62013-10-02 19:11:04 +0000280 const Identifier* lastIdent;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000281 do {
oliver@apple.comd055db62013-10-02 19:11:04 +0000282 lastIdent = 0;
283 lastPattern = 0;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000284 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000285 next();
oliver@apple.comd055db62013-10-02 19:11:04 +0000286 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.com20a9bf02013-10-04 20:35:24 +0000297 context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0);
oliver@apple.comd055db62013-10-02 19:11:04 +0000298 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.comd055db62013-10-02 19:11:04 +0000320 }
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000321
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000322 if (hasInitializer) {
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000323 if (!varDecls)
324 varDecls = node;
325 else
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000326 varDecls = context.combineCommaNodes(location, varDecls, node);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000327 }
328 } while (match(COMMA));
oliver@apple.comd055db62013-10-02 19:11:04 +0000329 if (lastIdent)
330 lastPattern = createBindingPattern<DeconstructToVariables>(context, *lastIdent, 0);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000331 return varDecls;
332}
333
msaboff@apple.com831599f2011-11-08 22:49:27 +0000334template <typename LexerType>
oliver@apple.comd055db62013-10-02 19:11:04 +0000335template <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
362template <typename LexerType>
363template <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
439template <typename LexerType>
msaboff@apple.com831599f2011-11-08 22:49:27 +0000440template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000441{
442 failIfTrue(strictMode());
443 TreeConstDeclList constDecls = 0;
444 TreeConstDeclList tail = 0;
445 do {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000446 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000447 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.com5b45f902013-07-09 16:15:12 +0000454
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000455 TreeExpression initializer = 0;
456 if (hasInitializer) {
457 next(TreeBuilder::DontBuildStrings); // consume '='
458 initializer = parseAssignmentExpression(context);
459 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000460 tail = context.appendConstDecl(location, tail, name, initializer);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000461 if (!constDecls)
462 constDecls = tail;
463 } while (match(COMMA));
464 return constDecls;
465}
466
msaboff@apple.com831599f2011-11-08 22:49:27 +0000467template <typename LexerType>
468template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000469{
470 ASSERT(match(FOR));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000471 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000472 int startLine = tokenLine();
473 next();
474 consumeOrFail(OPENPAREN);
475 int nonLHSCount = m_nonLHSCount;
476 int declarations = 0;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000477 JSTextPosition declsStart;
478 JSTextPosition declsEnd;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000479 TreeExpression decls = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000480 if (match(VAR)) {
481 /*
482 for (var IDENT in expression) statement
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000483 for (var varDeclarationList; expressionOpt; expressionOpt)
484 */
oliver@apple.comd055db62013-10-02 19:11:04 +0000485 TreeDeconstructionPattern forInTarget = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000486 TreeExpression forInInitializer = 0;
487 m_allowsIn = false;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000488 JSTextPosition initStart;
489 JSTextPosition initEnd;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000490 decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
491 m_allowsIn = true;
benjamin@webkit.org74385212013-04-11 03:17:08 +0000492 failIfTrue(hasError());
493
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000494 // Remainder of a standard for loop is handled identically
495 if (match(SEMICOLON))
496 goto standardForLoop;
497
498 failIfFalse(declarations == 1);
oliver@apple.com87881002013-09-13 21:19:38 +0000499 failIfTrueWithMessage(forInInitializer, "Cannot use initialiser syntax in a for-in loop");
oliver@apple.comd055db62013-10-02 19:11:04 +0000500
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000501 // Handle for-in with var declaration
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000502 JSTextPosition inLocation = tokenStartPosition();
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000503 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.com2e5003e2011-10-31 22:13:01 +0000509
510 TreeExpression expr = parseExpression(context);
511 failIfFalse(expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000512 JSTextPosition exprEnd = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000513
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.com20a9bf02013-10-04 20:35:24 +0000522 if (isOfEnumeration)
523 return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
oliver@apple.com87881002013-09-13 21:19:38 +0000524 return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000525 }
526
527 if (!match(SEMICOLON)) {
528 m_allowsIn = false;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000529 declsStart = tokenStartPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000530 decls = parseExpression(context);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000531 declsEnd = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000532 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.org1b331cb2012-08-06 03:16:46 +0000560 return context.createForLoop(location, decls, condition, increment, statement, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000561 }
562
563 // For-in loop
564 failIfFalse(nonLHSCount == m_nonLHSCount);
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000565 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.com2e5003e2011-10-31 22:13:01 +0000571 TreeExpression expr = parseExpression(context);
572 failIfFalse(expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000573 JSTextPosition exprEnd = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000574 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.com20a9bf02013-10-04 20:35:24 +0000581 if (isOfEnumeration)
582 return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000583 return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000584}
585
msaboff@apple.com831599f2011-11-08 22:49:27 +0000586template <typename LexerType>
587template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000588{
589 ASSERT(match(BREAK));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000590 JSTokenLocation location(tokenLocation());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000591 JSTextPosition start = tokenStartPosition();
592 JSTextPosition end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000593 next();
594
595 if (autoSemiColon()) {
596 failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000597 return context.createBreakStatement(location, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000598 }
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.com3b256ca2013-07-30 17:01:40 +0000602 end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000603 next();
604 failIfFalse(autoSemiColon());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000605 return context.createBreakStatement(location, ident, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000606}
607
msaboff@apple.com831599f2011-11-08 22:49:27 +0000608template <typename LexerType>
609template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000610{
611 ASSERT(match(CONTINUE));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000612 JSTokenLocation location(tokenLocation());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000613 JSTextPosition start = tokenStartPosition();
614 JSTextPosition end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000615 next();
616
617 if (autoSemiColon()) {
618 failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000619 return context.createContinueStatement(location, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000620 }
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.com3b256ca2013-07-30 17:01:40 +0000626 end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000627 next();
628 failIfFalse(autoSemiColon());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000629 return context.createContinueStatement(location, ident, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000630}
631
msaboff@apple.com831599f2011-11-08 22:49:27 +0000632template <typename LexerType>
633template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000634{
635 ASSERT(match(RETURN));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000636 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000637 failIfFalse(currentScope()->isFunction());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000638 JSTextPosition start = tokenStartPosition();
639 JSTextPosition end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000640 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.com3b256ca2013-07-30 17:01:40 +0000645 end = tokenEndPosition();
646
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000647 if (autoSemiColon())
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000648 return context.createReturnStatement(location, 0, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000649 TreeExpression expr = parseExpression(context);
650 failIfFalse(expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000651 end = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000652 if (match(SEMICOLON))
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000653 end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000654 failIfFalse(autoSemiColon());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000655 return context.createReturnStatement(location, expr, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000656}
657
msaboff@apple.com831599f2011-11-08 22:49:27 +0000658template <typename LexerType>
659template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000660{
661 ASSERT(match(THROW));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000662 JSTokenLocation location(tokenLocation());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000663 JSTextPosition start = tokenStartPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000664 next();
665
666 failIfTrue(autoSemiColon());
667
668 TreeExpression expr = parseExpression(context);
669 failIfFalse(expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000670 JSTextPosition end = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000671 failIfFalse(autoSemiColon());
672
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000673 return context.createThrowStatement(location, expr, start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000674}
675
msaboff@apple.com831599f2011-11-08 22:49:27 +0000676template <typename LexerType>
677template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000678{
679 ASSERT(match(WITH));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000680 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000681 failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
oliver@apple.com6bc11372012-05-07 23:35:52 +0000682 currentScope()->setNeedsFullActivation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000683 int startLine = tokenLine();
684 next();
685 consumeOrFail(OPENPAREN);
686 int start = tokenStart();
687 TreeExpression expr = parseExpression(context);
688 failIfFalse(expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000689 JSTextPosition end = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000690 int endLine = tokenLine();
691 consumeOrFail(CLOSEPAREN);
692 const Identifier* unused = 0;
693 TreeStatement statement = parseStatement(context, unused);
694 failIfFalse(statement);
695
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000696 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000697}
698
msaboff@apple.com831599f2011-11-08 22:49:27 +0000699template <typename LexerType>
700template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000701{
702 ASSERT(match(SWITCH));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000703 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000704 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.org74385212013-04-11 03:17:08 +0000714 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000715
716 TreeClause defaultClause = parseSwitchDefaultClause(context);
benjamin@webkit.org74385212013-04-11 03:17:08 +0000717 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000718
719 TreeClauseList secondClauses = parseSwitchClauses(context);
benjamin@webkit.org74385212013-04-11 03:17:08 +0000720 failIfTrue(hasError());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000721 endSwitch();
722 consumeOrFail(CLOSEBRACE);
723
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000724 return context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000725
726}
727
msaboff@apple.com831599f2011-11-08 22:49:27 +0000728template <typename LexerType>
729template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000730{
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.com831599f2011-11-08 22:49:27 +0000756template <typename LexerType>
757template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000758{
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.com831599f2011-11-08 22:49:27 +0000768template <typename LexerType>
769template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000770{
771 ASSERT(match(TRY));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000772 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000773 TreeStatement tryBlock = 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000774 const Identifier* ident = &m_vm->propertyNames->nullIdentifier;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000775 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.com3b256ca2013-07-30 17:01:40 +0000783 int lastLine = m_lastTokenEndPosition.line;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000784
785 if (match(CATCH)) {
oliver@apple.com6bc11372012-05-07 23:35:52 +0000786 currentScope()->setNeedsFullActivation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000787 next();
788 consumeOrFail(OPENPAREN);
789 matchOrFail(IDENT);
790 ident = m_token.m_data.ident;
791 next();
oliver@apple.com6bc11372012-05-07 23:35:52 +0000792 AutoPopScopeRef catchScope(this, pushScope());
commit-queue@webkit.org4c5567d2011-12-15 13:45:56 +0000793 failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode");
oliver@apple.com6bc11372012-05-07 23:35:52 +0000794 catchScope->preventNewDecls();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000795 consumeOrFail(CLOSEPAREN);
796 matchOrFail(OPENBRACE);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000797 catchBlock = parseBlockStatement(context);
798 failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block");
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000799 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.org1b331cb2012-08-06 03:16:46 +0000809 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000810}
811
msaboff@apple.com831599f2011-11-08 22:49:27 +0000812template <typename LexerType>
813template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000814{
815 ASSERT(match(DEBUGGER));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000816 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000817 int startLine = tokenLine();
818 int endLine = startLine;
819 next();
820 if (match(SEMICOLON))
821 startLine = tokenLine();
822 failIfFalse(autoSemiColon());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000823 return context.createDebugger(location, startLine, endLine);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000824}
825
msaboff@apple.com831599f2011-11-08 22:49:27 +0000826template <typename LexerType>
827template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000828{
829 ASSERT(match(OPENBRACE));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000830 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000831 int start = tokenLine();
832 next();
833 if (match(CLOSEBRACE)) {
834 next();
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000835 return context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000836 }
837 TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
838 failIfFalse(subtree);
839 matchOrFail(CLOSEBRACE);
840 next();
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000841 return context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000842}
843
msaboff@apple.com831599f2011-11-08 22:49:27 +0000844template <typename LexerType>
845template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000846{
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.org1b331cb2012-08-06 03:16:46 +0000862 case SEMICOLON: {
863 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000864 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000865 return context.createEmptyStatement(location);
866 }
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000867 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.org1664b942011-11-08 02:25:20 +0000901 if (directiveLiteralLength)
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000902 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000903 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.com831599f2011-11-08 22:49:27 +0000912template <typename LexerType>
913template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000914{
oliver@apple.comd055db62013-10-02 19:11:04 +0000915 auto parameter = parseDeconstructionPattern<DeconstructToParameters>(context);
916 failIfFalse(parameter);
917 TreeFormalParameterList list = context.createFormalParameterList(parameter);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000918 TreeFormalParameterList tail = list;
oliver@apple.comd055db62013-10-02 19:11:04 +0000919 while (consume(COMMA)) {
920 parameter = parseDeconstructionPattern<DeconstructToParameters>(context);
921 failIfFalse(parameter);
922 tail = context.createFormalParameterList(tail, parameter);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000923 }
924 return list;
925}
926
msaboff@apple.com831599f2011-11-08 22:49:27 +0000927template <typename LexerType>
928template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000929{
mark.lam@apple.comfaa53932013-03-20 09:09:38 +0000930 JSTokenLocation startLocation(tokenLocation());
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000931 unsigned startColumn = tokenColumn();
mark.lam@apple.comfaa53932013-03-20 09:09:38 +0000932 next();
933
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000934 if (match(CLOSEBRACE))
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000935 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000936 DepthManager statementDepth(&m_statementDepth);
937 m_statementDepth = 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000938 typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000939 failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000940 return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000941}
942
msaboff@apple.com831599f2011-11-08 22:49:27 +0000943template <typename LexerType>
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000944template <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.com2e5003e2011-10-31 22:13:01 +0000945{
oliver@apple.com6bc11372012-05-07 23:35:52 +0000946 AutoPopScopeRef functionScope(this, pushScope());
947 functionScope->setIsFunction();
oliver@apple.comd6b8be42012-11-28 21:11:53 +0000948 int functionStart = m_token.m_location.startOffset;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000949 if (match(IDENT)) {
950 name = m_token.m_data.ident;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000951 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.com5b45f902013-07-09 16:15:12 +0000964 openBraceOffset = m_token.m_data.offset;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000965 bodyStartLine = tokenLine();
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000966 bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
mark.lam@apple.comfaa53932013-03-20 09:09:38 +0000967 JSTokenLocation startLocation(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000968
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.com5b45f902013-07-09 16:15:12 +0000970 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 0) {
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000971 // If we're in a strict context, the cached function info must say it was strict too.
oliver@apple.com6bc11372012-05-07 23:35:52 +0000972 ASSERT(!strictMode() || cachedInfo->strictMode);
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000973 JSTokenLocation endLocation;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000974
mark.lam@apple.comfaa53932013-03-20 09:09:38 +0000975 endLocation.line = cachedInfo->closeBraceLine;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000976 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.com2e5003e2011-10-31 22:13:01 +0000981
akling@apple.come93cba92013-01-28 06:34:03 +0000982 functionScope->restoreFromSourceProviderCache(cachedInfo);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000983 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
984
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000985 closeBraceOffset = cachedInfo->closeBraceOffset;
986
oliver@apple.com924afcb2012-12-06 19:34:27 +0000987 context.setFunctionStart(body, functionStart);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000988 m_token = cachedInfo->closeBraceToken();
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000989
990 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000991 m_lexer->setLineNumber(m_token.m_location.line);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000992
993 next();
994 return true;
995 }
996
msaboff@apple.com2e5003e2011-10-31 22:13:01 +0000997 body = parseFunctionBody(context);
998 failIfFalse(body);
999 if (functionScope->strictMode() && name) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001000 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.com2e5003e2011-10-31 22:13:01 +00001002 }
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001003 closeBraceOffset = m_token.m_data.offset;
1004 unsigned closeBraceLine = m_token.m_data.line;
1005 unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001006
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.comd17e17e2013-02-19 01:39:12 +00001009 static const int minimumFunctionLengthToCache = 16;
andersca@apple.com2a6c4892013-09-26 20:44:02 +00001010 std::unique_ptr<SourceProviderCacheItem> newInfo;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001011 int functionLength = closeBraceOffset - openBraceOffset;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001012 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
akling@apple.come93cba92013-01-28 06:34:03 +00001013 SourceProviderCacheItemCreationParameters parameters;
1014 parameters.functionStart = functionStart;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001015 parameters.closeBraceLine = closeBraceLine;
1016 parameters.closeBraceOffset = closeBraceOffset;
1017 parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
akling@apple.come93cba92013-01-28 06:34:03 +00001018 functionScope->fillParametersForSourceProviderCache(parameters);
1019 newInfo = SourceProviderCacheItem::create(parameters);
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001020
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001021 }
oliver@apple.com924afcb2012-12-06 19:34:27 +00001022 context.setFunctionStart(body, functionStart);
oliver@apple.com30b760c2012-12-06 19:26:20 +00001023
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001024 failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
1025 matchOrFail(CLOSEBRACE);
1026
ggaren@apple.comd17e17e2013-02-19 01:39:12 +00001027 if (newInfo)
andersca@apple.com2a6c4892013-09-26 20:44:02 +00001028 m_functionCache->add(openBraceOffset, std::move(newInfo));
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001029
1030 next();
1031 return true;
1032}
1033
msaboff@apple.com831599f2011-11-08 22:49:27 +00001034template <typename LexerType>
1035template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001036{
1037 ASSERT(match(FUNCTION));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001038 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001039 next();
1040 const Identifier* name = 0;
1041 TreeFormalParameterList parameters = 0;
1042 TreeFunctionBody body = 0;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001043 unsigned openBraceOffset = 0;
1044 unsigned closeBraceOffset = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001045 int bodyStartLine = 0;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001046 unsigned bodyStartColumn = 0;
1047 failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001048 failIfFalse(name);
1049 failIfFalseIfStrict(declareVariable(name));
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001050 return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001051}
1052
1053struct LabelInfo {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001054 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001055 : m_ident(ident)
1056 , m_start(start)
1057 , m_end(end)
1058 {
1059 }
1060
1061 const Identifier* m_ident;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001062 JSTextPosition m_start;
1063 JSTextPosition m_end;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001064};
1065
msaboff@apple.com831599f2011-11-08 22:49:27 +00001066template <typename LexerType>
1067template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001068{
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.com0d5fdb92013-07-24 00:41:46 +00001074 JSTokenLocation location;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001075 do {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001076 JSTextPosition start = tokenStartPosition();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001077 location = tokenLocation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001078 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.com3b256ca2013-07-30 17:01:40 +00001085 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001086 }
1087 const Identifier* ident = m_token.m_data.ident;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001088 JSTextPosition end = tokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001089 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.com3b256ca2013-07-30 17:01:40 +00001097 labels.append(LabelInfo(ident, start, end));
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001098 }
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.com3b256ca2013-07-30 17:01:40 +00001124 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001125 }
1126 return statement;
1127}
1128
msaboff@apple.com831599f2011-11-08 22:49:27 +00001129template <typename LexerType>
1130template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001131{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001132 JSTextPosition start = tokenStartPosition();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001133 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001134 TreeExpression expression = parseExpression(context);
1135 failIfFalse(expression);
1136 failIfFalse(autoSemiColon());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001137 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001138}
1139
msaboff@apple.com831599f2011-11-08 22:49:27 +00001140template <typename LexerType>
1141template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001142{
1143 ASSERT(match(IF));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001144 JSTokenLocation ifLocation(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001145 int start = tokenLine();
1146 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001147
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001148 consumeOrFail(OPENPAREN);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001149
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001150 TreeExpression condition = parseExpression(context);
1151 failIfFalse(condition);
1152 int end = tokenLine();
1153 consumeOrFail(CLOSEPAREN);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001154
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001155 const Identifier* unused = 0;
1156 TreeStatement trueBlock = parseStatement(context, unused);
1157 failIfFalse(trueBlock);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001158
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001159 if (!match(ELSE))
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001160 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001161
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001162 Vector<TreeExpression> exprStack;
andersca@apple.comc3523f82013-10-18 23:41:24 +00001163 Vector<pair<int, int>> posStack;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001164 Vector<JSTokenLocation> tokenLocationStack;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001165 Vector<TreeStatement> statementStack;
1166 bool trailingElse = false;
1167 do {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001168 JSTokenLocation tempLocation = tokenLocation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001169 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.org1b331cb2012-08-06 03:16:46 +00001180
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001181 consumeOrFail(OPENPAREN);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001182
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001183 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.org1b331cb2012-08-06 03:16:46 +00001189 failIfFalse(innerTrueBlock);
1190 tokenLocationStack.append(tempLocation);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001191 exprStack.append(innerCondition);
1192 posStack.append(make_pair(innerStart, innerEnd));
1193 statementStack.append(innerTrueBlock);
1194 } while (match(ELSE));
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001195
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001196 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.org1b331cb2012-08-06 03:16:46 +00001203 JSTokenLocation elseLocation = tokenLocationStack.last();
1204 tokenLocationStack.removeLast();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001205 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second));
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001206 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001207
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001208 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.org1b331cb2012-08-06 03:16:46 +00001217 JSTokenLocation elseLocation = tokenLocationStack.last();
1218 tokenLocationStack.removeLast();
1219 statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second));
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001220 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001221
1222 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001223}
1224
msaboff@apple.com831599f2011-11-08 22:49:27 +00001225template <typename LexerType>
1226template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001227{
1228 failIfStackOverflow();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001229 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001230 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.org1b331cb2012-08-06 03:16:46 +00001239 typename TreeBuilder::Comma commaNode = context.createCommaExpr(location, node, right);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001240 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.com831599f2011-11-08 22:49:27 +00001249template <typename LexerType>
1250template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001251{
1252 failIfStackOverflow();
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001253 JSTextPosition start = tokenStartPosition();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001254 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001255 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.com3b256ca2013-07-30 17:01:40 +00001284 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_assignmentCount, op);
1285 start = tokenStartPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001286 m_assignmentCount++;
1287 next(TreeBuilder::DontBuildStrings);
1288 if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001289 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.com2e5003e2011-10-31 22:13:01 +00001291 declareWrite(m_lastIdentifier);
1292 m_lastIdentifier = 0;
1293 }
oliver@apple.comd055db62013-10-02 19:11:04 +00001294 lhs = parseAssignmentExpression(context);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001295 failIfFalse(lhs);
1296 if (initialNonLHSCount != m_nonLHSCount)
1297 break;
1298 }
1299end:
1300 if (hadAssignment)
1301 m_nonLHSCount++;
1302
1303 if (!TreeBuilder::CreatesAST)
1304 return lhs;
1305
1306 while (assignmentStack)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001307 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001308
1309 return lhs;
1310}
1311
msaboff@apple.com831599f2011-11-08 22:49:27 +00001312template <typename LexerType>
1313template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001314{
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001315 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001316 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.org1b331cb2012-08-06 03:16:46 +00001328 return context.createConditionalExpr(location, cond, lhs, rhs);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001329}
1330
1331ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
1332{
1333 return token & UnaryOpTokenFlag;
1334}
1335
msaboff@apple.com831599f2011-11-08 22:49:27 +00001336template <typename LexerType>
1337int Parser<LexerType>::isBinaryOperator(JSTokenType token)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001338{
1339 if (m_allowsIn)
1340 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
1341 return token & BinaryOpTokenPrecedenceMask;
1342}
1343
msaboff@apple.com831599f2011-11-08 22:49:27 +00001344template <typename LexerType>
1345template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001346{
1347
1348 int operandStackDepth = 0;
1349 int operatorStackDepth = 0;
1350 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001351 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001352 while (true) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001353 JSTextPosition exprStart = tokenStartPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001354 int initialAssignments = m_assignmentCount;
1355 TreeExpression current = parseUnaryExpression(context);
1356 failIfFalse(current);
1357
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001358 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_assignmentCount);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001359 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.org1b331cb2012-08-06 03:16:46 +00001373 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001374 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.org1b331cb2012-08-06 03:16:46 +00001384 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001385 context.operatorStackPop(operatorStackDepth);
1386 }
1387 return context.popOperandStack(operandStackDepth);
1388}
1389
msaboff@apple.com831599f2011-11-08 22:49:27 +00001390template <typename LexerType>
1391template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001392{
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.com9a9a4b52013-04-18 19:32:17 +00001400 if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
msaboff@apple.com11c2e642011-11-07 17:54:15 +00001401 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001402 else
msaboff@apple.com11c2e642011-11-07 17:54:15 +00001403 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001404
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.com2e5003e2011-10-31 22:13:01 +00001412 const Identifier* accessorName = 0;
1413 TreeFormalParameterList parameters = 0;
1414 TreeFunctionBody body = 0;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001415 unsigned openBraceOffset = 0;
1416 unsigned closeBraceOffset = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001417 int bodyStartLine = 0;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001418 unsigned bodyStartColumn = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001419 PropertyNode::Type type;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001420 if (*ident == m_vm->propertyNames->get)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001421 type = PropertyNode::Getter;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001422 else if (*ident == m_vm->propertyNames->set)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001423 type = PropertyNode::Setter;
1424 else
1425 fail();
commit-queue@webkit.org54da5c22012-02-26 22:51:38 +00001426 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.org1b331cb2012-08-06 03:16:46 +00001434 JSTokenLocation location(tokenLocation());
commit-queue@webkit.org54da5c22012-02-26 22:51:38 +00001435 next();
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001436 failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
commit-queue@webkit.org54da5c22012-02-26 22:51:38 +00001437 if (stringPropertyName)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001438 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.com2e5003e2011-10-31 22:13:01 +00001440 }
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.com9a9a4b52013-04-18 19:32:17 +00001447 return context.template createProperty<complete>(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001448 }
1449 default:
1450 failIfFalse(m_token.m_type & KeywordTokenFlag);
1451 goto namedProperty;
1452 }
1453}
1454
msaboff@apple.com831599f2011-11-08 22:49:27 +00001455template <typename LexerType>
1456template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001457{
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001458 int startOffset = m_token.m_data.offset;
1459 unsigned oldLineStartOffset = m_lexer->currentLineStartOffset();
oliver@apple.comc800ee02012-02-02 21:19:53 +00001460 unsigned oldLastLineNumber = m_lexer->lastLineNumber();
1461 unsigned oldLineNumber = m_lexer->lineNumber();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001462 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001463 JSTokenLocation location(tokenLocation());
1464
oliver@apple.comf8ef1472012-04-05 00:56:54 +00001465 int oldNonLHSCount = m_nonLHSCount;
1466
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001467 if (match(CLOSEBRACE)) {
1468 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001469 return context.createObjectLiteral(location);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001470 }
1471
1472 TreeProperty property = parseProperty<false>(context);
1473 failIfFalse(property);
1474 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001475 m_lexer->setOffset(startOffset, oldLineStartOffset);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001476 next();
oliver@apple.comc800ee02012-02-02 21:19:53 +00001477 m_lexer->setLastLineNumber(oldLastLineNumber);
1478 m_lexer->setLineNumber(oldLineNumber);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001479 return parseStrictObjectLiteral(context);
1480 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001481 TreePropertyList propertyList = context.createPropertyList(location, property);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001482 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.org1b331cb2012-08-06 03:16:46 +00001488 JSTokenLocation propertyLocation(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001489 property = parseProperty<false>(context);
1490 failIfFalse(property);
1491 if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001492 m_lexer->setOffset(startOffset, oldLineStartOffset);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001493 next();
oliver@apple.comc800ee02012-02-02 21:19:53 +00001494 m_lexer->setLastLineNumber(oldLastLineNumber);
1495 m_lexer->setLineNumber(oldLineNumber);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001496 return parseStrictObjectLiteral(context);
1497 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001498 tail = context.createPropertyList(propertyLocation, property, tail);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001499 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001500
1501 location = tokenLocation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001502 consumeOrFail(CLOSEBRACE);
1503
oliver@apple.comf8ef1472012-04-05 00:56:54 +00001504 m_nonLHSCount = oldNonLHSCount;
1505
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001506 return context.createObjectLiteral(location, propertyList);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001507}
1508
msaboff@apple.com831599f2011-11-08 22:49:27 +00001509template <typename LexerType>
1510template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001511{
1512 consumeOrFail(OPENBRACE);
1513
oliver@apple.comf8ef1472012-04-05 00:56:54 +00001514 int oldNonLHSCount = m_nonLHSCount;
1515
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001516 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001517 if (match(CLOSEBRACE)) {
1518 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001519 return context.createObjectLiteral(location);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001520 }
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.org1b331cb2012-08-06 03:16:46 +00001531 TreePropertyList propertyList = context.createPropertyList(location, property);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001532 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.org1b331cb2012-08-06 03:16:46 +00001538 JSTokenLocation propertyLocation(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001539 property = parseProperty<true>(context);
1540 failIfFalse(property);
1541 if (!m_syntaxAlreadyValidated) {
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +00001542 ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property).impl(), context.getType(property));
1543 if (!propertyEntry.isNewEntry) {
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001544 failIfTrue(propertyEntry.iterator->value == PropertyNode::Constant);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001545 failIfTrue(context.getType(property) == PropertyNode::Constant);
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001546 failIfTrue(context.getType(property) & propertyEntry.iterator->value);
1547 propertyEntry.iterator->value |= context.getType(property);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001548 }
1549 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001550 tail = context.createPropertyList(propertyLocation, property, tail);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001551 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001552
1553 location = tokenLocation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001554 consumeOrFail(CLOSEBRACE);
oliver@apple.comf8ef1472012-04-05 00:56:54 +00001555
1556 m_nonLHSCount = oldNonLHSCount;
1557
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001558 return context.createObjectLiteral(location, propertyList);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001559}
1560
msaboff@apple.com831599f2011-11-08 22:49:27 +00001561template <typename LexerType>
1562template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001563{
1564 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings);
1565
oliver@apple.comf8ef1472012-04-05 00:56:54 +00001566 int oldNonLHSCount = m_nonLHSCount;
1567
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001568 int elisions = 0;
1569 while (match(COMMA)) {
1570 next(TreeBuilder::DontBuildStrings);
1571 elisions++;
1572 }
1573 if (match(CLOSEBRACKET)) {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001574 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001575 next(TreeBuilder::DontBuildStrings);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001576 return context.createArray(location, elisions);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001577 }
1578
oliver@apple.com72f8a822013-10-17 01:02:34 +00001579 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.com2e5003e2011-10-31 22:13:01 +00001590 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.org1b331cb2012-08-06 03:16:46 +00001604 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001605 next(TreeBuilder::DontBuildStrings);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001606 return context.createArray(location, elisions, elementList);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001607 }
oliver@apple.com72f8a822013-10-17 01:02:34 +00001608 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.com2e5003e2011-10-31 22:13:01 +00001619 TreeExpression elem = parseAssignmentExpression(context);
1620 failIfFalse(elem);
1621 tail = context.createElementList(tail, elisions, elem);
1622 }
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001623
1624 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001625 consumeOrFail(CLOSEBRACKET);
1626
oliver@apple.comf8ef1472012-04-05 00:56:54 +00001627 m_nonLHSCount = oldNonLHSCount;
1628
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001629 return context.createArray(location, elementList);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001630}
1631
msaboff@apple.com831599f2011-11-08 22:49:27 +00001632template <typename LexerType>
1633template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001634{
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.org1b331cb2012-08-06 03:16:46 +00001653 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001654 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001655 return context.thisExpr(location);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001656 }
1657 case IDENT: {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001658 JSTextPosition start = tokenStartPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001659 const Identifier* ident = m_token.m_data.ident;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001660 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001661 next();
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001662 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001663 m_lastIdentifier = ident;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001664 return context.createResolve(location, ident, start);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001665 }
1666 case STRING: {
1667 const Identifier* ident = m_token.m_data.ident;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001668 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001669 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001670 return context.createString(location, ident);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001671 }
1672 case NUMBER: {
1673 double d = m_token.m_data.doubleValue;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001674 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001675 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001676 return context.createNumberExpr(location, d);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001677 }
1678 case NULLTOKEN: {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001679 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001680 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001681 return context.createNull(location);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001682 }
1683 case TRUETOKEN: {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001684 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001685 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001686 return context.createBoolean(location, true);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001687 }
1688 case FALSETOKEN: {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001689 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001690 next();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001691 return context.createBoolean(location, false);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001692 }
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.com3b256ca2013-07-30 17:01:40 +00001703 JSTextPosition start = tokenStartPosition();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001704 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001705 next();
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001706 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001707 if (!re) {
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00001708 const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001709 failWithMessage(yarrErrorMsg);
1710 }
1711 return re;
1712 }
1713 default:
1714 fail();
1715 }
1716}
1717
msaboff@apple.com831599f2011-11-08 22:49:27 +00001718template <typename LexerType>
oliver@apple.com72f8a822013-10-17 01:02:34 +00001719template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context, SpreadMode mode)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001720{
1721 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001722 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001723 if (match(CLOSEPAREN)) {
1724 next(TreeBuilder::DontBuildStrings);
1725 return context.createArguments();
1726 }
oliver@apple.com72f8a822013-10-17 01:02:34 +00001727 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.com2e5003e2011-10-31 22:13:01 +00001741 TreeExpression firstArg = parseAssignmentExpression(context);
1742 failIfFalse(firstArg);
1743
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001744 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001745 TreeArgumentsList tail = argList;
1746 while (match(COMMA)) {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001747 JSTokenLocation argumentLocation(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001748 next(TreeBuilder::DontBuildStrings);
1749 TreeExpression arg = parseAssignmentExpression(context);
1750 failIfFalse(arg);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001751 tail = context.createArgumentsList(argumentLocation, tail, arg);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001752 }
1753 consumeOrFail(CLOSEPAREN);
1754 return context.createArguments(argList);
1755}
1756
msaboff@apple.com831599f2011-11-08 22:49:27 +00001757template <typename LexerType>
1758template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001759{
1760 TreeExpression base = 0;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001761 JSTextPosition expressionStart = tokenStartPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001762 int newCount = 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +00001763 JSTokenLocation location;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001764 while (match(NEW)) {
1765 next();
1766 newCount++;
1767 }
1768
1769 if (match(FUNCTION)) {
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001770 const Identifier* name = &m_vm->propertyNames->nullIdentifier;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001771 TreeFormalParameterList parameters = 0;
1772 TreeFunctionBody body = 0;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001773 unsigned openBraceOffset = 0;
1774 unsigned closeBraceOffset = 0;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001775 int bodyStartLine = 0;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001776 unsigned bodyStartColumn = 0;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001777 location = tokenLocation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001778 next();
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001779 failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)));
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001780 base = context.createFunctionExpr(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001781 } else
1782 base = parsePrimaryExpression(context);
1783
1784 failIfFalse(base);
1785 while (true) {
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001786 location = tokenLocation();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001787 switch (m_token.m_type) {
1788 case OPENBRACKET: {
1789 m_nonTrivialExpressionCount++;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001790 JSTextPosition expressionEnd = lastTokenEndPosition();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001791 next();
1792 int nonLHSCount = m_nonLHSCount;
1793 int initialAssignments = m_assignmentCount;
1794 TreeExpression property = parseExpression(context);
1795 failIfFalse(property);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001796 base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001797 consumeOrFail(CLOSEBRACKET);
1798 m_nonLHSCount = nonLHSCount;
1799 break;
1800 }
1801 case OPENPAREN: {
1802 m_nonTrivialExpressionCount++;
oliver@apple.com2ea1fd12012-01-30 23:59:20 +00001803 int nonLHSCount = m_nonLHSCount;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001804 if (newCount) {
1805 newCount--;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001806 JSTextPosition expressionEnd = lastTokenEndPosition();
oliver@apple.com72f8a822013-10-17 01:02:34 +00001807 TreeArguments arguments = parseArguments(context, DontAllowSpread);
oliver@apple.com2ea1fd12012-01-30 23:59:20 +00001808 failIfFalse(arguments);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001809 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001810 } else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001811 JSTextPosition expressionEnd = lastTokenEndPosition();
oliver@apple.com72f8a822013-10-17 01:02:34 +00001812 TreeArguments arguments = parseArguments(context, AllowSpread);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001813 failIfFalse(arguments);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001814 base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001815 }
oliver@apple.com2ea1fd12012-01-30 23:59:20 +00001816 m_nonLHSCount = nonLHSCount;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001817 break;
1818 }
1819 case DOT: {
1820 m_nonTrivialExpressionCount++;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001821 JSTextPosition expressionEnd = lastTokenEndPosition();
msaboff@apple.com11c2e642011-11-07 17:54:15 +00001822 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001823 matchOrFail(IDENT);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001824 base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001825 next();
1826 break;
1827 }
1828 default:
1829 goto endMemberExpression;
1830 }
1831 }
1832endMemberExpression:
1833 while (newCount--)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001834 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001835 return base;
1836}
1837
msaboff@apple.com831599f2011-11-08 22:49:27 +00001838template <typename LexerType>
1839template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001840{
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.com3b256ca2013-07-30 17:01:40 +00001867 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001868 next();
1869 m_nonTrivialExpressionCount++;
1870 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001871 JSTextPosition subExprStart = tokenStartPosition();
1872 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001873 JSTokenLocation location(tokenLocation());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001874 TreeExpression expr = parseMemberExpression(context);
1875 failIfFalse(expr);
1876 bool isEvalOrArguments = false;
1877 if (strictMode() && !m_syntaxAlreadyValidated) {
1878 if (context.isResolve(expr))
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001879 isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments;
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001880 }
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.com3b256ca2013-07-30 17:01:40 +00001886 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001887 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.com3b256ca2013-07-30 17:01:40 +00001895 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001896 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.com3b256ca2013-07-30 17:01:40 +00001905 JSTextPosition end = lastTokenEndPosition();
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001906
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001907 if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
1908 return expr;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001909
1910 location = tokenLocation();
1911 location.line = m_lexer->lastLineNumber();
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001912 while (tokenStackDepth) {
1913 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
1914 case EXCLAMATION:
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001915 expr = context.createLogicalNot(location, expr);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001916 break;
1917 case TILDE:
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001918 expr = context.makeBitwiseNotNode(location, expr);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001919 break;
1920 case MINUS:
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001921 expr = context.makeNegateNode(location, expr);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001922 break;
1923 case PLUS:
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001924 expr = context.createUnaryPlus(location, expr);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001925 break;
1926 case PLUSPLUS:
1927 case AUTOPLUSPLUS:
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001928 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001929 m_assignmentCount++;
1930 break;
1931 case MINUSMINUS:
1932 case AUTOMINUSMINUS:
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001933 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001934 m_assignmentCount++;
1935 break;
1936 case TYPEOF:
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001937 expr = context.makeTypeOfNode(location, expr);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001938 break;
1939 case VOIDTOKEN:
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001940 expr = context.createVoid(location, expr);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001941 break;
1942 case DELETETOKEN:
1943 failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode");
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001944 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
msaboff@apple.com2e5003e2011-10-31 22:13:01 +00001945 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.com831599f2011-11-08 22:49:27 +00001956// Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
andersca@apple.comc3523f82013-10-18 23:41:24 +00001957template class Parser<Lexer<LChar>>;
1958template class Parser<Lexer<UChar>>;
msaboff@apple.com831599f2011-11-08 22:49:27 +00001959
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +00001960} // namespace JSC