/*-
* Copyright © 2009 Diamond Light Source Ltd.
*
* This file is part of GDA.
*
* GDA is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 3 as published by the Free
* Software Foundation.
*
* GDA 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 GDA. If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.gda.richbeans.editors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.nfunk.jep.ASTConstant;
import org.nfunk.jep.ASTVarNode;
import org.nfunk.jep.FunctionTable;
import org.nfunk.jep.JEP;
import org.nfunk.jep.Node;
import org.nfunk.jep.Operator;
import org.nfunk.jep.OperatorSet;
/**
* A lot of caching goes on here.
*/
public class ExpressionUtils {
private static JEP PARSER;
private static JEP getParser() {
if (PARSER==null) {
PARSER = new JEP();
PARSER.addStandardFunctions();
PARSER.addStandardConstants();
PARSER.setAllowUndeclared(true);
}
return PARSER;
}
private static List<String> OPERATORS;
public static final List<String> getOperators() {
if (OPERATORS==null) {
List<String> tmp = new ArrayList<String>(31);
final JEP jepParser = getParser();
final OperatorSet ops = jepParser.getOperatorSet();
for (Operator operator : ops.getOperators()) {
tmp.add(operator.getSymbol());
}
OPERATORS = Collections.unmodifiableList(tmp);
}
return OPERATORS;
}
public static boolean isOperator(final String posOp) {
return getOperators().contains(posOp);
}
private static List<String> CONSTANTS;
public static final List<String> getConstants() {
if (CONSTANTS==null) {
List<String> tmp = new ArrayList<String>(31);
final JEP jepParser = getParser();
for (Object var : jepParser.getSymbolTable().keySet()) {
tmp.add(var.toString());
}
CONSTANTS = Collections.unmodifiableList(tmp);
}
return CONSTANTS;
}
public static boolean isConstant(final String posConst) {
return getConstants().contains(posConst);
}
/**
* Attempts to parse contents as expression. If empty string
* is returned there is no last term and we are ready for a new term.
*/
public static String getLastTerm(String contents) {
if (contents==null||"".equals(contents)) return "";
// If ends with operator, we have no term
for (String op : getOperators()) {
if (contents.endsWith(op)) return "";
}
if (contents.endsWith("(")) return "";
try {
final JEP parser = getParser();
final Node node = parser.parseExpression(contents);
final List<Node> last = new ArrayList<Node>(1);
getLastNode(node, last);
final Node lastNode = last.get(0);
if (lastNode instanceof ASTVarNode) {
final String tempName = ((ASTVarNode)lastNode).getName();
return tempName;
} else if (lastNode instanceof ASTConstant) {
final String tempName = ((ASTConstant)lastNode).getValue().toString();
return tempName;
}
} catch (Exception ne) {
return "";
}
return "";
}
private static void getLastNode(final Node node, final List<Node> last) {
if (node.jjtGetNumChildren()<1) {
last.clear();
last.add(node);
return;
}
for (int i = 0; i<node.jjtGetNumChildren(); ++i) {
final Node c = node.jjtGetChild(i);
getLastNode(c, last);
}
}
private static List<String> FUNCTIONS;
private static List<String> FUNCTIONS_BRACKETS;
public static final List<String> getFunctions() {
if (FUNCTIONS==null) {
List<String> tmp1 = new ArrayList<String>(31);
List<String> tmp2 = new ArrayList<String>(31);
final JEP jepParser = getParser();
final FunctionTable table = jepParser.getFunctionTable();
for (Object function : table.keySet()) {
tmp1.add(function.toString());
tmp2.add(function.toString()+"(");
}
FUNCTIONS = Collections.unmodifiableList(tmp1);
FUNCTIONS_BRACKETS = Collections.unmodifiableList(tmp2);
}
return FUNCTIONS;
}
public static Collection<? extends String> getFunctionsWithOpeningBrackets() {
getFunctions();
return FUNCTIONS_BRACKETS;
}
}