summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/parser
diff options
context:
space:
mode:
authorLeon Clarke <leonclarke@google.com>2010-07-15 12:03:35 +0100
committerLeon Clarke <leonclarke@google.com>2010-07-20 16:57:23 +0100
commite458d70a0d18538346f41b503114c9ebe6b2ce12 (patch)
tree86f1637deca2c524432a822e5fcedd4bef221091 /JavaScriptCore/parser
parentf43eabc081f7ce6af24b9df4953498a3cd6ca24d (diff)
downloadexternal_webkit-e458d70a0d18538346f41b503114c9ebe6b2ce12.zip
external_webkit-e458d70a0d18538346f41b503114c9ebe6b2ce12.tar.gz
external_webkit-e458d70a0d18538346f41b503114c9ebe6b2ce12.tar.bz2
Merge WebKit at r63173 : Initial merge by git.
Change-Id: Ife5af0c7c6261fbbc8ae6bc08c390efa9ef10b44
Diffstat (limited to 'JavaScriptCore/parser')
-rw-r--r--JavaScriptCore/parser/ASTBuilder.h37
-rw-r--r--JavaScriptCore/parser/JSParser.cpp349
-rw-r--r--JavaScriptCore/parser/JSParser.h179
-rw-r--r--JavaScriptCore/parser/Lexer.cpp344
-rw-r--r--JavaScriptCore/parser/Lexer.h21
-rw-r--r--JavaScriptCore/parser/Nodes.cpp2
-rw-r--r--JavaScriptCore/parser/Nodes.h3
-rw-r--r--JavaScriptCore/parser/Parser.cpp2
-rw-r--r--JavaScriptCore/parser/ParserArena.cpp5
-rw-r--r--JavaScriptCore/parser/SourceProvider.h5
-rw-r--r--JavaScriptCore/parser/SyntaxChecker.h51
11 files changed, 544 insertions, 454 deletions
diff --git a/JavaScriptCore/parser/ASTBuilder.h b/JavaScriptCore/parser/ASTBuilder.h
index 7dcdff0..3b7ffb5 100644
--- a/JavaScriptCore/parser/ASTBuilder.h
+++ b/JavaScriptCore/parser/ASTBuilder.h
@@ -249,16 +249,9 @@ public:
return FunctionBodyNode::create(m_globalData);
}
- PropertyNode* createGetterOrSetterProperty(const Identifier* getOrSet, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+ template <bool> PropertyNode* createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
{
ASSERT(name);
- PropertyNode::Type type;
- if (*getOrSet == "get")
- type = PropertyNode::Getter;
- else if (*getOrSet == "set")
- type = PropertyNode::Setter;
- else
- return 0;
body->setLoc(bodyStartLine, bodyEndLine);
return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(m_globalData, m_globalData->propertyNames->nullIdentifier, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), params), type);
}
@@ -269,8 +262,8 @@ public:
ArgumentListNode* createArgumentsList(ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, arg); }
ArgumentListNode* createArgumentsList(ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, args, arg); }
- PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
- PropertyNode* createProperty(double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
+ template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
+ template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
PropertyListNode* createPropertyList(PropertyNode* property) { return new (m_globalData) PropertyListNode(m_globalData, property); }
PropertyListNode* createPropertyList(PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(m_globalData, property, tail); }
@@ -576,7 +569,9 @@ public:
assignmentStackDepth--;
return result;
}
-
+
+ const Identifier& getName(Property property) { return property->name(); }
+ PropertyNode::Type getType(Property property) { return property->type(); }
private:
struct Scope {
Scope(JSGlobalData* globalData)
@@ -767,13 +762,13 @@ ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, Bina
case AND:
return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalAnd);
- case '|':
+ case BITOR:
return new (m_globalData) BitOrNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '^':
+ case BITXOR:
return new (m_globalData) BitXOrNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '&':
+ case BITAND:
return new (m_globalData) BitAndNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
case EQEQ:
@@ -788,10 +783,10 @@ ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, Bina
case STRNEQ:
return new (m_globalData) NotStrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '<':
+ case LT:
return new (m_globalData) LessNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '>':
+ case GT:
return new (m_globalData) GreaterNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
case LE:
@@ -821,19 +816,19 @@ ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, Bina
case URSHIFT:
return new (m_globalData) UnsignedRightShiftNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '+':
+ case PLUS:
return makeAddNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '-':
+ case MINUS:
return makeSubNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '*':
+ case TIMES:
return makeMultNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '/':
+ case DIVIDE:
return makeDivNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '%':
+ case MOD:
return new (m_globalData) ModNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
}
CRASH();
diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp
index 5825270..1fb1a9187 100644
--- a/JavaScriptCore/parser/JSParser.cpp
+++ b/JavaScriptCore/parser/JSParser.cpp
@@ -32,6 +32,7 @@ using namespace JSC;
#include "JSGlobalData.h"
#include "NodeInfo.h"
#include "ASTBuilder.h"
+#include <wtf/HashFunctions.h>
#include <utility>
using namespace std;
@@ -58,12 +59,14 @@ namespace JSC {
#define TreeProperty typename TreeBuilder::Property
#define TreePropertyList typename TreeBuilder::PropertyList
+COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
+
// This matches v8
static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024;
class JSParser {
public:
- JSParser(Lexer*, JSGlobalData*);
+ JSParser(Lexer*, JSGlobalData*, SourceProvider*);
bool parseProgram();
private:
struct AllowInOverride {
@@ -84,14 +87,14 @@ private:
const JSToken& token() { return m_token; }
void next()
{
- m_lastLine = token().m_info.last_line;
- m_lastTokenEnd = token().m_info.last_column;
+ m_lastLine = token().m_info.line;
+ m_lastTokenEnd = token().m_info.endOffset;
m_lexer->setLastLineNumber(m_lastLine);
m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info);
m_tokenCount++;
}
- bool consume(int expected)
+ bool consume(JSTokenType expected)
{
bool result = m_token.m_type == expected;
failIfFalse(result);
@@ -99,24 +102,24 @@ private:
return result;
}
- bool match(int expected)
+ bool match(JSTokenType expected)
{
return m_token.m_type == expected;
}
int tokenStart()
{
- return token().m_info.first_column;
+ return token().m_info.startOffset;
}
int tokenLine()
{
- return token().m_info.first_line;
+ return token().m_info.line;
}
int tokenEnd()
{
- return token().m_info.last_column;
+ return token().m_info.endOffset;
}
template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
@@ -150,20 +153,21 @@ private:
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
- template <class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
+ template <bool strict, class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&, bool& usesArguments);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
template <FunctionRequirements, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
- int isBinaryOperator(int token);
+ ALWAYS_INLINE int isBinaryOperator(JSTokenType token);
bool allowAutomaticSemicolon();
bool autoSemiColon()
{
- if (token().m_type == ';') {
+ if (token().m_type == SEMICOLON) {
next();
return true;
}
@@ -194,15 +198,16 @@ private:
int m_lastTokenEnd;
int m_assignmentCount;
int m_nonLHSCount;
+ bool m_syntaxAlreadyValidated;
};
-int jsParse(JSGlobalData* globalData)
+int jsParse(JSGlobalData* globalData, const SourceCode* source)
{
- JSParser parser(globalData->lexer, globalData);
+ JSParser parser(globalData->lexer, globalData, source->provider());
return parser.parseProgram();
}
-JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData)
+JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, SourceProvider* provider)
: m_lexer(lexer)
, m_endAddress(0)
, m_error(false)
@@ -213,6 +218,7 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData)
, m_lastTokenEnd(0)
, m_assignmentCount(0)
, m_nonLHSCount(0)
+ , m_syntaxAlreadyValidated(provider->isValid())
{
m_endAddress = *(globalData->stackGuards);
if (!m_endAddress) {
@@ -228,7 +234,7 @@ bool JSParser::parseProgram()
{
ASTBuilder context(m_globalData, m_lexer);
SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context);
- if (!sourceElements || !consume(0))
+ if (!sourceElements || !consume(EOFTOK))
return true;
m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(),
m_lastLine, context.numConstants());
@@ -237,7 +243,7 @@ bool JSParser::parseProgram()
bool JSParser::allowAutomaticSemicolon()
{
- return match(CLOSEBRACE) || match(0) || m_lexer->prevTerminator();
+ return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
}
template <class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
@@ -288,11 +294,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeB
failIfFalse(statement);
int endLine = tokenLine();
consumeOrFail(WHILE);
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
- consumeOrFail(')');
- if (match(';'))
+ consumeOrFail(CLOSEPAREN);
+ if (match(SEMICOLON))
next(); // Always performs automatic semicolon insertion.
return context.createDoWhileStatement(statement, expr, startLine, endLine);
}
@@ -302,11 +308,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBui
ASSERT(match(WHILE));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
return context.createWhileStatement(expr, statement, startLine, endLine);
@@ -325,7 +331,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr
const Identifier* name = token().m_data.ident;
lastIdent = name;
next();
- bool hasInitializer = match('=');
+ bool hasInitializer = match(EQUAL);
context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
if (hasInitializer) {
int varDivot = tokenStart() + 1;
@@ -343,7 +349,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr
else
varDecls = context.combineCommaNodes(varDecls, node);
}
- } while (match(','));
+ } while (match(COMMA));
return varDecls;
}
@@ -356,7 +362,7 @@ template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationLi
matchOrFail(IDENT);
const Identifier* name = token().m_data.ident;
next();
- bool hasInitializer = match('=');
+ bool hasInitializer = match(EQUAL);
context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
TreeExpression initializer = 0;
if (hasInitializer) {
@@ -366,7 +372,7 @@ template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationLi
tail = context.appendConstDecl(tail, name, initializer);
if (!constDecls)
constDecls = tail;
- } while (match(','));
+ } while (match(COMMA));
return constDecls;
}
@@ -375,7 +381,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
ASSERT(match(FOR));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
int nonLHSCount = m_nonLHSCount;
int declarations = 0;
int declsStart = 0;
@@ -400,7 +406,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
fail();
// Remainder of a standard for loop is handled identically
- if (declarations > 1 || match(';'))
+ if (declarations > 1 || match(SEMICOLON))
goto standardForLoop;
// Handle for-in with var declaration
@@ -413,7 +419,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
int exprEnd = lastTokenEnd();
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
@@ -421,7 +427,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
}
- if (!match(';')) {
+ if (!match(SEMICOLON)) {
m_allowsIn = false;
declsStart = tokenStart();
decls = parseExpression(context);
@@ -430,25 +436,25 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
failIfFalse(decls);
}
- if (match(';')) {
+ if (match(SEMICOLON)) {
standardForLoop:
// Standard for loop
next();
TreeExpression condition = 0;
- if (!match(';')) {
+ if (!match(SEMICOLON)) {
condition = parseExpression(context);
failIfFalse(condition);
}
- consumeOrFail(';');
+ consumeOrFail(SEMICOLON);
TreeExpression increment = 0;
- if (!match(')')) {
+ if (!match(CLOSEPAREN)) {
increment = parseExpression(context);
failIfFalse(increment);
}
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
@@ -461,7 +467,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
failIfFalse(expr);
int exprEnd = lastTokenEnd();
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
@@ -519,14 +525,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBu
// We do the auto semicolon check before attempting to parse an expression
// as we need to ensure the a line break after the return correctly terminates
// the statement
- if (match(';'))
+ if (match(SEMICOLON))
endLine = tokenLine();
if (autoSemiColon())
return context.createReturnStatement(0, start, end, startLine, endLine);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
end = lastTokenEnd();
- if (match(';'))
+ if (match(SEMICOLON))
endLine = tokenLine();
failIfFalse(autoSemiColon());
return context.createReturnStatement(expr, start, end, startLine, endLine);
@@ -553,14 +559,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuil
ASSERT(match(WITH));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
int start = tokenStart();
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
int end = lastTokenEnd();
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
@@ -573,11 +579,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBu
ASSERT(match(SWITCH));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
consumeOrFail(OPENBRACE);
TreeClauseList firstClauses = parseSwitchClauses(context);
@@ -601,7 +607,7 @@ template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBui
next();
TreeExpression condition = parseExpression(context);
failIfFalse(condition);
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeSourceElements statements = parseSourceElements(context);
failIfFalse(statements);
TreeClause clause = context.createClause(condition, statements);
@@ -612,7 +618,7 @@ template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBui
next();
TreeExpression condition = parseExpression(context);
failIfFalse(condition);
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeSourceElements statements = parseSourceElements(context);
failIfFalse(statements);
clause = context.createClause(condition, statements);
@@ -626,7 +632,7 @@ template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeB
if (!match(DEFAULT))
return 0;
next();
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeSourceElements statements = parseSourceElements(context);
failIfFalse(statements);
return context.createClause(0, statements);
@@ -650,11 +656,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild
if (match(CATCH)) {
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
matchOrFail(IDENT);
ident = token().m_data.ident;
next();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
matchOrFail(OPENBRACE);
int initialEvalCount = context.evalCount();
catchBlock = parseBlockStatement(context);
@@ -678,7 +684,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(Tree
int startLine = tokenLine();
int endLine = startLine;
next();
- if (match(';'))
+ if (match(SEMICOLON))
startLine = tokenLine();
failIfFalse(autoSemiColon());
return context.createDebugger(startLine, endLine);
@@ -712,7 +718,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder&
return parseConstDeclaration(context);
case FUNCTION:
return parseFunctionDeclaration(context);
- case ';':
+ case SEMICOLON:
next();
return context.createEmptyStatement();
case IF:
@@ -739,7 +745,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder&
return parseTryStatement(context);
case DEBUGGER:
return parseDebuggerStatement(context);
- case 0:
+ case EOFTOK:
case CASE:
case CLOSEBRACE:
case DEFAULT:
@@ -759,7 +765,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame
TreeFormalParameterList list = context.createFormalParameterList(*token().m_data.ident);
TreeFormalParameterList tail = list;
next();
- while (match(',')) {
+ while (match(COMMA)) {
next();
matchOrFail(IDENT);
const Identifier* ident = token().m_data.ident;
@@ -786,13 +792,13 @@ template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool J
next();
} else if (requirements == FunctionNeedsName)
return false;
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
bool usesArguments = false;
- if (!match(')')) {
+ if (!match(CLOSEPAREN)) {
parameters = parseFormalParameters(context, usesArguments);
failIfFalse(parameters);
}
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
matchOrFail(OPENBRACE);
openBracePos = token().m_data.intValue;
@@ -843,7 +849,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelState
return context.createExprStatement(expression, startLine, m_lastLine);
failIfFalse(currentToken + 1 == m_tokenCount);
int end = tokenEnd();
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
return context.createLabelStatement(ident, statement, start, end);
@@ -865,12 +871,12 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde
int start = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression condition = parseExpression(context);
failIfFalse(condition);
int end = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement trueBlock = parseStatement(context);
failIfFalse(trueBlock);
@@ -894,12 +900,12 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde
int innerStart = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression innerCondition = parseExpression(context);
failIfFalse(innerCondition);
int innerEnd = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement innerTrueBlock = parseStatement(context);
failIfFalse(innerTrueBlock);
@@ -938,14 +944,14 @@ template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilde
failIfStackOverflow();
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node);
- if (!match(','))
+ if (!match(COMMA))
return node;
next();
m_nonLHSCount++;
TreeExpression right = parseAssignmentExpression(context);
failIfFalse(right);
typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
- while (match(',')) {
+ while (match(COMMA)) {
next();
right = parseAssignmentExpression(context);
failIfFalse(right);
@@ -971,7 +977,7 @@ template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpressi
bool hadAssignment = false;
while (true) {
switch (token().m_type) {
- case '=': op = OpEqual; break;
+ case EQUAL: op = OpEqual; break;
case PLUSEQUAL: op = OpPlusEq; break;
case MINUSEQUAL: op = OpMinusEq; break;
case MULTEQUAL: op = OpMultEq; break;
@@ -1013,92 +1019,28 @@ template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression
{
TreeExpression cond = parseBinaryExpression(context);
failIfFalse(cond);
- if (!match('?'))
+ if (!match(QUESTION))
return cond;
m_nonLHSCount++;
next();
TreeExpression lhs = parseAssignmentExpression(context);
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeExpression rhs = parseAssignmentExpression(context);
failIfFalse(rhs);
return context.createConditionalExpr(cond, lhs, rhs);
}
-static bool isUnaryOp(int token)
+ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
{
- switch (token) {
- case '!':
- case '~':
- case '-':
- case '+':
- case PLUSPLUS:
- case AUTOPLUSPLUS:
- case MINUSMINUS:
- case AUTOMINUSMINUS:
- case TYPEOF:
- case VOIDTOKEN:
- case DELETETOKEN:
- return true;
- default:
- return false;
- }
+ return token & UnaryOpTokenFlag;
}
-int JSParser::isBinaryOperator(int token)
+int JSParser::isBinaryOperator(JSTokenType token)
{
- switch (token) {
- case OR:
- return 1;
-
- case AND:
- return 2;
-
- case '|':
- return 3;
-
- case '^':
- return 4;
-
- case '&':
- return 5;
-
- case EQEQ:
- case NE:
- case STREQ:
- case STRNEQ:
- return 6;
-
- case '<':
- case '>':
- case LE:
- case GE:
- case INSTANCEOF:
- return 7;
-
- case INTOKEN:
- // same precedence as the above but needs a validity check
- if (m_allowsIn)
- return 7;
- return 0;
-
- case LSHIFT:
- case RSHIFT:
- case URSHIFT:
- return 8;
-
- case '+':
- case '-':
- return 9;
-
- case '*':
- case '/':
- case '%':
- return 10;
-
- default:
- return 0;
- }
+ if (m_allowsIn)
+ return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
+ return token & BinaryOpTokenPrecedenceMask;
}
template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
@@ -1145,7 +1087,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(Tree
}
-template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
+template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
{
bool wasIdent = false;
switch (token().m_type) {
@@ -1154,11 +1096,11 @@ template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& c
case STRING: {
const Identifier* ident = token().m_data.ident;
next();
- if (match(':')) {
+ if (match(COLON)) {
next();
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node);
- return context.createProperty(ident, node, PropertyNode::Constant);
+ return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
}
failIfFalse(wasIdent);
matchOrFail(IDENT);
@@ -1168,23 +1110,32 @@ template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& c
int openBracePos = 0;
int closeBracePos = 0;
int bodyStartLine = 0;
+ PropertyNode::Type type;
+ if (*ident == m_globalData->propertyNames->get)
+ type = PropertyNode::Getter;
+ else if (*ident == m_globalData->propertyNames->set)
+ type = PropertyNode::Setter;
+ else
+ fail();
failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine));
- return context.createGetterOrSetterProperty(ident, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+ return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
}
case NUMBER: {
double propertyName = token().m_data.doubleValue;
next();
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node);
- return context.createProperty(propertyName, node, PropertyNode::Constant);
+ return context.template createProperty<complete>(m_globalData, propertyName, node, PropertyNode::Constant);
}
+ default:
+ fail();
}
- fail();
}
template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
{
+ int startOffset = token().m_data.intValue;
consumeOrFail(OPENBRACE);
if (match(CLOSEBRACE)) {
@@ -1192,20 +1143,27 @@ template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBui
return context.createObjectLiteral();
}
- TreeProperty property = parseProperty(context);
+ TreeProperty property = parseProperty<false>(context);
failIfFalse(property);
-
+ if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+ m_lexer->setOffset(startOffset);
+ next();
+ return parseStrictObjectLiteral(context);
+ }
TreePropertyList propertyList = context.createPropertyList(property);
TreePropertyList tail = propertyList;
-
- while (match(',')) {
+ while (match(COMMA)) {
next();
// allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
if (match(CLOSEBRACE))
break;
- property = parseProperty(context);
+ property = parseProperty<false>(context);
failIfFalse(property);
-
+ if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+ m_lexer->setOffset(startOffset);
+ next();
+ return parseStrictObjectLiteral(context);
+ }
tail = context.createPropertyList(property, tail);
}
@@ -1214,16 +1172,62 @@ template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBui
return context.createObjectLiteral(propertyList);
}
+template <class TreeBuilder> TreeExpression JSParser::parseStrictObjectLiteral(TreeBuilder& context)
+{
+ consumeOrFail(OPENBRACE);
+
+ if (match(CLOSEBRACE)) {
+ next();
+ return context.createObjectLiteral();
+ }
+
+ TreeProperty property = parseProperty<true>(context);
+ failIfFalse(property);
+
+ typedef HashMap<RefPtr<UString::Rep>, unsigned, IdentifierRepHash> ObjectValidationMap;
+ ObjectValidationMap objectValidator;
+ // Add the first property
+ if (!m_syntaxAlreadyValidated)
+ objectValidator.add(context.getName(property).ustring().rep(), context.getType(property));
+
+ TreePropertyList propertyList = context.createPropertyList(property);
+ TreePropertyList tail = propertyList;
+ while (match(COMMA)) {
+ next();
+ // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
+ if (match(CLOSEBRACE))
+ break;
+ property = parseProperty<true>(context);
+ failIfFalse(property);
+ if (!m_syntaxAlreadyValidated) {
+ std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).ustring().rep(), context.getType(property));
+ if (!propertyEntryIter.second) {
+ if ((context.getType(property) & propertyEntryIter.first->second) != PropertyNode::Constant) {
+ // Can't have multiple getters or setters with the same name, nor can we define
+ // a property as both an accessor and a constant value
+ failIfTrue(context.getType(property) & propertyEntryIter.first->second);
+ failIfTrue((context.getType(property) | propertyEntryIter.first->second) & PropertyNode::Constant);
+ }
+ }
+ }
+ tail = context.createPropertyList(property, tail);
+ }
+
+ consumeOrFail(CLOSEBRACE);
+
+ return context.createObjectLiteral(propertyList);
+}
+
template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
{
- consumeOrFail('[');
+ consumeOrFail(OPENBRACKET);
int elisions = 0;
- while (match(',')) {
+ while (match(COMMA)) {
next();
elisions++;
}
- if (match(']')) {
+ if (match(CLOSEBRACKET)) {
next();
return context.createArray(elisions);
}
@@ -1233,16 +1237,16 @@ template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuil
typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
typename TreeBuilder::ElementList tail = elementList;
elisions = 0;
- while (match(',')) {
+ while (match(COMMA)) {
next();
elisions = 0;
- while (match(',')) {
+ while (match(COMMA)) {
next();
elisions++;
}
- if (match(']')) {
+ if (match(CLOSEBRACKET)) {
next();
return context.createArray(elisions, elementList);
}
@@ -1251,7 +1255,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuil
tail = context.createElementList(tail, elisions, elem);
}
- consumeOrFail(']');
+ consumeOrFail(CLOSEBRACKET);
return context.createArray(elementList);
}
@@ -1261,14 +1265,14 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre
switch (token().m_type) {
case OPENBRACE:
return parseObjectLiteral(context);
- case '[':
+ case OPENBRACKET:
return parseArrayLiteral(context);
- case '(': {
+ case OPENPAREN: {
next();
int oldNonLHSCount = m_nonLHSCount;
TreeExpression result = parseExpression(context);
m_nonLHSCount = oldNonLHSCount;
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
return result;
}
@@ -1305,7 +1309,7 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre
return context.createBoolean(false);
}
case DIVEQUAL:
- case '/': {
+ case DIVIDE: {
/* regexp */
const Identifier* pattern;
const Identifier* flags;
@@ -1318,14 +1322,15 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre
next();
return context.createRegex(*pattern, *flags, start);
}
+ default:
+ fail();
}
- fail();
}
template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
{
- consumeOrFail('(');
- if (match(')')) {
+ consumeOrFail(OPENPAREN);
+ if (match(CLOSEPAREN)) {
next();
return context.createArguments();
}
@@ -1334,13 +1339,13 @@ template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder&
TreeArgumentsList argList = context.createArgumentsList(firstArg);
TreeArgumentsList tail = argList;
- while (match(',')) {
+ while (match(COMMA)) {
next();
TreeExpression arg = parseAssignmentExpression(context);
failIfFalse(arg);
tail = context.createArgumentsList(tail, arg);
}
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
return context.createArguments(argList);
}
@@ -1370,7 +1375,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree
failIfFalse(base);
while (true) {
switch (token().m_type) {
- case '[': {
+ case OPENBRACKET: {
int expressionEnd = lastTokenEnd();
next();
int nonLHSCount = m_nonLHSCount;
@@ -1378,15 +1383,15 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree
TreeExpression property = parseExpression(context);
failIfFalse(property);
base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
- if (!consume(']'))
+ if (!consume(CLOSEBRACKET))
fail();
m_nonLHSCount = nonLHSCount;
break;
}
- case '(': {
+ case OPENPAREN: {
if (newCount) {
newCount--;
- if (match('(')) {
+ if (match(OPENPAREN)) {
int exprEnd = lastTokenEnd();
TreeArguments arguments = parseArguments(context);
failIfFalse(arguments);
@@ -1403,7 +1408,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree
}
break;
}
- case '.': {
+ case DOT: {
int expressionEnd = lastTokenEnd();
next();
matchOrFail(IDENT);
@@ -1446,6 +1451,8 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB
m_assignmentCount++;
next();
break;
+ default:
+ break;
}
int end = lastTokenEnd();
@@ -1455,16 +1462,16 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB
while (tokenStackDepth) {
switch (context.unaryTokenStackLastType(tokenStackDepth)) {
- case '!':
+ case EXCLAMATION:
expr = context.createLogicalNot(expr);
break;
- case '~':
+ case TILDE:
expr = context.makeBitwiseNotNode(expr);
break;
- case '-':
+ case MINUS:
expr = context.makeNegateNode(expr);
break;
- case '+':
+ case PLUS:
expr = context.createUnaryPlus(expr);
break;
case PLUSPLUS:
diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h
index 554556f..60f284c 100644
--- a/JavaScriptCore/parser/JSParser.h
+++ b/JavaScriptCore/parser/JSParser.h
@@ -30,71 +30,108 @@ namespace JSC {
class Identifier;
class JSGlobalData;
+class SourceCode;
+
+enum {
+ UnaryOpTokenFlag = 64,
+ BinaryOpTokenPrecedenceShift = 7,
+ BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4,
+ BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift
+};
+
+#define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)))
+#define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))
enum JSTokenType {
- NULLTOKEN = 258,
- TRUETOKEN = 259,
- FALSETOKEN = 260,
- BREAK = 261,
- CASE = 262,
- DEFAULT = 263,
- FOR = 264,
- NEW = 265,
- VAR = 266,
- CONSTTOKEN = 267,
- CONTINUE = 268,
- FUNCTION = 269,
- RETURN = 270,
- VOIDTOKEN = 271,
- DELETETOKEN = 272,
- IF = 273,
- THISTOKEN = 274,
- DO = 275,
- WHILE = 276,
- INTOKEN = 277,
- INSTANCEOF = 278,
- TYPEOF = 279,
- SWITCH = 280,
- WITH = 281,
- RESERVED = 282,
- THROW = 283,
- TRY = 284,
- CATCH = 285,
- FINALLY = 286,
- DEBUGGER = 287,
- IF_WITHOUT_ELSE = 288,
- ELSE = 289,
- EQEQ = 290,
- NE = 291,
- STREQ = 292,
- STRNEQ = 293,
- LE = 294,
- GE = 295,
- OR = 296,
- AND = 297,
- PLUSPLUS = 298,
- MINUSMINUS = 299,
- LSHIFT = 300,
- RSHIFT = 301,
- URSHIFT = 302,
- PLUSEQUAL = 303,
- MINUSEQUAL = 304,
- MULTEQUAL = 305,
- DIVEQUAL = 306,
- LSHIFTEQUAL = 307,
- RSHIFTEQUAL = 308,
- URSHIFTEQUAL = 309,
- ANDEQUAL = 310,
- MODEQUAL = 311,
- XOREQUAL = 312,
- OREQUAL = 313,
- OPENBRACE = 314,
- CLOSEBRACE = 315,
- NUMBER = 316,
- IDENT = 317,
- STRING = 318,
- AUTOPLUSPLUS = 319,
- AUTOMINUSMINUS = 320
+ NULLTOKEN,
+ TRUETOKEN,
+ FALSETOKEN,
+ BREAK,
+ CASE,
+ DEFAULT,
+ FOR,
+ NEW,
+ VAR,
+ CONSTTOKEN,
+ CONTINUE,
+ FUNCTION,
+ RETURN,
+ IF,
+ THISTOKEN,
+ DO,
+ WHILE,
+ SWITCH,
+ WITH,
+ RESERVED,
+ THROW,
+ TRY,
+ CATCH,
+ FINALLY,
+ DEBUGGER,
+ ELSE,
+ OPENBRACE,
+ CLOSEBRACE,
+ OPENPAREN,
+ CLOSEPAREN,
+ OPENBRACKET,
+ CLOSEBRACKET,
+ COMMA,
+ QUESTION,
+ NUMBER,
+ IDENT,
+ STRING,
+ SEMICOLON,
+ COLON,
+ DOT,
+ ERRORTOK,
+ EOFTOK,
+ EQUAL,
+ PLUSEQUAL,
+ MINUSEQUAL,
+ MULTEQUAL,
+ DIVEQUAL,
+ LSHIFTEQUAL,
+ RSHIFTEQUAL,
+ URSHIFTEQUAL,
+ ANDEQUAL,
+ MODEQUAL,
+ XOREQUAL,
+ OREQUAL,
+ LastUntaggedToken,
+
+ // Begin tagged tokens
+ PLUSPLUS = 0 | UnaryOpTokenFlag,
+ MINUSMINUS = 1 | UnaryOpTokenFlag,
+ EXCLAMATION = 2 | UnaryOpTokenFlag,
+ TILDE = 3 | UnaryOpTokenFlag,
+ AUTOPLUSPLUS = 4 | UnaryOpTokenFlag,
+ AUTOMINUSMINUS = 5 | UnaryOpTokenFlag,
+ TYPEOF = 6 | UnaryOpTokenFlag,
+ VOIDTOKEN = 7 | UnaryOpTokenFlag,
+ DELETETOKEN = 8 | UnaryOpTokenFlag,
+ OR = 0 | BINARY_OP_PRECEDENCE(1),
+ AND = 1 | BINARY_OP_PRECEDENCE(2),
+ BITOR = 2 | BINARY_OP_PRECEDENCE(3),
+ BITXOR = 3 | BINARY_OP_PRECEDENCE(4),
+ BITAND = 4 | BINARY_OP_PRECEDENCE(5),
+ EQEQ = 5 | BINARY_OP_PRECEDENCE(6),
+ NE = 6 | BINARY_OP_PRECEDENCE(6),
+ STREQ = 7 | BINARY_OP_PRECEDENCE(6),
+ STRNEQ = 8 | BINARY_OP_PRECEDENCE(6),
+ LT = 9 | BINARY_OP_PRECEDENCE(7),
+ GT = 10 | BINARY_OP_PRECEDENCE(7),
+ LE = 11 | BINARY_OP_PRECEDENCE(7),
+ GE = 12 | BINARY_OP_PRECEDENCE(7),
+ INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7),
+ INTOKEN = 14 | IN_OP_PRECEDENCE(7),
+ LSHIFT = 15 | BINARY_OP_PRECEDENCE(8),
+ RSHIFT = 16 | BINARY_OP_PRECEDENCE(8),
+ URSHIFT = 17 | BINARY_OP_PRECEDENCE(8),
+ PLUS = 18 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
+ MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
+ TIMES = 20 | BINARY_OP_PRECEDENCE(10),
+ DIVIDE = 21 | BINARY_OP_PRECEDENCE(10),
+ MOD = 22 | BINARY_OP_PRECEDENCE(10)
};
union JSTokenData {
@@ -102,22 +139,20 @@ union JSTokenData {
double doubleValue;
const Identifier* ident;
};
-typedef JSTokenData YYSTYPE;
struct JSTokenInfo {
- JSTokenInfo() : last_line(0) {}
- int first_line;
- int last_line;
- int first_column;
- int last_column;
+ JSTokenInfo() : line(0) {}
+ int line;
+ int startOffset;
+ int endOffset;
};
-typedef JSTokenInfo YYLTYPE;
+
struct JSToken {
- int m_type;
+ JSTokenType m_type;
JSTokenData m_data;
JSTokenInfo m_info;
};
-int jsParse(JSGlobalData*);
+int jsParse(JSGlobalData*, const SourceCode*);
}
#endif // JSParser_h
diff --git a/JavaScriptCore/parser/Lexer.cpp b/JavaScriptCore/parser/Lexer.cpp
index 660b1a4..45fe007 100644
--- a/JavaScriptCore/parser/Lexer.cpp
+++ b/JavaScriptCore/parser/Lexer.cpp
@@ -56,7 +56,14 @@ enum CharacterTypes {
CharacterLineTerminator,
CharacterExclamationMark,
- CharacterSimple,
+ CharacterOpenParen,
+ CharacterCloseParen,
+ CharacterOpenBracket,
+ CharacterCloseBracket,
+ CharacterComma,
+ CharacterColon,
+ CharacterQuestion,
+ CharacterTilde,
CharacterQuote,
CharacterDot,
CharacterSlash,
@@ -81,7 +88,7 @@ enum CharacterTypes {
};
// 128 ascii codes
-static unsigned char AsciiCharacters[128] = {
+static unsigned short AsciiCharacters[128] = {
/* 0 - Null */ CharacterInvalid,
/* 1 - Start of Heading */ CharacterInvalid,
/* 2 - Start of Text */ CharacterInvalid,
@@ -122,11 +129,11 @@ static unsigned char AsciiCharacters[128] = {
/* 37 - % */ CharacterModulo,
/* 38 - & */ CharacterAnd,
/* 39 - ' */ CharacterQuote,
-/* 40 - ( */ CharacterSimple,
-/* 41 - ) */ CharacterSimple,
+/* 40 - ( */ CharacterOpenParen,
+/* 41 - ) */ CharacterCloseParen,
/* 42 - * */ CharacterMultiply,
/* 43 - + */ CharacterAdd,
-/* 44 - , */ CharacterSimple,
+/* 44 - , */ CharacterComma,
/* 45 - - */ CharacterSub,
/* 46 - . */ CharacterDot,
/* 47 - / */ CharacterSlash,
@@ -140,12 +147,12 @@ static unsigned char AsciiCharacters[128] = {
/* 55 - 7 */ CharacterNumber,
/* 56 - 8 */ CharacterNumber,
/* 57 - 9 */ CharacterNumber,
-/* 58 - : */ CharacterSimple,
+/* 58 - : */ CharacterColon,
/* 59 - ; */ CharacterSemicolon,
/* 60 - < */ CharacterLess,
/* 61 - = */ CharacterEqual,
/* 62 - > */ CharacterGreater,
-/* 63 - ? */ CharacterSimple,
+/* 63 - ? */ CharacterQuestion,
/* 64 - @ */ CharacterInvalid,
/* 65 - A */ CharacterAlpha,
/* 66 - B */ CharacterAlpha,
@@ -173,9 +180,9 @@ static unsigned char AsciiCharacters[128] = {
/* 88 - X */ CharacterAlpha,
/* 89 - Y */ CharacterAlpha,
/* 90 - Z */ CharacterAlpha,
-/* 91 - [ */ CharacterSimple,
+/* 91 - [ */ CharacterOpenBracket,
/* 92 - \ */ CharacterBackSlash,
-/* 93 - ] */ CharacterSimple,
+/* 93 - ] */ CharacterCloseBracket,
/* 94 - ^ */ CharacterXor,
/* 95 - _ */ CharacterAlpha,
/* 96 - ` */ CharacterInvalid,
@@ -208,7 +215,7 @@ static unsigned char AsciiCharacters[128] = {
/* 123 - { */ CharacterOpenBrace,
/* 124 - | */ CharacterOr,
/* 125 - } */ CharacterCloseBrace,
-/* 126 - ~ */ CharacterSimple,
+/* 126 - ~ */ CharacterTilde,
/* 127 - Delete */ CharacterInvalid,
};
@@ -357,8 +364,14 @@ static inline int singleEscape(int c)
return 0x0C;
case 'r':
return 0x0D;
+ case '\\':
+ return '\\';
+ case '\'':
+ return '\'';
+ case '"':
+ return '"';
default:
- return c;
+ return 0;
}
}
@@ -381,15 +394,92 @@ inline void Lexer::record16(int c)
record16(UChar(static_cast<unsigned short>(c)));
}
-int Lexer::lex(void* p1, void* p2)
+ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp)
+{
+ int stringQuoteCharacter = m_current;
+ shift();
+
+ const UChar* stringStart = currentCharacter();
+
+ while (m_current != stringQuoteCharacter) {
+ if (UNLIKELY(m_current == '\\')) {
+ if (stringStart != currentCharacter())
+ m_buffer16.append(stringStart, currentCharacter() - stringStart);
+ shift();
+
+ int escape = singleEscape(m_current);
+
+ // Most common escape sequences first
+ if (escape) {
+ record16(escape);
+ shift();
+ } else if (UNLIKELY(isLineTerminator(m_current)))
+ shiftLineTerminator();
+ else if (m_current == 'x') {
+ shift();
+ if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
+ int prev = m_current;
+ shift();
+ record16(convertHex(prev, m_current));
+ shift();
+ } else
+ record16('x');
+ } else if (m_current == 'u') {
+ shift();
+ int character = getUnicodeCharacter();
+ if (character != -1)
+ record16(character);
+ else if (m_current == stringQuoteCharacter)
+ record16('u');
+ else // Only stringQuoteCharacter allowed after \u
+ return false;
+ } else if (isASCIIOctalDigit(m_current)) {
+ // Octal character sequences
+ int character1 = m_current;
+ shift();
+ if (isASCIIOctalDigit(m_current)) {
+ // Two octal characters
+ int character2 = m_current;
+ shift();
+ if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
+ record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
+ shift();
+ } else
+ record16((character1 - '0') * 8 + character2 - '0');
+ } else
+ record16(character1 - '0');
+ } else if (m_current != -1) {
+ record16(m_current);
+ shift();
+ } else
+ return false;
+
+ stringStart = currentCharacter();
+ continue;
+ } else if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
+ // New-line or end of input is not allowed
+ if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1))
+ return false;
+ // Anything else is just a normal character
+ }
+ shift();
+ }
+
+ if (currentCharacter() != stringStart)
+ m_buffer16.append(stringStart, currentCharacter() - stringStart);
+ lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+ m_buffer16.resize(0);
+ return true;
+}
+
+JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp)
{
ASSERT(!m_error);
ASSERT(m_buffer8.isEmpty());
ASSERT(m_buffer16.isEmpty());
- YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1);
- YYLTYPE* llocp = static_cast<YYLTYPE*>(p2);
- int token = 0;
+ JSTokenType token = ERRORTOK;
+ int identChar = 0;
m_terminator = false;
start:
@@ -398,20 +488,13 @@ start:
int startOffset = currentOffset();
- if (UNLIKELY(m_current == -1)) {
- if (!m_terminator && !m_delimited && !m_isReparsing) {
- // automatic semicolon insertion if program incomplete
- token = ';';
- goto doneSemicolon;
- }
- return 0;
- }
+ if (UNLIKELY(m_current == -1))
+ return EOFTOK;
m_delimited = false;
- ASSERT(m_current >= 0);
- if (m_current < 128) {
- ASSERT(isASCII(m_current));
+ if (isASCII(m_current)) {
+ ASSERT(m_current >= 0 && m_current < 128);
switch (AsciiCharacters[m_current]) {
case CharacterGreater:
@@ -441,7 +524,7 @@ start:
token = GE;
break;
}
- token = '>';
+ token = GT;
break;
case CharacterEqual:
shift();
@@ -455,7 +538,7 @@ start:
token = EQEQ;
break;
}
- token = '=';
+ token = EQUAL;
break;
case CharacterLess:
shift();
@@ -478,7 +561,7 @@ start:
token = LE;
break;
}
- token = '<';
+ token = LT;
break;
case CharacterExclamationMark:
shift();
@@ -492,7 +575,7 @@ start:
token = NE;
break;
}
- token = '!';
+ token = EXCLAMATION;
break;
case CharacterAdd:
shift();
@@ -506,7 +589,7 @@ start:
token = PLUSEQUAL;
break;
}
- token = '+';
+ token = PLUS;
break;
case CharacterSub:
shift();
@@ -524,7 +607,7 @@ start:
token = MINUSEQUAL;
break;
}
- token = '-';
+ token = MINUS;
break;
case CharacterMultiply:
shift();
@@ -533,7 +616,7 @@ start:
token = MULTEQUAL;
break;
}
- token = '*';
+ token = TIMES;
break;
case CharacterSlash:
shift();
@@ -550,7 +633,7 @@ start:
token = DIVEQUAL;
break;
}
- token = '/';
+ token = DIVIDE;
break;
case CharacterAnd:
shift();
@@ -564,7 +647,7 @@ start:
token = ANDEQUAL;
break;
}
- token = '&';
+ token = BITAND;
break;
case CharacterXor:
shift();
@@ -573,7 +656,7 @@ start:
token = XOREQUAL;
break;
}
- token = '^';
+ token = BITXOR;
break;
case CharacterModulo:
shift();
@@ -582,7 +665,7 @@ start:
token = MODEQUAL;
break;
}
- token = '%';
+ token = MOD;
break;
case CharacterOr:
shift();
@@ -596,7 +679,7 @@ start:
token = OR;
break;
}
- token = '|';
+ token = BITOR;
break;
case CharacterDot:
shift();
@@ -604,16 +687,44 @@ start:
record8('.');
goto inNumberAfterDecimalPoint;
}
- token = '.';
+ token = DOT;
+ break;
+ case CharacterOpenParen:
+ token = OPENPAREN;
+ shift();
+ break;
+ case CharacterCloseParen:
+ token = CLOSEPAREN;
+ shift();
+ break;
+ case CharacterOpenBracket:
+ token = OPENBRACKET;
+ shift();
break;
- case CharacterSimple:
- token = m_current;
+ case CharacterCloseBracket:
+ token = CLOSEBRACKET;
+ shift();
+ break;
+ case CharacterComma:
+ token = COMMA;
+ shift();
+ break;
+ case CharacterColon:
+ token = COLON;
+ shift();
+ break;
+ case CharacterQuestion:
+ token = QUESTION;
+ shift();
+ break;
+ case CharacterTilde:
+ token = TILDE;
shift();
break;
case CharacterSemicolon:
m_delimited = true;
shift();
- token = ';';
+ token = SEMICOLON;
break;
case CharacterOpenBrace:
lvalp->intValue = currentOffset();
@@ -633,7 +744,12 @@ start:
case CharacterNumber:
goto startNumber;
case CharacterQuote:
- goto startString;
+ if (UNLIKELY(!parseString(lvalp)))
+ goto returnError;
+ shift();
+ m_delimited = false;
+ token = STRING;
+ break;
case CharacterAlpha:
ASSERT(isIdentStart(m_current));
goto startIdentifierOrKeyword;
@@ -643,7 +759,7 @@ start:
m_atLineStart = true;
m_terminator = true;
if (lastTokenWasRestrKeyword()) {
- token = ';';
+ token = SEMICOLON;
goto doneSemicolon;
}
goto start;
@@ -655,7 +771,6 @@ start:
}
} else {
// Rare characters
- ASSERT(!isASCII(m_current));
if (isNonASCIIIdentStart(m_current))
goto startIdentifierOrKeyword;
@@ -663,10 +778,8 @@ start:
shiftLineTerminator();
m_atLineStart = true;
m_terminator = true;
- if (lastTokenWasRestrKeyword()) {
- token = ';';
+ if (lastTokenWasRestrKeyword())
goto doneSemicolon;
- }
goto start;
}
goto returnError;
@@ -675,109 +788,16 @@ start:
m_atLineStart = false;
goto returnToken;
-startString: {
- int stringQuoteCharacter = m_current;
- shift();
-
- const UChar* stringStart = currentCharacter();
- while (m_current != stringQuoteCharacter) {
- // Fast check for characters that require special handling.
- // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently
- // as possible, and lets through all common ASCII characters.
- if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
- m_buffer16.append(stringStart, currentCharacter() - stringStart);
- goto inString;
- }
- shift();
- }
- lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart);
- shift();
- m_atLineStart = false;
- m_delimited = false;
- token = STRING;
- goto returnToken;
-
-inString:
- while (m_current != stringQuoteCharacter) {
- if (m_current == '\\')
- goto inStringEscapeSequence;
- if (UNLIKELY(isLineTerminator(m_current)))
- goto returnError;
- if (UNLIKELY(m_current == -1))
- goto returnError;
- record16(m_current);
- shift();
- }
- goto doneString;
-
-inStringEscapeSequence:
- shift();
- if (m_current == 'x') {
- shift();
- if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
- int prev = m_current;
- shift();
- record16(convertHex(prev, m_current));
- shift();
- goto inString;
- }
- record16('x');
- if (m_current == stringQuoteCharacter)
- goto doneString;
- goto inString;
- }
- if (m_current == 'u') {
- shift();
- token = getUnicodeCharacter();
- if (token != -1) {
- record16(token);
- goto inString;
- }
- if (m_current == stringQuoteCharacter) {
- record16('u');
- goto doneString;
- }
- goto returnError;
- }
- if (isASCIIOctalDigit(m_current)) {
- int char1 = m_current;
- shift();
- if (char1 >= '0' && char1 <= '3' && isASCIIOctalDigit(m_current) && isASCIIOctalDigit(peek(1))) {
- int char2 = m_current;
- shift();
- record16((char1 - '0') * 64 + (char2 - '0') * 8 + m_current - '0');
- shift();
- goto inString;
- }
- if (isASCIIOctalDigit(m_current)) {
- record16((char1 - '0') * 8 + m_current - '0');
- shift();
- goto inString;
- }
- record16(char1 - '0');
- goto inString;
- }
- if (isLineTerminator(m_current)) {
- shiftLineTerminator();
- goto inString;
- }
- if (m_current == -1)
- goto returnError;
- record16(singleEscape(m_current));
- shift();
- goto inString;
-}
-
startIdentifierWithBackslash: {
shift();
if (UNLIKELY(m_current != 'u'))
goto returnError;
shift();
- token = getUnicodeCharacter();
- if (UNLIKELY(token == -1))
+ identChar = getUnicodeCharacter();
+ if (UNLIKELY(identChar == -1))
goto returnError;
- if (UNLIKELY(!isIdentStart(token)))
+ if (UNLIKELY(!isIdentStart(identChar)))
goto returnError;
goto inIdentifierAfterCharacterCheck;
}
@@ -800,13 +820,13 @@ startIdentifierOrKeyword: {
if (UNLIKELY(m_current != 'u'))
goto returnError;
shift();
- token = getUnicodeCharacter();
- if (UNLIKELY(token == -1))
+ identChar = getUnicodeCharacter();
+ if (UNLIKELY(identChar == -1))
goto returnError;
- if (UNLIKELY(!isIdentPart(token)))
+ if (UNLIKELY(!isIdentPart(identChar)))
goto returnError;
inIdentifierAfterCharacterCheck:
- record16(token);
+ record16(identChar);
while (isIdentPart(m_current)) {
record16(m_current);
@@ -818,7 +838,7 @@ inIdentifierAfterCharacterCheck:
inSingleLineComment:
while (!isLineTerminator(m_current)) {
if (UNLIKELY(m_current == -1))
- return 0;
+ return EOFTOK;
shift();
}
shiftLineTerminator();
@@ -985,7 +1005,7 @@ doneNumeric:
goto returnToken;
doneSemicolon:
- token = ';';
+ token = SEMICOLON;
m_delimited = true;
goto returnToken;
@@ -1002,34 +1022,23 @@ doneIdentifierOrKeyword: {
m_delimited = false;
m_buffer16.resize(0);
const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
- token = entry ? entry->lexerValue() : static_cast<int>(IDENT);
- goto returnToken;
-}
-
-doneString:
- // Atomize constant strings in case they're later used in property lookup.
- shift();
- m_atLineStart = false;
- m_delimited = false;
- lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
- m_buffer16.resize(0);
- token = STRING;
+ token = entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT;
// Fall through into returnToken.
+}
returnToken: {
int lineNumber = m_lineNumber;
- llocp->first_line = lineNumber;
- llocp->last_line = lineNumber;
- llocp->first_column = startOffset;
- llocp->last_column = currentOffset();
+ llocp->line = lineNumber;
+ llocp->startOffset = startOffset;
+ llocp->endOffset = currentOffset();
m_lastToken = token;
return token;
}
returnError:
m_error = true;
- return -1;
+ return ERRORTOK;
}
bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
@@ -1136,7 +1145,6 @@ bool Lexer::skipRegExp()
void Lexer::clear()
{
m_arena = 0;
- m_codeWithoutBOMs.clear();
Vector<char> newBuffer8;
m_buffer8.swap(newBuffer8);
diff --git a/JavaScriptCore/parser/Lexer.h b/JavaScriptCore/parser/Lexer.h
index ec254ce..5ab7ad7 100644
--- a/JavaScriptCore/parser/Lexer.h
+++ b/JavaScriptCore/parser/Lexer.h
@@ -23,6 +23,7 @@
#ifndef Lexer_h
#define Lexer_h
+#include "JSParser.h"
#include "Lookup.h"
#include "ParserArena.h"
#include "SourceCode.h"
@@ -49,7 +50,7 @@ namespace JSC {
void setIsReparsing() { m_isReparsing = true; }
// Functions for the parser itself.
- int lex(void* lvalp, void* llocp);
+ JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp);
int lineNumber() const { return m_lineNumber; }
void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
int lastLineNumber() const { return m_lastLineNumber; }
@@ -61,6 +62,12 @@ namespace JSC {
// Functions for use after parsing.
bool sawError() const { return m_error; }
void clear();
+ int currentOffset() { return m_code - m_codeStart; }
+ void setOffset(int offset)
+ {
+ m_code = m_codeStart + offset;
+ m_current = *m_code;
+ }
private:
friend class JSGlobalData;
@@ -86,8 +93,10 @@ namespace JSC {
ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
+ ALWAYS_INLINE bool parseString(JSTokenData* lvalp);
+
static const size_t initialReadBufferCapacity = 32;
-
+
int m_lineNumber;
int m_lastLineNumber;
@@ -113,8 +122,6 @@ namespace JSC {
JSGlobalData* m_globalData;
const HashTable m_keywordTable;
-
- Vector<UChar> m_codeWithoutBOMs;
};
inline bool Lexer::isWhiteSpace(int ch)
@@ -137,12 +144,6 @@ namespace JSC {
return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
}
- // A bridge for yacc from the C world to the C++ world.
- inline int jscyylex(void* lvalp, void* llocp, void* globalData)
- {
- return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
- }
-
} // namespace JSC
#endif // Lexer_h
diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp
index 4b97e9a..ffea524 100644
--- a/JavaScriptCore/parser/Nodes.cpp
+++ b/JavaScriptCore/parser/Nodes.cpp
@@ -98,7 +98,7 @@ ScopeNode::ScopeNode(JSGlobalData* globalData)
ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
: StatementNode(globalData)
, ParserArenaRefCounted(globalData)
- , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))
+ , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants)))
, m_features(features)
, m_source(source)
{
diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h
index 57c8f4f..6206384 100644
--- a/JavaScriptCore/parser/Nodes.h
+++ b/JavaScriptCore/parser/Nodes.h
@@ -404,12 +404,13 @@ namespace JSC {
class PropertyNode : public ParserArenaFreeable {
public:
- enum Type { Constant, Getter, Setter };
+ enum Type { Constant = 1, Getter = 2, Setter = 4 };
PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
const Identifier& name() const { return m_name; }
+ Type type() const { return m_type; }
private:
friend class PropertyListNode;
diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp
index b97754f..39ff597 100644
--- a/JavaScriptCore/parser/Parser.cpp
+++ b/JavaScriptCore/parser/Parser.cpp
@@ -60,7 +60,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena);
- int parseError = jsParse(globalData);
+ int parseError = jsParse(globalData, m_source);
int lineNumber = lexer.lineNumber();
bool lexError = lexer.sawError();
lexer.clear();
diff --git a/JavaScriptCore/parser/ParserArena.cpp b/JavaScriptCore/parser/ParserArena.cpp
index a8e8159..9c96de7 100644
--- a/JavaScriptCore/parser/ParserArena.cpp
+++ b/JavaScriptCore/parser/ParserArena.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,13 +27,14 @@
#include "ParserArena.h"
#include "Nodes.h"
+#include <wtf/PassOwnPtr.h>
namespace JSC {
ParserArena::ParserArena()
: m_freeableMemory(0)
, m_freeablePoolEnd(0)
- , m_identifierArena(new IdentifierArena)
+ , m_identifierArena(adoptPtr(new IdentifierArena))
{
}
diff --git a/JavaScriptCore/parser/SourceProvider.h b/JavaScriptCore/parser/SourceProvider.h
index 87ea960..6b9c028 100644
--- a/JavaScriptCore/parser/SourceProvider.h
+++ b/JavaScriptCore/parser/SourceProvider.h
@@ -38,6 +38,7 @@ namespace JSC {
public:
SourceProvider(const UString& url)
: m_url(url)
+ , m_validated(false)
{
}
virtual ~SourceProvider() { }
@@ -49,8 +50,12 @@ namespace JSC {
const UString& url() { return m_url; }
intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
+ bool isValid() const { return m_validated; }
+ void setValid() { m_validated = true; }
+
private:
UString m_url;
+ bool m_validated;
};
class UStringSourceProvider : public SourceProvider {
diff --git a/JavaScriptCore/parser/SyntaxChecker.h b/JavaScriptCore/parser/SyntaxChecker.h
index cad89f6..e05facd 100644
--- a/JavaScriptCore/parser/SyntaxChecker.h
+++ b/JavaScriptCore/parser/SyntaxChecker.h
@@ -29,7 +29,7 @@
namespace JSC {
class SyntaxChecker {
public:
- SyntaxChecker(JSGlobalData*, Lexer*)
+ SyntaxChecker(JSGlobalData* , Lexer*)
{
}
@@ -39,7 +39,25 @@ public:
typedef int SourceElements;
typedef int Arguments;
typedef int Comma;
- typedef int Property;
+ struct Property {
+ ALWAYS_INLINE Property(void* = 0)
+ : type((PropertyNode::Type)0)
+ {
+ }
+ ALWAYS_INLINE Property(const Identifier* ident, PropertyNode::Type ty)
+ : name(ident)
+ , type(ty)
+ {
+ }
+ ALWAYS_INLINE Property(PropertyNode::Type ty)
+ : name(0)
+ , type(ty)
+ {
+ }
+ ALWAYS_INLINE bool operator!() { return !type; }
+ const Identifier* name;
+ PropertyNode::Type type;
+ };
typedef int PropertyList;
typedef int ElementList;
typedef int ArgumentsList;
@@ -90,10 +108,21 @@ public:
int createArguments(int) { return 1; }
int createArgumentsList(int) { return 1; }
int createArgumentsList(int, int) { return 1; }
- int createProperty(const Identifier*, int, PropertyNode::Type) { return 1; }
- int createProperty(double, int, PropertyNode::Type) { return 1; }
- int createPropertyList(int) { return 1; }
- int createPropertyList(int, int) { return 1; }
+ template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type)
+ {
+ ASSERT(name);
+ if (!complete)
+ return Property(type);
+ return Property(name, type);
+ }
+ template <bool complete> Property createProperty(JSGlobalData* globalData, double name, int, PropertyNode::Type type)
+ {
+ if (!complete)
+ return Property(type);
+ return Property(&globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name), type);
+ }
+ int createPropertyList(Property) { return 1; }
+ int createPropertyList(Property, int) { return 1; }
int createElementList(int, int) { return 1; }
int createElementList(int, int, int) { return 1; }
int createFormalParameterList(const Identifier&) { return 1; }
@@ -127,7 +156,13 @@ public:
int createDebugger(int, int) { return 1; }
int createConstStatement(int, int, int) { return 1; }
int appendConstDecl(int, const Identifier*, int) { return 1; }
- int createGetterOrSetterProperty(const Identifier*, const Identifier*, int, int, int, int, int, int) { return 1; }
+ template <bool strict> Property createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int)
+ {
+ ASSERT(name);
+ if (!strict)
+ return Property(type);
+ return Property(name, type);
+ }
void appendStatement(int, int) { }
void addVar(const Identifier*, bool) { }
@@ -151,6 +186,8 @@ public:
void assignmentStackAppend(int, int, int, int, int, Operator) { }
int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; }
+ const Identifier& getName(const Property& property) { ASSERT(property.name); return *property.name; }
+ PropertyNode::Type getType(const Property& property) { return property.type; }
};
}