/*
* (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.antar.expr.oldparser;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
import org.openflexo.antar.expr.BinaryOperator;
import org.openflexo.antar.expr.UnaryOperator;
/*
* Created on 4 janv. 2006 by sguerin
*
* Flexo Application Suite
* (c) Denali 2003-2005
*/
public abstract class ParsedExpression extends Token {
private ParsedOperator _operator;
public ParsedExpression(ParsedOperator operator) {
super();
_operator = operator;
}
protected 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+" because "+e.getMessage());
// e.printStackTrace();
// System.out.println("TRY AS FUNCTION: "+listOfToken);
return ParsedFunction.makeFunction(listOfToken);
}
}
}
public ParsedOperator getOperator() {
return _operator;
}
@Override
public abstract String toString();
protected static ParsedExpression makeExpression(ListOfToken aListOfTokens) throws ParseException {
if (aListOfTokens.size() == 1 && aListOfTokens.firstElement() instanceof ParsedExpression) {
return (ParsedExpression) aListOfTokens.firstElement();
}
if (aListOfTokens.size() == 1 && aListOfTokens.firstElement() instanceof ListOfToken) {
return makeExpression((ListOfToken) aListOfTokens.firstElement());
} else {
boolean hasAmbigousOperators = false;
for (AbstractToken token : aListOfTokens) {
if (token instanceof ParsedOperator && ((ParsedOperator) token).isAmbigous()) {
hasAmbigousOperators = true;
}
}
if (hasAmbigousOperators) {
// System.out.println("Found ambigous operator !!!");
Vector<ListOfToken> evaluateThis = new Vector<ListOfToken>();
evaluateThis.add(aListOfTokens);
for (AbstractToken token : aListOfTokens) {
if (token instanceof ParsedOperator && ((ParsedOperator) token).isAmbigous()) {
ParsedOperator ambigousOperator = (ParsedOperator) token;
Vector<ListOfToken> newListsToEvaluate = new Vector<ListOfToken>();
for (ListOfToken aList : evaluateThis) {
ListOfToken cloneList = (ListOfToken) aList.clone();
for (int i = 0; i < cloneList.size(); i++) {
AbstractToken t = cloneList.elementAt(i);
if (t == ambigousOperator) { // This is the ambigous operator
cloneList.set(
i,
new ParsedOperator(ambigousOperator.getAlternativeOperator(), ambigousOperator
.getExpressionParser()));
}
}
newListsToEvaluate.add(cloneList);
}
evaluateThis.addAll(newListsToEvaluate);
}
}
/* for (ListOfToken aList : evaluateThis) {
System.out.println("Evaluating : "+aList);
}*/
for (ListOfToken aList : evaluateThis) {
// System.out.println("Evaluating : "+aList);
try {
return _internallyMakeExpression(aList);
} catch (ParseException e) {
// Lets evaluate an other one
}
}
// No way, abort
throw new ParseException("Parse error");
} else {
return _internallyMakeExpression(aListOfTokens);
}
}
}
private static ParsedExpression _internallyMakeExpression(ListOfToken aListOfTokens) throws ParseException {
// 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++;
// System.out.println("J'identifie une fonction "+tok+" with args "+tryToBuildFunction);
} else {
functionsReducedParamList.add(tok);
}
}
ListOfToken unparsedList = functionsReducedParamList;
// ListOfToken unparsedList = aListOfTokens;
Vector<IndexedOperator> allOperators = new Vector<IndexedOperator>();
for (int i = 0; i < unparsedList.size(); i++) {
if (unparsedList.elementAt(i) instanceof ParsedOperator) {
IndexedOperator toAdd = new IndexedOperator();
toAdd.operator = (ParsedOperator) 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();
}
});
if (allOperators.size() == 0) {
// System.out.println("unparsedList of size: "+unparsedList.size());
/*for (AbstractToken token : unparsedList) {
System.out.println("token: "+token+" of "+token.getClass().getSimpleName());
}*/
StringBuffer sb = new StringBuffer();
for (AbstractToken token : unparsedList) {
sb.append(token.toString());
}
throw new ParseException("Syntax error: no operator found in " + sb.toString());
}
IndexedOperator pivot = allOperators.firstElement();
if (pivot.operator.getOperator() instanceof BinaryOperator) {
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 ParsedBinaryExpression(pivot.operator, left, right);
}
else if (pivot.operator.getOperator() instanceof UnaryOperator) {
/*if (pivot.index != 0)
throw new ParseException("Parse error near "+pivot.operator.toString());
ListOfToken right = new ListOfToken();
for (int i=1; i<unparsedList.size(); i++) right.add(unparsedList.elementAt(i));
return new ParsedUnaryExpression(pivot.operator,right);*/
ListOfToken right = new ListOfToken();
for (int i = pivot.index + 1; i < unparsedList.size(); i++) {
right.add(unparsedList.elementAt(i));
}
ParsedUnaryExpression newParsedUnaryExpression = new ParsedUnaryExpression(pivot.operator, right);
ListOfToken newUnparsedList = new ListOfToken();
for (int i = 0; i < pivot.index; i++) {
newUnparsedList.add(unparsedList.elementAt(i));
}
newUnparsedList.add(newParsedUnaryExpression);
return makeExpression(newUnparsedList);
}
else {
throw new ParseException("Internal error");
}
}
protected static class IndexedOperator {
protected int index;
protected ParsedOperator operator;
@Override
public String toString() {
return "(" + index + "," + operator + ")";
}
}
}