/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.letparser;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
/*
* Created on 4 janv. 2006 by sguerin
*
* Flexo Application Suite
* (c) Denali 2003-2005
*/
public class Expression extends Token {
private Operator _operator;
private Token _leftOperand;
private Token _rightOperand;
public Expression(Operator operator, ListOfToken left, ListOfToken right) throws ParseException {
this(operator, makeOperand(left), makeOperand(right));
}
public Expression(Operator operator, Token left, Token right) {
super();
_operator = operator;
_leftOperand = left;
_rightOperand = right;
}
private static Token makeOperand(ListOfToken listOfToken) throws ParseException {
if (listOfToken.size() == 0) {
throw new ParseException("Syntax error: invalid null operand");
} else if (listOfToken.size() == 1) {
if (listOfToken.firstElement() instanceof Token) {
return (Token) listOfToken.firstElement();
}
if (listOfToken.firstElement() instanceof ListOfToken) {
return makeOperand((ListOfToken) listOfToken.firstElement());
} else {
throw new ParseException("Syntax error: invalid operand");
}
}
else {
try {
// System.out.println("TRYING TO DECODE AS EXPRESSION: "+listOfToken);
return makeExpression(listOfToken);
} catch (ParseException e) {
// System.out.println("FAILED TO EXPRESS AS AN EXPRESSION: "+listOfToken);
// e.printStackTrace();
// System.out.println("TRY AS FUNCTION: "+listOfToken);
return Function.makeFunction(listOfToken);
}
}
}
public Token getLeftOperand() {
return _leftOperand;
}
public Operator getOperator() {
return _operator;
}
public Token getRightOperand() {
return _rightOperand;
}
@Override
public String toString() {
return "(" + _leftOperand + _operator + _rightOperand + ")";
}
@Override
public String getSerializationValue() {
return "(" + _leftOperand.getSerializationValue() + " " + _operator.getSymbol() + " " + _rightOperand.getSerializationValue() + ")";
}
protected static Expression makeExpression(ListOfToken aListOfTokens) throws ParseException {
if (aListOfTokens.size() == 1 && aListOfTokens.firstElement() instanceof ListOfToken) {
return makeExpression((ListOfToken) aListOfTokens.firstElement());
} else {
// On y va, ca rigole plus
// Reduce functions first
ListOfToken functionsReducedParamList = new ListOfToken();
for (int i = 0; i < aListOfTokens.size(); i++) {
AbstractToken tok = aListOfTokens.elementAt(i);
if (tok instanceof Word && i + 1 < aListOfTokens.size() && aListOfTokens.elementAt(i + 1) instanceof ListOfToken) {
ListOfToken tryToBuildFunction = new ListOfToken();
tryToBuildFunction.add(tok);
tryToBuildFunction.add(aListOfTokens.elementAt(i + 1));
functionsReducedParamList.add(tryToBuildFunction);
i++;
} else {
functionsReducedParamList.add(tok);
}
}
ListOfToken unparsedList = functionsReducedParamList;
Vector<IndexedOperator> allOperators = new Vector<IndexedOperator>();
for (int i = 0; i < unparsedList.size(); i++) {
if (i % 2 != 0) {
// Impair: must be an operator
if (!(unparsedList.elementAt(i) instanceof Operator)) {
throw new ParseException("Syntax error near " + unparsedList.elementAt(i));
} else {
IndexedOperator toAdd = new IndexedOperator();
toAdd.operator = (Operator) unparsedList.elementAt(i);
toAdd.index = i;
allOperators.insertElementAt(toAdd, 0);
}
}
}
Collections.sort(allOperators, new Comparator<IndexedOperator>() {
@Override
public int compare(IndexedOperator o1, IndexedOperator o2) {
return o2.operator.getPriority() - o1.operator.getPriority();
}
});
// System.out.println ("sorted operators = "+allOperators);
if (allOperators.size() == 0) {
throw new ParseException("Syntax error: no operator found");
}
IndexedOperator pivot = allOperators.firstElement();
ListOfToken left = new ListOfToken();
for (int i = 0; i < pivot.index; i++) {
left.add(unparsedList.elementAt(i));
}
ListOfToken right = new ListOfToken();
for (int i = pivot.index + 1; i < unparsedList.size(); i++) {
right.add(unparsedList.elementAt(i));
}
return new Expression(pivot.operator, left, right);
}
}
protected static class IndexedOperator {
protected int index;
protected Operator operator;
@Override
public String toString() {
return "(" + index + "," + operator + ")";
}
}
}