summaryrefslogtreecommitdiff
path: root/trunk/users/metalab/AoI/plugins/CSGEvaluator/src/org/cheffo/jeplite/JEP.java
blob: 2a403bc6470c5355edc93ef9b796b552385971ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*****************************************************************************
JEP - Java Expression Parser
    JEP is a Java package for parsing and evaluating mathematical
	expressions. It currently supports user defined variables,
	constant, and functions. A number of common mathematical
	functions and constants are included.
  JEPLite is a simplified version of JEP.
JEP Author: Nathan Funk
JEPLite Author: Stephen "Cheffo" Kolaroff
JEP Copyright (C) 2001 Nathan Funk
JEPLite Copyright (C) 2002 Stefan  Kolarov
    JEPLite 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 2 of the License, or
    (at your option) any later version.

    JEPLite 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 JEPLite; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*****************************************************************************/
package org.cheffo.jeplite;
import java.io.*;
import java.util.*;
import org.cheffo.jeplite.*;
import org.cheffo.jeplite.function.*;
import org.cheffo.jeplite.util.*;

public class JEP {
	private HashMap symTab;
	private HashMap funTab;
	private SimpleNode topNode;
	private boolean debug=false;
	private Parser parser;
	private boolean hasError;
	private ParseException parseException;
	public JEP()
	{
		topNode = null;
		hasError = true;
		parseException = null;
		initSymTab();
		initFunTab();
		parser = new Parser(new StringReader(""));
		parseExpression("");
	}

  	/**
	  * Initializes the symbol table
	  */
	public void initSymTab() {
		symTab = new HashMap();
	}

	/**
	  * Initializes the function table
	  */
	public void initFunTab() {
		funTab = new HashMap();
	}

	/**
	  * Adds the standard functions to the parser. If this function is not called
		* before parsing an expression, functions such as sin() or cos() would
		* produce an "Unrecognized function..." error.
		* In most cases, this method should be called immediately after the JEP
		* object is created.
	  */
	public void addStandardFunctions()
	{
    PostfixMathCommand.fillFunctionTable(funTab);
	}

	/**
	  * Adds the constants pi and e to the parser. As addStandardFunctions(), this
	  * method should be called immediatly after the JEP object is created.
	  */
	public void addStandardConstants(){
		addVariable("pi", Math.PI);
		addVariable("e", Math.E);
	}

	/**
	  * Adds a new function to the parser. This must be done before parsing
	  * an expression so the parser is aware that the new function may be
	  * contained in the expression.
	  */
	public void addFunction(String functionName, Object function)
	{
  	funTab.put(functionName, function);
	}

	/**
	  * Adds a new variable to the parser, or updates the value of an
	  * existing variable. This must be done before parsing
	  * an expression so the parser is aware that the new variable may be
	  * contained in the expression.
	  * @param name Name of the variable to be added
	  * @param value Initial value or new value for the variable
	  * @return Double object of the variable
	  */
	public Double addVariable(String name, double value)
	{
	  ASTVarNode toAdd = (ASTVarNode)symTab.get(name);
	  if(toAdd!=null)
	    toAdd.setValue(value);
	  else {
	    toAdd = new ASTVarNode(ParserTreeConstants.JJTVARNODE);
	    toAdd.setName(name);
	    toAdd.setValue(value);
	    symTab.put(name, toAdd);
	  }
    return new Double(value);
	}

	public ASTVarNode getVarNode(String var) {
	  return (ASTVarNode)symTab.get(var);
	}

  public void setVarNode(String var, ASTVarNode node) {
    symTab.put(var, node);
  }

	/**
	  * Parses the expression
	  * @param expression_in The input expression string
	  */
	public void parseExpression(String expression_in)
	{
		Reader reader = new StringReader(expression_in);
		hasError = false;
		parseException = null;
		try
		{
			topNode = parser.parseStream(reader, symTab, funTab);
		} catch (Throwable e)
		{
			if (debug && !(e instanceof ParseException))
			{
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
			topNode = null;
			hasError = true;
			if (e instanceof ParseException)
				parseException = (ParseException)e;
			else
			    parseException = null;
		}
		Vector errorList = parser.getErrorList();
		if (!errorList.isEmpty()) hasError = true;
	}

	/**
	  * Evaluates and returns the value of the expression. If the value is
	  * complex, the real component of the complex number is returned. To
	  * get the complex value, use getComplexValue().
	  * @return The calculated value of the expression. If the value is
	  * complex, the real component is returned. If an error occurs during
	  * evaluation, 0 is returned.
	  */
	public double getValue() throws ParseException
	{
    return getValue(new DoubleStack());
	}

  public SimpleNode getTopNode() {
    return topNode;
  }

	public double getValue(DoubleStack evalStack) throws ParseException {
	  topNode.getValue(evalStack);
	  return(evalStack.pop());
	}

	/**
	  * Reports whether there is an error in the expression
	  * @return Returns true if the expression has an error
	  */
	public boolean hasError()
	{
		return hasError;
	}

	/**
	  * Reports information on the error in the expression
	  * @return Returns a string containing information on the error;
	  * null if no error has occured
	  */
	public String getErrorInfo()
	{
		if (hasError)
		{
			Vector el = parser.getErrorList();
			String str = "";
			if (parseException == null && el.size()==0) str = "Syntax error\n";
			if (parseException != null) str = parseException.getErrorInfo() + "\n";
			for (int i=0; i<el.size(); i++)
				str += el.elementAt(i) + "\n";
			return str;
		}
		else
			return null;
	}
}