com.google.dart.compiler.backend.js.JsPrecedenceVisitor Maven / Gradle / Ivy
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
/**
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
* 57)
*
* Precedence 17 is for indivisible primaries that either don't have children,
* or provide their own delimiters.
*
* Precedence 16 is for really important things that have their own AST classes.
*
* Precedence 15 is for the new construct.
*
* Precedence 14 is for unary operators.
*
* Precedences 12 through 4 are for non-assigning binary operators.
*
* Precedence 3 is for the tertiary conditional.
*
* Precedence 2 is for assignments.
*
* Precedence 1 is for comma operations.
*/
class JsPrecedenceVisitor extends JsVisitor {
static final int PRECEDENCE_NEW = 15;
private int answer = -1;
private JsPrecedenceVisitor() {
}
public static int exec(JsExpression expression) {
JsPrecedenceVisitor visitor = new JsPrecedenceVisitor();
visitor.accept(expression);
if (visitor.answer < 0) {
throw new RuntimeException("Precedence must be >= 0!");
}
return visitor.answer;
}
@Override
public void visitArrayAccess(@NotNull JsArrayAccess x) {
answer = 16;
}
@Override
public void visitArray(@NotNull JsArrayLiteral x) {
answer = 17; // primary
}
@Override
public void visitBinaryExpression(@NotNull JsBinaryOperation x) {
answer = x.getOperator().getPrecedence();
}
@Override
public void visitBoolean(@NotNull JsLiteral.JsBooleanLiteral x) {
answer = 17; // primary
}
@Override
public void visitConditional(@NotNull JsConditional x) {
answer = 3;
}
@Override
public void visitFunction(@NotNull JsFunction x) {
answer = 17; // primary
}
@Override
public void visitInvocation(@NotNull JsInvocation invocation) {
answer = 16;
}
@Override
public void visitNameRef(@NotNull JsNameRef nameRef) {
if (nameRef.isLeaf()) {
answer = 17; // primary
}
else {
answer = 16; // property access
}
}
@Override
public void visitNew(@NotNull JsNew x) {
answer = PRECEDENCE_NEW;
}
@Override
public void visitNull(@NotNull JsNullLiteral x) {
answer = 17; // primary
}
@Override
public void visitInt(@NotNull JsNumberLiteral.JsIntLiteral x) {
answer = 17; // primary
}
@Override
public void visitDouble(@NotNull JsNumberLiteral.JsDoubleLiteral x) {
answer = 17; // primary
}
@Override
public void visitObjectLiteral(@NotNull JsObjectLiteral x) {
answer = 17; // primary
}
@Override
public void visitPostfixOperation(@NotNull JsPostfixOperation x) {
answer = x.getOperator().getPrecedence();
}
@Override
public void visitPrefixOperation(@NotNull JsPrefixOperation x) {
answer = x.getOperator().getPrecedence();
}
@Override
public void visitPropertyInitializer(@NotNull JsPropertyInitializer x) {
answer = 17; // primary
}
@Override
public void visitRegExp(@NotNull JsRegExp x) {
answer = 17; // primary
}
@Override
public void visitString(@NotNull JsStringLiteral x) {
answer = 17; // primary
}
@Override
public void visitThis(@NotNull JsLiteral.JsThisRef x) {
answer = 17; // primary
}
@Override
protected void visitElement(@NotNull JsNode node) {
throw new RuntimeException("Only expressions have precedence.");
}
}