]> git.saurik.com Git - apple/javascriptcore.git/blob - parser/Parser.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / parser / Parser.h
1 /*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifndef Parser_h
24 #define Parser_h
25
26 #include "Debugger.h"
27 #include "ExceptionHelpers.h"
28 #include "Executable.h"
29 #include "JSGlobalObject.h"
30 #include "Lexer.h"
31 #include "Nodes.h"
32 #include "ParserArena.h"
33 #include "ParserError.h"
34 #include "ParserTokens.h"
35 #include "SourceProvider.h"
36 #include "SourceProviderCache.h"
37 #include "SourceProviderCacheItem.h"
38 #include <wtf/Forward.h>
39 #include <wtf/Noncopyable.h>
40 #include <wtf/OwnPtr.h>
41 #include <wtf/RefPtr.h>
42 namespace JSC {
43 struct Scope;
44 }
45
46 namespace WTF {
47 template <> struct VectorTraits<JSC::Scope> : SimpleClassVectorTraits {
48 static const bool canInitializeWithMemset = false; // Not all Scope data members initialize to 0.
49 };
50 }
51
52 namespace JSC {
53
54 class ExecState;
55 class FunctionBodyNode;
56 class FunctionParameters;
57 class Identifier;
58 class VM;
59 class ProgramNode;
60 class SourceCode;
61
62 // Macros to make the more common TreeBuilder types a little less verbose
63 #define TreeStatement typename TreeBuilder::Statement
64 #define TreeExpression typename TreeBuilder::Expression
65 #define TreeFormalParameterList typename TreeBuilder::FormalParameterList
66 #define TreeSourceElements typename TreeBuilder::SourceElements
67 #define TreeClause typename TreeBuilder::Clause
68 #define TreeClauseList typename TreeBuilder::ClauseList
69 #define TreeConstDeclList typename TreeBuilder::ConstDeclList
70 #define TreeArguments typename TreeBuilder::Arguments
71 #define TreeArgumentsList typename TreeBuilder::ArgumentsList
72 #define TreeFunctionBody typename TreeBuilder::FunctionBody
73 #define TreeProperty typename TreeBuilder::Property
74 #define TreePropertyList typename TreeBuilder::PropertyList
75 #define TreeDeconstructionPattern typename TreeBuilder::DeconstructionPattern
76
77 COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
78
79 enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
80 enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
81 enum FunctionParseMode { FunctionMode, GetterMode, SetterMode };
82 enum DeconstructionKind {
83 DeconstructToVariables,
84 DeconstructToParameters,
85 DeconstructToExpressions
86 };
87
88 template <typename T> inline bool isEvalNode() { return false; }
89 template <> inline bool isEvalNode<EvalNode>() { return true; }
90
91 struct ScopeLabelInfo {
92 ScopeLabelInfo(StringImpl* ident, bool isLoop)
93 : m_ident(ident)
94 , m_isLoop(isLoop)
95 {
96 }
97
98 StringImpl* m_ident;
99 bool m_isLoop;
100 };
101
102 struct Scope {
103 Scope(const VM* vm, bool isFunction, bool strictMode)
104 : m_vm(vm)
105 , m_shadowsArguments(false)
106 , m_usesEval(false)
107 , m_needsFullActivation(false)
108 , m_allowsNewDecls(true)
109 , m_strictMode(strictMode)
110 , m_isFunction(isFunction)
111 , m_isFunctionBoundary(false)
112 , m_isValidStrictMode(true)
113 , m_loopDepth(0)
114 , m_switchDepth(0)
115 {
116 }
117
118 Scope(const Scope& rhs)
119 : m_vm(rhs.m_vm)
120 , m_shadowsArguments(rhs.m_shadowsArguments)
121 , m_usesEval(rhs.m_usesEval)
122 , m_needsFullActivation(rhs.m_needsFullActivation)
123 , m_allowsNewDecls(rhs.m_allowsNewDecls)
124 , m_strictMode(rhs.m_strictMode)
125 , m_isFunction(rhs.m_isFunction)
126 , m_isFunctionBoundary(rhs.m_isFunctionBoundary)
127 , m_isValidStrictMode(rhs.m_isValidStrictMode)
128 , m_loopDepth(rhs.m_loopDepth)
129 , m_switchDepth(rhs.m_switchDepth)
130 {
131 if (rhs.m_labels) {
132 m_labels = adoptPtr(new LabelStack);
133
134 typedef LabelStack::const_iterator iterator;
135 iterator end = rhs.m_labels->end();
136 for (iterator it = rhs.m_labels->begin(); it != end; ++it)
137 m_labels->append(ScopeLabelInfo(it->m_ident, it->m_isLoop));
138 }
139 }
140
141 void startSwitch() { m_switchDepth++; }
142 void endSwitch() { m_switchDepth--; }
143 void startLoop() { m_loopDepth++; }
144 void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; }
145 bool inLoop() { return !!m_loopDepth; }
146 bool breakIsValid() { return m_loopDepth || m_switchDepth; }
147 bool continueIsValid() { return m_loopDepth; }
148
149 void pushLabel(const Identifier* label, bool isLoop)
150 {
151 if (!m_labels)
152 m_labels = adoptPtr(new LabelStack);
153 m_labels->append(ScopeLabelInfo(label->impl(), isLoop));
154 }
155
156 void popLabel()
157 {
158 ASSERT(m_labels);
159 ASSERT(m_labels->size());
160 m_labels->removeLast();
161 }
162
163 ScopeLabelInfo* getLabel(const Identifier* label)
164 {
165 if (!m_labels)
166 return 0;
167 for (int i = m_labels->size(); i > 0; i--) {
168 if (m_labels->at(i - 1).m_ident == label->impl())
169 return &m_labels->at(i - 1);
170 }
171 return 0;
172 }
173
174 void setIsFunction()
175 {
176 m_isFunction = true;
177 m_isFunctionBoundary = true;
178 }
179 bool isFunction() { return m_isFunction; }
180 bool isFunctionBoundary() { return m_isFunctionBoundary; }
181
182 void declareCallee(const Identifier* ident)
183 {
184 m_declaredVariables.add(ident->string().impl());
185 }
186
187 bool declareVariable(const Identifier* ident)
188 {
189 bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident;
190 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
191 m_declaredVariables.add(ident->string().impl());
192 return isValidStrictMode;
193 }
194
195 bool hasDeclaredVariable(const Identifier& ident)
196 {
197 return m_declaredVariables.contains(ident.impl());
198 }
199
200 bool hasDeclaredParameter(const Identifier& ident)
201 {
202 return m_declaredParameters.contains(ident.impl()) || m_declaredVariables.contains(ident.impl());
203 }
204
205 void declareWrite(const Identifier* ident)
206 {
207 ASSERT(m_strictMode);
208 m_writtenVariables.add(ident->impl());
209 }
210
211 void preventNewDecls() { m_allowsNewDecls = false; }
212 bool allowsNewDecls() const { return m_allowsNewDecls; }
213
214 bool declareParameter(const Identifier* ident)
215 {
216 bool isArguments = m_vm->propertyNames->arguments == *ident;
217 bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments;
218 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
219 m_declaredParameters.add(ident->string().impl());
220
221 if (isArguments)
222 m_shadowsArguments = true;
223 return isValidStrictMode;
224 }
225
226 enum BindingResult {
227 BindingFailed,
228 StrictBindingFailed,
229 BindingSucceeded
230 };
231 BindingResult declareBoundParameter(const Identifier* ident)
232 {
233 bool isArguments = m_vm->propertyNames->arguments == *ident;
234 bool newEntry = m_declaredVariables.add(ident->string().impl()).isNewEntry;
235 bool isValidStrictMode = newEntry && m_vm->propertyNames->eval != *ident && !isArguments;
236 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
237
238 if (isArguments)
239 m_shadowsArguments = true;
240 if (!newEntry)
241 return BindingFailed;
242 return isValidStrictMode ? BindingSucceeded : StrictBindingFailed;
243 }
244
245 void getUsedVariables(IdentifierSet& usedVariables)
246 {
247 usedVariables.swap(m_usedVariables);
248 }
249
250 void useVariable(const Identifier* ident, bool isEval)
251 {
252 m_usesEval |= isEval;
253 m_usedVariables.add(ident->string().impl());
254 }
255
256 void setNeedsFullActivation() { m_needsFullActivation = true; }
257
258 bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
259 {
260 if (nestedScope->m_usesEval)
261 m_usesEval = true;
262 IdentifierSet::iterator end = nestedScope->m_usedVariables.end();
263 for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) {
264 if (nestedScope->m_declaredVariables.contains(*ptr))
265 continue;
266 m_usedVariables.add(*ptr);
267 if (shouldTrackClosedVariables)
268 m_closedVariables.add(*ptr);
269 }
270 if (nestedScope->m_writtenVariables.size()) {
271 IdentifierSet::iterator end = nestedScope->m_writtenVariables.end();
272 for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) {
273 if (nestedScope->m_declaredVariables.contains(*ptr))
274 continue;
275 m_writtenVariables.add(*ptr);
276 }
277 }
278
279 return true;
280 }
281
282 void getCapturedVariables(IdentifierSet& capturedVariables, bool& modifiedParameter)
283 {
284 if (m_needsFullActivation || m_usesEval) {
285 modifiedParameter = true;
286 capturedVariables.swap(m_declaredVariables);
287 return;
288 }
289 for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) {
290 if (!m_declaredVariables.contains(*ptr))
291 continue;
292 capturedVariables.add(*ptr);
293 }
294 modifiedParameter = false;
295 if (m_declaredParameters.size()) {
296 IdentifierSet::iterator end = m_writtenVariables.end();
297 for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
298 if (!m_declaredParameters.contains(*ptr))
299 continue;
300 modifiedParameter = true;
301 break;
302 }
303 }
304 }
305 void setStrictMode() { m_strictMode = true; }
306 bool strictMode() const { return m_strictMode; }
307 bool isValidStrictMode() const { return m_isValidStrictMode; }
308 bool shadowsArguments() const { return m_shadowsArguments; }
309
310 void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl>>& vector)
311 {
312 IdentifierSet::iterator end = capturedVariables.end();
313 for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) {
314 if (m_declaredVariables.contains(*it))
315 continue;
316 vector.append(*it);
317 }
318 }
319
320 void fillParametersForSourceProviderCache(SourceProviderCacheItemCreationParameters& parameters)
321 {
322 ASSERT(m_isFunction);
323 parameters.usesEval = m_usesEval;
324 parameters.strictMode = m_strictMode;
325 parameters.needsFullActivation = m_needsFullActivation;
326 copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables);
327 copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables);
328 }
329
330 void restoreFromSourceProviderCache(const SourceProviderCacheItem* info)
331 {
332 ASSERT(m_isFunction);
333 m_usesEval = info->usesEval;
334 m_strictMode = info->strictMode;
335 m_needsFullActivation = info->needsFullActivation;
336 for (unsigned i = 0; i < info->usedVariablesCount; ++i)
337 m_usedVariables.add(info->usedVariables()[i]);
338 for (unsigned i = 0; i < info->writtenVariablesCount; ++i)
339 m_writtenVariables.add(info->writtenVariables()[i]);
340 }
341
342 private:
343 const VM* m_vm;
344 bool m_shadowsArguments : 1;
345 bool m_usesEval : 1;
346 bool m_needsFullActivation : 1;
347 bool m_allowsNewDecls : 1;
348 bool m_strictMode : 1;
349 bool m_isFunction : 1;
350 bool m_isFunctionBoundary : 1;
351 bool m_isValidStrictMode : 1;
352 int m_loopDepth;
353 int m_switchDepth;
354
355 typedef Vector<ScopeLabelInfo, 2> LabelStack;
356 OwnPtr<LabelStack> m_labels;
357 IdentifierSet m_declaredParameters;
358 IdentifierSet m_declaredVariables;
359 IdentifierSet m_usedVariables;
360 IdentifierSet m_closedVariables;
361 IdentifierSet m_writtenVariables;
362 };
363
364 typedef Vector<Scope, 10> ScopeStack;
365
366 struct ScopeRef {
367 ScopeRef(ScopeStack* scopeStack, unsigned index)
368 : m_scopeStack(scopeStack)
369 , m_index(index)
370 {
371 }
372 Scope* operator->() { return &m_scopeStack->at(m_index); }
373 unsigned index() const { return m_index; }
374
375 bool hasContainingScope()
376 {
377 return m_index && !m_scopeStack->at(m_index).isFunctionBoundary();
378 }
379
380 ScopeRef containingScope()
381 {
382 ASSERT(hasContainingScope());
383 return ScopeRef(m_scopeStack, m_index - 1);
384 }
385
386 private:
387 ScopeStack* m_scopeStack;
388 unsigned m_index;
389 };
390
391 template <typename LexerType>
392 class Parser {
393 WTF_MAKE_NONCOPYABLE(Parser);
394 WTF_MAKE_FAST_ALLOCATED;
395
396 public:
397 Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode);
398 ~Parser();
399
400 template <class ParsedNode>
401 PassRefPtr<ParsedNode> parse(ParserError&, bool needReparsingAdjustment);
402
403 JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
404 Vector<RefPtr<StringImpl>>&& closedVariables() { return WTF::move(m_closedVariables); }
405
406 private:
407 struct AllowInOverride {
408 AllowInOverride(Parser* parser)
409 : m_parser(parser)
410 , m_oldAllowsIn(parser->m_allowsIn)
411 {
412 parser->m_allowsIn = true;
413 }
414 ~AllowInOverride()
415 {
416 m_parser->m_allowsIn = m_oldAllowsIn;
417 }
418 Parser* m_parser;
419 bool m_oldAllowsIn;
420 };
421
422 struct AutoPopScopeRef : public ScopeRef {
423 AutoPopScopeRef(Parser* parser, ScopeRef scope)
424 : ScopeRef(scope)
425 , m_parser(parser)
426 {
427 }
428
429 ~AutoPopScopeRef()
430 {
431 if (m_parser)
432 m_parser->popScope(*this, false);
433 }
434
435 void setPopped()
436 {
437 m_parser = 0;
438 }
439
440 private:
441 Parser* m_parser;
442 };
443
444 ScopeRef currentScope()
445 {
446 return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1);
447 }
448
449 ScopeRef pushScope()
450 {
451 bool isFunction = false;
452 bool isStrict = false;
453 if (!m_scopeStack.isEmpty()) {
454 isStrict = m_scopeStack.last().strictMode();
455 isFunction = m_scopeStack.last().isFunction();
456 }
457 m_scopeStack.append(Scope(m_vm, isFunction, isStrict));
458 return currentScope();
459 }
460
461 bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
462 {
463 ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
464 ASSERT(m_scopeStack.size() > 1);
465 bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
466 m_scopeStack.removeLast();
467 return result;
468 }
469
470 bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
471 {
472 return popScopeInternal(scope, shouldTrackClosedVariables);
473 }
474
475 bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
476 {
477 scope.setPopped();
478 return popScopeInternal(scope, shouldTrackClosedVariables);
479 }
480
481 bool declareVariable(const Identifier* ident)
482 {
483 unsigned i = m_scopeStack.size() - 1;
484 ASSERT(i < m_scopeStack.size());
485 while (!m_scopeStack[i].allowsNewDecls()) {
486 i--;
487 ASSERT(i < m_scopeStack.size());
488 }
489 return m_scopeStack[i].declareVariable(ident);
490 }
491
492 NEVER_INLINE bool hasDeclaredVariable(const Identifier& ident)
493 {
494 unsigned i = m_scopeStack.size() - 1;
495 ASSERT(i < m_scopeStack.size());
496 while (!m_scopeStack[i].allowsNewDecls()) {
497 i--;
498 ASSERT(i < m_scopeStack.size());
499 }
500 return m_scopeStack[i].hasDeclaredVariable(ident);
501 }
502
503 NEVER_INLINE bool hasDeclaredParameter(const Identifier& ident)
504 {
505 unsigned i = m_scopeStack.size() - 1;
506 ASSERT(i < m_scopeStack.size());
507 while (!m_scopeStack[i].allowsNewDecls()) {
508 i--;
509 ASSERT(i < m_scopeStack.size());
510 }
511 return m_scopeStack[i].hasDeclaredParameter(ident);
512 }
513
514 void declareWrite(const Identifier* ident)
515 {
516 if (!m_syntaxAlreadyValidated || strictMode())
517 m_scopeStack.last().declareWrite(ident);
518 }
519
520 ScopeStack m_scopeStack;
521
522 const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos)
523 {
524 return m_functionCache ? m_functionCache->get(openBracePos) : 0;
525 }
526
527 Parser();
528 String parseInner();
529
530 void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*,
531 ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&, const Vector<RefPtr<StringImpl>>&&);
532
533 // Used to determine type of error to report.
534 bool isFunctionBodyNode(ScopeNode*) { return false; }
535 bool isFunctionBodyNode(FunctionBodyNode*) { return true; }
536
537 ALWAYS_INLINE void next(unsigned lexerFlags = 0)
538 {
539 int lastLine = m_token.m_location.line;
540 int lastTokenEnd = m_token.m_location.endOffset;
541 int lastTokenLineStart = m_token.m_location.lineStartOffset;
542 m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart);
543 m_lexer->setLastLineNumber(lastLine);
544 m_token.m_type = m_lexer->lex(&m_token, lexerFlags, strictMode());
545 }
546
547 ALWAYS_INLINE void nextExpectIdentifier(unsigned lexerFlags = 0)
548 {
549 int lastLine = m_token.m_location.line;
550 int lastTokenEnd = m_token.m_location.endOffset;
551 int lastTokenLineStart = m_token.m_location.lineStartOffset;
552 m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart);
553 m_lexer->setLastLineNumber(lastLine);
554 m_token.m_type = m_lexer->lexExpectIdentifier(&m_token, lexerFlags, strictMode());
555 }
556
557 ALWAYS_INLINE bool nextTokenIsColon()
558 {
559 return m_lexer->nextTokenIsColon();
560 }
561
562 ALWAYS_INLINE bool consume(JSTokenType expected, unsigned flags = 0)
563 {
564 bool result = m_token.m_type == expected;
565 if (result)
566 next(flags);
567 return result;
568 }
569
570 void printUnexpectedTokenText(WTF::PrintStream&);
571 ALWAYS_INLINE String getToken() {
572 SourceProvider* sourceProvider = m_source->provider();
573 return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset);
574 }
575
576 ALWAYS_INLINE bool match(JSTokenType expected)
577 {
578 return m_token.m_type == expected;
579 }
580
581 ALWAYS_INLINE bool isofToken()
582 {
583 return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of;
584 }
585
586 ALWAYS_INLINE unsigned tokenStart()
587 {
588 return m_token.m_location.startOffset;
589 }
590
591 ALWAYS_INLINE const JSTextPosition& tokenStartPosition()
592 {
593 return m_token.m_startPosition;
594 }
595
596 ALWAYS_INLINE int tokenLine()
597 {
598 return m_token.m_location.line;
599 }
600
601 ALWAYS_INLINE int tokenColumn()
602 {
603 return tokenStart() - tokenLineStart();
604 }
605
606 ALWAYS_INLINE const JSTextPosition& tokenEndPosition()
607 {
608 return m_token.m_endPosition;
609 }
610
611 ALWAYS_INLINE unsigned tokenLineStart()
612 {
613 return m_token.m_location.lineStartOffset;
614 }
615
616 ALWAYS_INLINE const JSTokenLocation& tokenLocation()
617 {
618 return m_token.m_location;
619 }
620
621 void setErrorMessage(String msg)
622 {
623 m_errorMessage = msg;
624 }
625
626 NEVER_INLINE void logError(bool);
627 template <typename A> NEVER_INLINE void logError(bool, const A&);
628 template <typename A, typename B> NEVER_INLINE void logError(bool, const A&, const B&);
629 template <typename A, typename B, typename C> NEVER_INLINE void logError(bool, const A&, const B&, const C&);
630 template <typename A, typename B, typename C, typename D> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&);
631 template <typename A, typename B, typename C, typename D, typename E> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&);
632 template <typename A, typename B, typename C, typename D, typename E, typename F> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&);
633 template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&, const G&);
634
635 NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, String name, const char* afterMsg)
636 {
637 m_errorMessage = makeString(beforeMsg, " '", name, "' ", afterMsg);
638 }
639
640 NEVER_INLINE void updateErrorMessage(const char* msg)
641 {
642 ASSERT(msg);
643 m_errorMessage = String(msg);
644 ASSERT(!m_errorMessage.isNull());
645 }
646
647 void startLoop() { currentScope()->startLoop(); }
648 void endLoop() { currentScope()->endLoop(); }
649 void startSwitch() { currentScope()->startSwitch(); }
650 void endSwitch() { currentScope()->endSwitch(); }
651 void setStrictMode() { currentScope()->setStrictMode(); }
652 bool strictMode() { return currentScope()->strictMode(); }
653 bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
654 bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
655 Scope::BindingResult declareBoundParameter(const Identifier* ident) { return currentScope()->declareBoundParameter(ident); }
656 bool breakIsValid()
657 {
658 ScopeRef current = currentScope();
659 while (!current->breakIsValid()) {
660 if (!current.hasContainingScope())
661 return false;
662 current = current.containingScope();
663 }
664 return true;
665 }
666 bool continueIsValid()
667 {
668 ScopeRef current = currentScope();
669 while (!current->continueIsValid()) {
670 if (!current.hasContainingScope())
671 return false;
672 current = current.containingScope();
673 }
674 return true;
675 }
676 void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); }
677 void popLabel() { currentScope()->popLabel(); }
678 ScopeLabelInfo* getLabel(const Identifier* label)
679 {
680 ScopeRef current = currentScope();
681 ScopeLabelInfo* result = 0;
682 while (!(result = current->getLabel(label))) {
683 if (!current.hasContainingScope())
684 return 0;
685 current = current.containingScope();
686 }
687 return result;
688 }
689
690 template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode);
691 template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
692 template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
693 template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
694 template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
695 template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
696 template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
697 template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
698 template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
699 template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
700 template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
701 template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
702 template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
703 template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
704 template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
705 template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
706 template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
707 template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
708 template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
709 template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
710 template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
711 template <class TreeBuilder> TreeStatement parseBlockStatement(TreeBuilder&);
712 template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
713 template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
714 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
715 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
716 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
717 template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
718 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
719 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
720 template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
721 template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
722 enum SpreadMode { AllowSpread, DontAllowSpread };
723 template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode);
724 template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
725 template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
726 template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
727 template <class TreeBuilder> TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd);
728 template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&);
729
730 template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth);
731 template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0);
732 template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&);
733 template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn);
734 ALWAYS_INLINE int isBinaryOperator(JSTokenType);
735 bool allowAutomaticSemicolon();
736
737 bool autoSemiColon()
738 {
739 if (m_token.m_type == SEMICOLON) {
740 next();
741 return true;
742 }
743 return allowAutomaticSemicolon();
744 }
745
746 bool canRecurse()
747 {
748 return m_vm->isSafeToRecurse();
749 }
750
751 const JSTextPosition& lastTokenEndPosition() const
752 {
753 return m_lastTokenEndPosition;
754 }
755
756 bool hasError() const
757 {
758 return !m_errorMessage.isNull();
759 }
760
761 struct SavePoint {
762 int startOffset;
763 unsigned oldLineStartOffset;
764 unsigned oldLastLineNumber;
765 unsigned oldLineNumber;
766 };
767
768 ALWAYS_INLINE SavePoint createSavePoint()
769 {
770 ASSERT(!hasError());
771 SavePoint result;
772 result.startOffset = m_token.m_location.startOffset;
773 result.oldLineStartOffset = m_token.m_location.lineStartOffset;
774 result.oldLastLineNumber = m_lexer->lastLineNumber();
775 result.oldLineNumber = m_lexer->lineNumber();
776 return result;
777 }
778
779 ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint)
780 {
781 m_errorMessage = String();
782 m_lexer->setOffset(savePoint.startOffset, savePoint.oldLineStartOffset);
783 next();
784 m_lexer->setLastLineNumber(savePoint.oldLastLineNumber);
785 m_lexer->setLineNumber(savePoint.oldLineNumber);
786 }
787
788 struct ParserState {
789 int assignmentCount;
790 int nonLHSCount;
791 int nonTrivialExpressionCount;
792 };
793
794 ALWAYS_INLINE ParserState saveState()
795 {
796 ParserState result;
797 result.assignmentCount = m_assignmentCount;
798 result.nonLHSCount = m_nonLHSCount;
799 result.nonTrivialExpressionCount = m_nonTrivialExpressionCount;
800 return result;
801 }
802
803 ALWAYS_INLINE void restoreState(const ParserState& state)
804 {
805 m_assignmentCount = state.assignmentCount;
806 m_nonLHSCount = state.nonLHSCount;
807 m_nonTrivialExpressionCount = state.nonTrivialExpressionCount;
808
809 }
810
811
812 VM* m_vm;
813 const SourceCode* m_source;
814 ParserArena* m_arena;
815 OwnPtr<LexerType> m_lexer;
816
817 bool m_hasStackOverflow;
818 String m_errorMessage;
819 JSToken m_token;
820 bool m_allowsIn;
821 JSTextPosition m_lastTokenEndPosition;
822 int m_assignmentCount;
823 int m_nonLHSCount;
824 bool m_syntaxAlreadyValidated;
825 int m_statementDepth;
826 int m_nonTrivialExpressionCount;
827 const Identifier* m_lastIdentifier;
828 const Identifier* m_lastFunctionName;
829 RefPtr<SourceProviderCache> m_functionCache;
830 SourceElements* m_sourceElements;
831 bool m_parsingBuiltin;
832 ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
833 ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
834 IdentifierSet m_capturedVariables;
835 Vector<RefPtr<StringImpl>> m_closedVariables;
836 CodeFeatures m_features;
837 int m_numConstants;
838
839 struct DepthManager {
840 DepthManager(int* depth)
841 : m_originalDepth(*depth)
842 , m_depth(depth)
843 {
844 }
845
846 ~DepthManager()
847 {
848 *m_depth = m_originalDepth;
849 }
850
851 private:
852 int m_originalDepth;
853 int* m_depth;
854 };
855 };
856
857
858 template <typename LexerType>
859 template <class ParsedNode>
860 PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error, bool needReparsingAdjustment)
861 {
862 int errLine;
863 String errMsg;
864
865 if (ParsedNode::scopeIsFunction && needReparsingAdjustment)
866 m_lexer->setIsReparsing();
867
868 m_sourceElements = 0;
869
870 errLine = -1;
871 errMsg = String();
872
873 JSTokenLocation startLocation(tokenLocation());
874 ASSERT(m_source->startColumn() > 0);
875 unsigned startColumn = m_source->startColumn() - 1;
876
877 String parseError = parseInner();
878
879 int lineNumber = m_lexer->lineNumber();
880 bool lexError = m_lexer->sawError();
881 String lexErrorMessage = lexError ? m_lexer->getErrorMessage() : String();
882 ASSERT(lexErrorMessage.isNull() != lexError);
883 m_lexer->clear();
884
885 if (!parseError.isNull() || lexError) {
886 errLine = lineNumber;
887 errMsg = !lexErrorMessage.isNull() ? lexErrorMessage : parseError;
888 m_sourceElements = 0;
889 }
890
891 RefPtr<ParsedNode> result;
892 if (m_sourceElements) {
893 JSTokenLocation endLocation;
894 endLocation.line = m_lexer->lineNumber();
895 endLocation.lineStartOffset = m_lexer->currentLineStartOffset();
896 endLocation.startOffset = m_lexer->currentOffset();
897 unsigned endColumn = endLocation.startOffset - endLocation.lineStartOffset;
898 result = ParsedNode::create(m_vm,
899 startLocation,
900 endLocation,
901 startColumn,
902 endColumn,
903 m_sourceElements,
904 m_varDeclarations ? &m_varDeclarations->data : 0,
905 m_funcDeclarations ? &m_funcDeclarations->data : 0,
906 m_capturedVariables,
907 *m_source,
908 m_features,
909 m_numConstants);
910 result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset());
911 } else {
912 // We can never see a syntax error when reparsing a function, since we should have
913 // reported the error when parsing the containing program or eval code. So if we're
914 // parsing a function body node, we assume that what actually happened here is that
915 // we ran out of stack while parsing. If we see an error while parsing eval or program
916 // code we assume that it was a syntax error since running out of stack is much less
917 // likely, and we are currently unable to distinguish between the two cases.
918 if (isFunctionBodyNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow)
919 error = ParserError(ParserError::StackOverflow, ParserError::SyntaxErrorNone, m_token);
920 else {
921 ParserError::SyntaxErrorType errorType = ParserError::SyntaxErrorIrrecoverable;
922 if (m_token.m_type == EOFTOK)
923 errorType = ParserError::SyntaxErrorRecoverable;
924 else if (m_token.m_type & UnterminatedErrorTokenFlag)
925 errorType = ParserError::SyntaxErrorUnterminatedLiteral;
926
927 if (isEvalNode<ParsedNode>())
928 error = ParserError(ParserError::EvalError, errorType, m_token, errMsg, errLine);
929 else
930 error = ParserError(ParserError::SyntaxError, errorType, m_token, errMsg, errLine);
931 }
932 }
933
934 m_arena->reset();
935
936 return result.release();
937 }
938
939 template <class ParsedNode>
940 PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0, bool needReparsingAdjustment = false)
941 {
942 SamplingRegion samplingRegion("Parsing");
943
944 ASSERT(!source.provider()->source().isNull());
945 if (source.provider()->source().is8Bit()) {
946 Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode);
947 RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error, needReparsingAdjustment);
948 if (positionBeforeLastNewline)
949 *positionBeforeLastNewline = parser.positionBeforeLastNewline();
950 if (strictness == JSParseBuiltin) {
951 if (!result)
952 WTF::dataLog("Error compiling builtin: ", error.m_message, "\n");
953 RELEASE_ASSERT(result);
954 result->setClosedVariables(parser.closedVariables());
955 }
956 return result.release();
957 }
958 Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode);
959 RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error, needReparsingAdjustment);
960 if (positionBeforeLastNewline)
961 *positionBeforeLastNewline = parser.positionBeforeLastNewline();
962 return result.release();
963 }
964
965 } // namespace
966 #endif