001    // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
002    // for details. All rights reserved. Use of this source code is governed by a
003    // BSD-style license that can be found in the LICENSE file.
004    
005    package org.jetbrains.kotlin.js.backend.ast;
006    
007    /**
008     * Represents the operator in a JavaScript binary operation.
009     */
010    public enum JsBinaryOperator implements JsOperator {
011      /*
012       * Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
013       * (page 57)
014       *
015       *
016       * Precedence 15 is for really important things that have their own AST
017       * classes.
018       *
019       * Precedence 14 is for unary operators.
020       */
021    
022      MUL("*", 13, LEFT | INFIX), DIV("/", 13, LEFT | INFIX), MOD("%", 13, LEFT
023          | INFIX),
024    
025      ADD("+", 12, LEFT | INFIX), SUB("-", 12, LEFT | INFIX),
026    
027      SHL("<<", 11, LEFT | INFIX), SHR(">>", 11, LEFT | INFIX), SHRU(">>>", 11,
028          LEFT | INFIX),
029    
030      LT("<", 10, LEFT | INFIX), LTE("<=", 10, LEFT | INFIX), GT(">", 10, LEFT
031          | INFIX), GTE(">=", 10, LEFT | INFIX), INSTANCEOF("instanceof", 10, LEFT
032          | INFIX), INOP("in", 10, LEFT | INFIX),
033    
034      EQ("==", 9, LEFT | INFIX), NEQ("!=", 9, LEFT | INFIX), REF_EQ("===", 9, LEFT
035          | INFIX), REF_NEQ("!==", 9, LEFT | INFIX),
036    
037      BIT_AND("&", 8, LEFT | INFIX),
038    
039      BIT_XOR("^", 7, LEFT | INFIX),
040    
041      BIT_OR("|", 6, LEFT | INFIX),
042    
043      AND("&&", 5, LEFT | INFIX),
044    
045      OR("||", 4, LEFT | INFIX),
046    
047      // Precedence 3 is for the condition operator.
048    
049      // These assignment operators are right-associative.
050      ASG("=", 2, INFIX), ASG_ADD("+=", 2, INFIX), ASG_SUB("-=", 2, INFIX), ASG_MUL(
051          "*=", 2, INFIX), ASG_DIV("/=", 2, INFIX), ASG_MOD("%=", 2, INFIX), ASG_SHL(
052          "<<=", 2, INFIX), ASG_SHR(">>=", 2, INFIX), ASG_SHRU(">>>=", 2, INFIX), ASG_BIT_AND(
053          "&=", 2, INFIX), ASG_BIT_OR("|=", 2, INFIX), ASG_BIT_XOR("^=", 2, INFIX),
054    
055      COMMA(",", 1, LEFT | INFIX);
056    
057      private final int mask;
058      private final int precedence;
059      private final String symbol;
060    
061      private JsBinaryOperator(String symbol, int precedence, int mask) {
062        this.symbol = symbol;
063        this.precedence = precedence;
064        this.mask = mask;
065      }
066    
067      @Override
068      public int getPrecedence() {
069        return precedence;
070      }
071    
072      @Override
073      public String getSymbol() {
074        return symbol;
075      }
076    
077      public boolean isAssignment() {
078        return getPrecedence() == ASG.getPrecedence();
079      }
080    
081      @Override
082      public boolean isKeyword() {
083        return this == INSTANCEOF || this == INOP;
084      }
085    
086      @Override
087      public boolean isLeftAssociative() {
088        return (mask & LEFT) != 0;
089      }
090    
091      @Override
092      public boolean isPrecedenceLessThan(JsOperator other) {
093        return precedence < other.getPrecedence();
094      }
095    
096      @Override
097      public boolean isValidInfix() {
098        return (mask & INFIX) != 0;
099      }
100    
101      @Override
102      public boolean isValidPostfix() {
103        return (mask & POSTFIX) != 0;
104      }
105    
106      @Override
107      public boolean isValidPrefix() {
108        return (mask & PREFIX) != 0;
109      }
110    
111      @Override
112      public String toString() {
113        return symbol;
114      }
115    }