/*
* JBoss, Home of Professional Open Source
* Copyright 2008-10 Red Hat and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
* @authors Andrew Dinn
*/
package org.jboss.byteman.rule.expression;
import org.jboss.byteman.rule.type.Type;
import org.jboss.byteman.rule.Rule;
import org.jboss.byteman.rule.grammar.ParseNode;
import java.io.StringWriter;
/**
* generic operator expression subsumes unary, binary and ternary operators
*/
public abstract class OperExpression extends Expression
{
OperExpression(Rule rule, int oper, Type type, ParseNode token)
{
super(rule, type, token);
this.oper = oper;
}
protected int oper;
/**
* return the operand with the given index or null if the index is out of range
* @param index the index
* @return the operand with the given index
*/
public abstract Expression getOperand(int index);
public void writeTo(StringWriter stringWriter) {
if ((oper & UNARY) != 0) {
stringWriter.write(getOperandString());
stringWriter.write("(");
getOperand(0).writeTo(stringWriter);
stringWriter.write(")");
} else if ((oper & BINARY) != 0) {
stringWriter.write("(");
getOperand(0).writeTo(stringWriter);
stringWriter.write(" ");
stringWriter.write(getOperandString());
stringWriter.write(" ");
getOperand(1).writeTo(stringWriter);
stringWriter.write(")");
} else if (oper == COND) {
// we only have one ternary operator
stringWriter.write("(");
getOperand(0).writeTo(stringWriter);
stringWriter.write(" ? ");
getOperand(1).writeTo(stringWriter);
stringWriter.write(" : ");
getOperand(2).writeTo(stringWriter);
stringWriter.write(")");
} else {
stringWriter.write("*** error unknown operator *** " + oper);
}
}
private String getOperandString()
{
for (int i = 0; i < operands.length; i++)
{
if (operands[i] == oper) {
return operandNames[i];
}
}
return "*** error unknown operator ***";
}
public static int convertOper(int parserOper)
{
for (int i = 0; i < parserOperands.length; i++) {
if (parserOperands[i] == parserOper) {
return operands[i];
}
}
return -1;
}
final public static int UNARY = 0x1000;
final public static int BINARY = 0x2000;
final public static int TERNARY = 0x4000;
final public static int NOT = 0x0010 | UNARY;
final public static int TWIDDLE = 0x0020 | UNARY;
final public static int OR = 0x0040 | BINARY;
final public static int AND = 0x0041 | BINARY;
final public static int EQ = 0x0080 | BINARY;
final public static int NE = 0x0081 | BINARY;
final public static int GT = 0x0082 | BINARY;
final public static int LT = 0x0083 | BINARY;
final public static int GE = 0x0084 | BINARY;
final public static int LE = 0x0085 | BINARY;
final public static int BOR = 0x0100 | BINARY;
final public static int BAND = 0x0101 | BINARY;
final public static int BXOR = 0x0102 | BINARY;
final public static int URSH = 0x0103 | BINARY;
final public static int RSH = 0x0104 | BINARY;
final public static int LSH = 0x0105 | BINARY;
final public static int UMINUS = 0x0200 | UNARY;
final public static int MUL = 0x0201 | BINARY;
final public static int DIV = 0x0202 | BINARY;
final public static int PLUS = 0x0203| BINARY;
final public static int MINUS = 0x0204 | BINARY;
final public static int MOD = 0x0205 | BINARY;
final public static int ASSIGN = 0x0401 | BINARY;
final public static int COND = 0x0800 | TERNARY;
final private static int[] operands = {
NOT,
TWIDDLE,
OR,
AND,
EQ,
NE,
GT,
LT,
GE,
LE,
BOR,
BAND,
BXOR,
URSH,
RSH,
LSH,
UMINUS,
MUL,
DIV,
PLUS,
MINUS,
MOD,
ASSIGN,
COND,
};
/* parser operands are not allocated rationally so we convert using this table */
final private static int[] parserOperands = {
org.jboss.byteman.rule.grammar.ParseNode.NOT,
org.jboss.byteman.rule.grammar.ParseNode.TWIDDLE,
org.jboss.byteman.rule.grammar.ParseNode.OR,
org.jboss.byteman.rule.grammar.ParseNode.AND,
org.jboss.byteman.rule.grammar.ParseNode.EQ,
org.jboss.byteman.rule.grammar.ParseNode.NE,
org.jboss.byteman.rule.grammar.ParseNode.GT,
org.jboss.byteman.rule.grammar.ParseNode.LT,
org.jboss.byteman.rule.grammar.ParseNode.GE,
org.jboss.byteman.rule.grammar.ParseNode.LE,
org.jboss.byteman.rule.grammar.ParseNode.BOR,
org.jboss.byteman.rule.grammar.ParseNode.BAND,
org.jboss.byteman.rule.grammar.ParseNode.BXOR,
org.jboss.byteman.rule.grammar.ParseNode.URSH,
org.jboss.byteman.rule.grammar.ParseNode.RSH,
org.jboss.byteman.rule.grammar.ParseNode.LSH,
org.jboss.byteman.rule.grammar.ParseNode.UMINUS,
org.jboss.byteman.rule.grammar.ParseNode.MUL,
org.jboss.byteman.rule.grammar.ParseNode.DIV,
org.jboss.byteman.rule.grammar.ParseNode.PLUS,
org.jboss.byteman.rule.grammar.ParseNode.MINUS,
org.jboss.byteman.rule.grammar.ParseNode.MOD,
org.jboss.byteman.rule.grammar.ParseNode.ASSIGN,
org.jboss.byteman.rule.grammar.ParseNode.TERNOP
};
final private static String[] operandNames = {
"!",
"~",
"||",
"&&",
"==",
"!=",
">",
"<",
">=",
"<=",
"|",
"&",
"^",
">>>",
">>",
"<<",
"-",
"*",
"/",
"+",
"-",
"%",
"=",
"? :"
};
}