/**********************************************************************
Copyright (c) 2008 Erik Bengtson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
...
**********************************************************************/
package org.jpox.query.expression;
import java.util.ArrayList;
import java.util.List;
import org.jpox.query.node.Node;
import org.jpox.query.symbol.SymbolTable;
public class ExpressionCompiler
{
SymbolTable symtbl;
public void setSymbolTable(SymbolTable symtbl)
{
this.symtbl = symtbl;
}
public Expression compileOrderExpression(Node node)
{
if (isOperator(node, "order"))
{
if( node.getChildNodes().size()>1)
{
return new OrderExpression(symtbl, compileExpression(node.getFirstChild()),(String)node.getNextChild().getNodeValue());
}
if( node.getChildNodes().size()==1)
{
return new OrderExpression(symtbl, compileExpression(node.getFirstChild()));
}
}
return compileExpression(node.getFirstChild());
}
public Expression compileExpression(Node node)
{
return compileConditionalOrExpression(node);
}
/**
* This method deals with the AND condition
* A condition specifies a combination of one or more expressions and
* logical (Boolean) operators and returns a value of TRUE, FALSE, or
* unknown
*/
private Expression compileConditionalOrExpression(Node node)
{
if (isOperator(node, "||"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_OR,right);
}
return compileConditionalAndExpression(node);
}
/**
* This method deals with the AND condition
* A condition specifies a combination of one or more expressions and
* logical (Boolean) operators and returns a value of TRUE, FALSE, or
* unknown
*/
private Expression compileConditionalAndExpression(Node node)
{
if (isOperator(node, "&&"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_AND,right);
}
return compileInclusiveOrExpression(node);
}
private Expression compileInclusiveOrExpression(Node node)
{
if (isOperator(node, "|"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_OR,right);
}
return compileExclusiveOrExpression(node);
}
private Expression compileExclusiveOrExpression(Node node)
{
if (isOperator(node, "^"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_OR,right);
}
return compileAndExpression(node);
}
private Expression compileAndExpression(Node node)
{
if (isOperator(node, "&"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_AND,right);
}
return compileEqualityExpression(node);
}
private Expression compileEqualityExpression(Node node)
{
if (isOperator(node, "=="))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_EQ,right);
}
else if (isOperator(node, "!="))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_NOTEQ,right);
}
return compileRelationalExpression(node);
}
private Expression compileRelationalExpression(Node node)
{
if (isOperator(node, "<="))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_LTEQ,right);
}
else if (isOperator(node, ">="))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_GTEQ,right);
}
else if (isOperator(node, "<"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_LT,right);
}
else if (isOperator(node, ">"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_GT,right);
}
else if (isOperator(node, "instanceof"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_IS,right);
}
return compileAdditiveExpression(node);
}
private Expression compileAdditiveExpression(Node node)
{
if (isOperator(node, "+"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_ADD,right);
}
else if (isOperator(node, "-"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_SUB,right);
}
return compileMultiplicativeExpression(node);
}
private Expression compileMultiplicativeExpression(Node node)
{
if (isOperator(node, "*"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_MUL,right);
}
else if (isOperator(node, "/"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_DIV,right);
}
else if (isOperator(node, "%"))
{
Expression left = compileExpression(node.getFirstChild());
Expression right = compileExpression(node.getNextChild());
return new DyadicExpression(left,Expression.OP_MOD,right);
}
return compileUnaryExpression(node);
}
private Expression compileUnaryExpression(Node node)
{
return compileUnaryExpressionNotPlusMinus(node);
}
private Expression compileUnaryExpressionNotPlusMinus(Node node)
{
if (isOperator(node, "~"))
{
Expression left = compileExpression(node.getFirstChild());
return new DyadicExpression(Expression.OP_COM,left);
}
else if (isOperator(node, "!"))
{
Expression left = compileExpression(node.getFirstChild());
return new DyadicExpression(Expression.OP_NOT,left);
}
return compilePrimaryExpression(node);
}
private Expression compilePrimaryExpression(Node node)
{
if( node.getNodeType() == Node.IDENTIFIER)
{
Node currentNode = node;
List tupple = new ArrayList();
List parameterExprs = new ArrayList();
boolean method = false;
while( currentNode != null)
{
tupple.add(currentNode.getNodeValue());
if( currentNode.getNodeType() == Node.INVOKE )
{
method = true;
break;
}
currentNode = currentNode.getFirstChild();
}
while( method && currentNode.hasNextChild())
{
parameterExprs.add(compileExpression(currentNode.getNextChild()));
}
if( method)
{
return new InvokeExpression(symtbl, tupple,parameterExprs);
}
return new PrimaryExpression(symtbl, tupple,parameterExprs);
}
else if( node.getNodeType() == Node.INVOKE)
{
Node currentNode = node;
List tupple = new ArrayList();
List parameterExprs = new ArrayList();
boolean method = false;
while( currentNode != null)
{
tupple.add(currentNode.getNodeValue());
if( currentNode.getNodeType() == Node.INVOKE )
{
method = true;
break;
}
currentNode = currentNode.getFirstChild();
}
while( method && currentNode.hasNextChild())
{
parameterExprs.add(compileExpression(currentNode.getNextChild()));
}
return new InvokeExpression(symtbl, tupple,parameterExprs);
}
else if( node.getNodeType() == Node.CREATOR)
{
Node currentNode = node.getFirstChild();
List tupple = new ArrayList();
List parameterExprs = new ArrayList();
boolean method = false;
while( currentNode != null)
{
tupple.add(currentNode.getNodeValue());
if( currentNode.getNodeType() == Node.INVOKE )
{
method = true;
break;
}
currentNode = currentNode.getFirstChild();
}
while( method && currentNode.hasNextChild())
{
parameterExprs.add(compileExpression(currentNode.getNextChild()));
}
return new CreatorExpression(symtbl, tupple,parameterExprs);
}
else if( node.getNodeType() == Node.LITERAL)
{
return new Literal(node.getNodeValue());
}
return null;
}
private boolean isOperator(Node node, String operator)
{
return node.getNodeType() == Node.OPERATOR && node.getNodeValue().equals(operator);
}
}