Commit 9b94d12f authored by marja@chromium.org's avatar marja@chromium.org

Move ParseBinaryExpression to ParserBase.

R=mstarzinger@chromium.org
BUG=v8:3126
LOG=N

Review URL: https://codereview.chromium.org/196933005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19997 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a868a74c
......@@ -478,6 +478,66 @@ void ParserTraits::CheckStrictModeLValue(Expression* expression,
}
bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
Expression** x, Expression* y, Token::Value op, int pos,
AstNodeFactory<AstConstructionVisitor>* factory) {
if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() &&
y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
double x_val = (*x)->AsLiteral()->value()->Number();
double y_val = y->AsLiteral()->value()->Number();
switch (op) {
case Token::ADD:
*x = factory->NewNumberLiteral(x_val + y_val, pos);
return true;
case Token::SUB:
*x = factory->NewNumberLiteral(x_val - y_val, pos);
return true;
case Token::MUL:
*x = factory->NewNumberLiteral(x_val * y_val, pos);
return true;
case Token::DIV:
*x = factory->NewNumberLiteral(x_val / y_val, pos);
return true;
case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos);
return true;
}
case Token::BIT_AND: {
int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos);
return true;
}
case Token::BIT_XOR: {
int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
*x = factory->NewNumberLiteral(value, pos);
return true;
}
case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
*x = factory->NewNumberLiteral(value, pos);
return true;
}
case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift;
*x = factory->NewNumberLiteral(value, pos);
return true;
}
case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
*x = factory->NewNumberLiteral(value, pos);
return true;
}
default:
break;
}
}
return false;
}
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<const char*> args,
......@@ -633,9 +693,8 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
}
Expression* ParserTraits::ParseBinaryExpression(int prec, bool accept_IN,
bool* ok) {
return parser_->ParseBinaryExpression(prec, accept_IN, ok);
Expression* ParserTraits::ParseUnaryExpression(bool* ok) {
return parser_->ParseUnaryExpression(ok);
}
......@@ -2923,100 +2982,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
}
// Precedence >= 4
Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
ASSERT(prec >= 4);
Expression* x = ParseUnaryExpression(CHECK_OK);
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) {
Token::Value op = Next();
int pos = position();
Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
// Compute some expressions involving only number literals.
if (x && x->AsLiteral() && x->AsLiteral()->value()->IsNumber() &&
y && y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
double x_val = x->AsLiteral()->value()->Number();
double y_val = y->AsLiteral()->value()->Number();
switch (op) {
case Token::ADD:
x = factory()->NewNumberLiteral(x_val + y_val, pos);
continue;
case Token::SUB:
x = factory()->NewNumberLiteral(x_val - y_val, pos);
continue;
case Token::MUL:
x = factory()->NewNumberLiteral(x_val * y_val, pos);
continue;
case Token::DIV:
x = factory()->NewNumberLiteral(x_val / y_val, pos);
continue;
case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
x = factory()->NewNumberLiteral(value, pos);
continue;
}
case Token::BIT_AND: {
int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
x = factory()->NewNumberLiteral(value, pos);
continue;
}
case Token::BIT_XOR: {
int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
x = factory()->NewNumberLiteral(value, pos);
continue;
}
case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
x = factory()->NewNumberLiteral(value, pos);
continue;
}
case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift;
x = factory()->NewNumberLiteral(value, pos);
continue;
}
case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
x = factory()->NewNumberLiteral(value, pos);
continue;
}
default:
break;
}
}
// For now we distinguish between comparisons and other binary
// operations. (We could combine the two and get rid of this
// code and AST node eventually.)
if (Token::IsCompareOp(op)) {
// We have a comparison.
Token::Value cmp = op;
switch (op) {
case Token::NE: cmp = Token::EQ; break;
case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
default: break;
}
x = factory()->NewCompareOperation(cmp, x, y, pos);
if (cmp != op) {
// The comparison was negated - add a NOT.
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
} else {
// We have a "normal" binary operation.
x = factory()->NewBinaryOperation(op, x, y, pos);
}
}
}
return x;
}
Expression* Parser::ParseUnaryExpression(bool* ok) {
// UnaryExpression ::
// PostfixExpression
......
......@@ -498,6 +498,13 @@ class ParserTraits {
// in strict mode.
void CheckStrictModeLValue(Expression*expression, bool* ok);
// Returns true if we have a binary expression between two numeric
// literals. In that case, *x will be changed to an expression which is the
// computed value.
bool ShortcutNumericLiteralBinaryExpression(
Expression** x, Expression* y, Token::Value op, int pos,
AstNodeFactory<AstConstructionVisitor>* factory);
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
const char* message,
......@@ -561,7 +568,7 @@ class ParserTraits {
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok);
Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
Expression* ParseUnaryExpression(bool* ok);
private:
Parser* parser_;
......@@ -704,7 +711,6 @@ class Parser : public ParserBase<ParserTraits> {
// Support for hamony block scoped bindings.
Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
Expression* ParseUnaryExpression(bool* ok);
Expression* ParsePostfixExpression(bool* ok);
Expression* ParseLeftHandSideExpression(bool* ok);
......
......@@ -146,10 +146,8 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral(
}
PreParserExpression PreParserTraits::ParseBinaryExpression(int prec,
bool accept_IN,
bool* ok) {
return pre_parser_->ParseBinaryExpression(prec, accept_IN, ok);
PreParserExpression PreParserTraits::ParseUnaryExpression(bool* ok) {
return pre_parser_->ParseUnaryExpression(ok);
}
......@@ -844,23 +842,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
#undef DUMMY
// Precedence >= 4
PreParser::Expression PreParser::ParseBinaryExpression(int prec,
bool accept_IN,
bool* ok) {
Expression result = ParseUnaryExpression(CHECK_OK);
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) {
Next();
ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
result = Expression::Default();
}
}
return result;
}
PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
// UnaryExpression ::
// PostfixExpression
......
......@@ -390,6 +390,9 @@ class ParserBase : public Traits {
typename Traits::Type::Expression ParseYieldExpression(bool* ok);
typename Traits::Type::Expression ParseConditionalExpression(bool accept_IN,
bool* ok);
typename Traits::Type::Expression ParseBinaryExpression(int prec,
bool accept_IN,
bool* ok);
// Used to detect duplicates in object literals. Each of the values
// kGetterProperty, kSetterProperty and kValueProperty represents
......@@ -663,11 +666,21 @@ class PreParserFactory {
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewUnaryOperation(Token::Value op,
PreParserExpression expression,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewBinaryOperation(Token::Value op,
PreParserExpression left,
PreParserExpression right, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewCompareOperation(Token::Value op,
PreParserExpression left,
PreParserExpression right, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewArrayLiteral(PreParserExpressionList values,
int literal_index,
int pos) {
......@@ -818,6 +831,13 @@ class PreParserTraits {
// in strict mode.
void CheckStrictModeLValue(PreParserExpression expression, bool* ok);
bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
PreParserExpression y,
Token::Value op,
int pos,
PreParserFactory* factory) {
return false;
}
// Reporting errors.
void ReportMessageAt(Scanner::Location location,
......@@ -900,7 +920,7 @@ class PreParserTraits {
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok);
PreParserExpression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
PreParserExpression ParseUnaryExpression(bool* ok);
private:
PreParser* pre_parser_;
......@@ -1066,7 +1086,6 @@ class PreParser : public ParserBase<PreParserTraits> {
Statement ParseTryStatement(bool* ok);
Statement ParseDebuggerStatement(bool* ok);
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
Expression ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
Expression ParseUnaryExpression(bool* ok);
Expression ParsePostfixExpression(bool* ok);
Expression ParseLeftHandSideExpression(bool* ok);
......@@ -1729,6 +1748,52 @@ ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, bool* ok) {
}
// Precedence >= 4
template <class Traits>
typename Traits::Type::Expression
ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
ASSERT(prec >= 4);
typename Traits::Type::Expression x = this->ParseUnaryExpression(CHECK_OK);
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4
while (Precedence(peek(), accept_IN) == prec1) {
Token::Value op = Next();
int pos = position();
typename Traits::Type::Expression y =
ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
factory())) {
continue;
}
// For now we distinguish between comparisons and other binary
// operations. (We could combine the two and get rid of this
// code and AST node eventually.)
if (Token::IsCompareOp(op)) {
// We have a comparison.
Token::Value cmp = op;
switch (op) {
case Token::NE: cmp = Token::EQ; break;
case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
default: break;
}
x = factory()->NewCompareOperation(cmp, x, y, pos);
if (cmp != op) {
// The comparison was negated - add a NOT.
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
} else {
// We have a "normal" binary operation.
x = factory()->NewBinaryOperation(op, x, y, pos);
}
}
}
return x;
}
#undef CHECK_OK
#undef CHECK_OK_CUSTOM
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment