/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package lux.xpath;
import lux.xml.ValueType;
public class BinaryOperation extends AbstractExpression {
private static final int MLT = 1;
private static final int MEQ = 2;
private static final int MGT = 4;
private static final int MAND = 8;
private static final int MOR = 16; // OR >= (AND,OR)
private static final int MINTERSECT = 32;
private static final int MUNION = 64;
private static final int MEXCEPT = 128;
private final Operator operator;
public enum Operator {
// boolean operators
AND("and", ValueType.BOOLEAN, 5, MAND),
OR("or", ValueType.BOOLEAN, 4, MAND | MOR),
// set operators
INTERSECT("intersect", ValueType.VALUE, 11, MINTERSECT),
EXCEPT("except", ValueType.VALUE, 11, MEXCEPT),
UNION("|", ValueType.VALUE, 10, MUNION | MEXCEPT | MINTERSECT),
// arithmetic operators
ADD("+", ValueType.ATOMIC, 8),
SUB("-", ValueType.ATOMIC, 8),
MUL("*", ValueType.ATOMIC, 9),
DIV("div", ValueType.ATOMIC, 9),
IDIV("idiv", ValueType.ATOMIC, 9),
MOD("mod", ValueType.ATOMIC, 9),
// general comparisons
EQUALS("=", ValueType.BOOLEAN, 6, MEQ),
NE("!=", ValueType.BOOLEAN, 6, MGT | MLT),
LT("<", ValueType.BOOLEAN, 6, MLT),
LE("<=", ValueType.BOOLEAN, 6, MLT | MEQ),
GT(">", ValueType.BOOLEAN, 6, MGT),
GE(">=", ValueType.BOOLEAN, 6, MGT | MEQ),
// atomic comparisons
AEQ("eq", ValueType.BOOLEAN, 6, MEQ),
ANE("ne", ValueType.BOOLEAN, 6, MLT | MGT),
ALT("lt", ValueType.BOOLEAN, 6, MLT),
ALE("le", ValueType.BOOLEAN, 6, MLT | MEQ),
AGT("gt", ValueType.BOOLEAN, 6, MGT),
AGE("ge", ValueType.BOOLEAN, 6, MGT | MEQ),
// node operators
IS("is", ValueType.BOOLEAN, 6),
BEFORE("<<", ValueType.BOOLEAN, 6),
AFTER(">>", ValueType.BOOLEAN, 6),
TO("to", ValueType.ATOMIC, 7);
private String token;
private ValueType resultType;
private int precedence;
private int rangeMask;
Operator (String token, ValueType resultType, int precedence) {
this (token, resultType, precedence, 0);
}
Operator (String token, ValueType resultType, int precedence, int rangeMask) {
this.token = token;
this.resultType = resultType;
this.precedence = precedence;
}
@Override
public String toString () {
return token;
}
public ValueType getResultType () {
return resultType;
}
public int getPrecedence() {
return precedence;
}
};
public BinaryOperation (AbstractExpression op1, Operator operator, AbstractExpression op2) {
super (Type.BINARY_OPERATION);
setSubs (op1, op2);
this.operator = operator;
}
@Override
public void toString (StringBuilder buf) {
appendSub(buf, subs[0]);
buf.append(' ').append(operator).append(' ');
appendSub(buf, subs[1]);
}
public AbstractExpression getOperand1() {
return subs[0];
}
public AbstractExpression getOperand2() {
return subs[1];
}
public Operator getOperator () {
return operator;
}
@Override
public AbstractExpression accept(ExpressionVisitor visitor) {
super.acceptSubs(visitor);
return visitor.visit(this);
}
@Override
public boolean isDocumentOrdered () {
return operator.getResultType().isNode && super.isDocumentOrdered();
}
@Override
public int getPrecedence () {
return operator.precedence;
}
@Override
protected boolean propEquals (AbstractExpression other) {
return operator == ((BinaryOperation)other).operator;
}
@Override
public boolean propGreaterEqual (AbstractExpression other) {
Operator op2 = ((BinaryOperation)other).operator;
// GE >= AGE, is AGE >= GE?
return operator == op2 ||
(op2.rangeMask != 0 && (operator.rangeMask & op2.rangeMask) == op2.rangeMask);
}
@Override
public int equivHash () {
return 13 + operator.ordinal();
}
@Override
public boolean isRestrictive () {
return (operator == Operator.AND || operator == Operator.INTERSECT);
}
}
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */