2
* STANDARD ML OF NEW JERSEY COPYRIGHT NOTICE, LICENSE AND DISCLAIMER.
4
* Copyright (c) 1989-1998 by Lucent Technologies
6
* Permission to use, copy, modify, and distribute this software and its
7
* documentation for any purpose and without fee is hereby granted, provided
8
* that the above copyright notice appear in all copies and that both the
9
* copyright notice and this permission notice and warranty disclaimer appear
10
* in supporting documentation, and that the name of Lucent Technologies, Bell
11
* Labs or any Lucent entity not be used in advertising or publicity pertaining
12
* to distribution of the software without specific, written prior permission.
14
* Lucent disclaims all warranties with regard to this software, including all
15
* implied warranties of merchantability and fitness. In no event shall Lucent
16
* be liable for any special, indirect or consequential damages or any damages
17
* whatsoever resulting from loss of use, data or profits, whether in an action
18
* of contract, negligence or other tortious action, arising out of or in
19
* connection with the use or performance of this software.
21
* Taken from this URL:
22
* http://www.smlnj.org/license.html
24
* This license is compatible with the GNU GPL (see section "Standard ML of New
25
* Jersey Copyright License"):
26
* http://www.gnu.org/licenses/license-list.html#StandardMLofNJ
30
* Copyright 1996-1999 by Scott Hudson, Frank Flannery, C. Scott Ananian
33
package weka.core.mathematicalexpression;
35
import weka.core.parser.java_cup.runtime.*;
41
* A parser for parsing mathematical expressions.
43
* @author FracPete (fracpete at waikato dot ac dot nz)
44
* @version $Revision: 1.2 $
48
/** variable - value relation. */
49
protected HashMap m_Symbols = new HashMap();
51
/** for storing the result of the expresion. */
52
protected Double m_Result = null;
55
* Sets the variable - value relation to use.
57
* @param value the variable-value relation
59
public void setSymbols(HashMap value) {
64
* Returns the current variable - value relation in use.
66
* @return the variable-value relation
68
public HashMap getSymbols() {
73
* Sets the result of the evaluation.
75
* @param value the result
77
public void setResult(Double value) {
82
* Returns the result of the evaluation.
86
public Double getResult() {
91
* Runs the parser from commandline. Either reads lines from System.in
92
* or from a provided file (line by line). With
93
* <code>-symbols <semi-colon separated list of variable/value pairs></code>
94
* as first parameter one can provide predefined variable values. E.g.:
95
* <code>-symbols "Y=10;X=3" "X+Y"</code>
97
* @param args the commandline arguments
98
* @throws Exception if something goes wrong
100
public static void main(String args[]) throws Exception {
101
// read symbols, if present
102
HashMap symbols = new HashMap();
103
if (args.length > 0) {
104
if (args[0].equals("-symbols")) {
106
String[] pairs = args[1].replaceAll(" ", "").split(";");
107
for (int i = 0; i < pairs.length; i++) {
108
String[] parts = pairs[i].split("=");
109
symbols.put(parts[0], new Double(parts[1]));
112
System.out.println("\nSymbols provided:");
113
Iterator iter = symbols.keySet().iterator();
114
while (iter.hasNext()) {
115
String key = (String) iter.next();
116
System.out.println(key + "=" + symbols.get(key));
118
// remove symbols from commandline
119
String[] argsNew = new String[args.length - 2];
120
System.arraycopy(args, 2, argsNew, 0, argsNew.length);
125
// setup input stream
127
if (args.length == 1)
129
BufferedReader input = null;
131
System.out.println("\nPlease type in expressions (and press <Enter>), exit with <Ctrl+D>:");
132
input = new BufferedReader(new InputStreamReader(System.in));
135
System.out.println("\nReading expressions from file '" + args[index] + "':");
136
input = new BufferedReader(new FileReader(args[index]));
140
SymbolFactory sf = new DefaultSymbolFactory();
142
while ((line = input.readLine()) != null) {
143
ByteArrayInputStream parserInput = new ByteArrayInputStream(line.getBytes());
144
Parser parser = new Parser(new Scanner(parserInput,sf), sf);
145
parser.setSymbols(symbols);
147
System.out.println(line + " = " + parser.getResult());
152
terminal COMMA, LPAREN, RPAREN;
153
terminal MINUS, PLUS, TIMES, DIVISION;
154
terminal ABS, SQRT, LOG, EXP, SIN, COS, TAN, RINT, FLOOR, POW, CEIL, IFELSE;
155
terminal TRUE, FALSE, LT, LE, GT, GE, EQ, NOT, AND, OR;
156
terminal Double NUMBER;
157
terminal Boolean BOOLEAN;
158
terminal String VARIABLE;
160
non terminal expr_list, expr_part;
161
non terminal Double expr;
162
non terminal Double opexpr;
163
non terminal Double varexpr;
164
non terminal Double funcexpr;
165
non terminal Boolean boolexpr;
167
precedence left PLUS, MINUS;
168
precedence left TIMES, DIVISION;
169
precedence left LPAREN, RPAREN;
170
precedence left ABS, SQRT, LOG, EXP, SIN, COS, TAN, RINT, FLOOR, POW, CEIL;
171
precedence left AND, OR;
174
expr_list ::= expr_list expr_part | expr_part;
175
expr_part ::= expr:e {: parser.setResult(e); :} ;
178
| LPAREN expr:e RPAREN
188
opexpr ::= expr:l PLUS expr:r
189
{: RESULT = new Double(l.doubleValue() + r.doubleValue()); :}
190
| expr:l MINUS expr:r
191
{: RESULT = new Double(l.doubleValue() - r.doubleValue()); :}
192
| expr:l TIMES expr:r
193
{: RESULT = new Double(l.doubleValue() * r.doubleValue()); :}
194
| expr:l DIVISION expr:r
195
{: RESULT = new Double(l.doubleValue() / r.doubleValue()); :}
198
varexpr ::= VARIABLE:v
199
{: if (parser.getSymbols().containsKey(v))
200
RESULT = (Double) parser.getSymbols().get(v);
202
throw new IllegalStateException("Unknown symbol '" + v + "'!");
206
funcexpr ::= ABS LPAREN expr:e RPAREN
207
{: RESULT = new Double(Math.abs(e)); :}
208
| SQRT LPAREN expr:e RPAREN
209
{: RESULT = new Double(Math.sqrt(e)); :}
210
| LOG LPAREN expr:e RPAREN
211
{: RESULT = new Double(Math.log(e)); :}
212
| EXP LPAREN expr:e RPAREN
213
{: RESULT = new Double(Math.exp(e)); :}
214
| SIN LPAREN expr:e RPAREN
215
{: RESULT = new Double(Math.sin(e)); :}
216
| COS LPAREN expr:e RPAREN
217
{: RESULT = new Double(Math.cos(e)); :}
218
| TAN LPAREN expr:e RPAREN
219
{: RESULT = new Double(Math.tan(e)); :}
220
| RINT LPAREN expr:e RPAREN
221
{: RESULT = new Double(Math.rint(e)); :}
222
| FLOOR LPAREN expr:e RPAREN
223
{: RESULT = new Double(Math.floor(e)); :}
224
| POW LPAREN expr:base COMMA expr:exponent RPAREN
225
{: RESULT = new Double(Math.pow(base, exponent)); :}
226
| CEIL LPAREN expr:e RPAREN
227
{: RESULT = new Double(Math.ceil(e)); :}
228
| IFELSE LPAREN boolexpr:b COMMA expr:e_true COMMA expr:e_false RPAREN
236
boolexpr ::= BOOLEAN:b
239
{: RESULT = new Boolean(true); :}
241
{: RESULT = new Boolean(false); :}
243
{: RESULT = new Boolean(l.doubleValue() < r.doubleValue()); :}
245
{: RESULT = new Boolean(l.doubleValue() <= r.doubleValue()); :}
247
{: RESULT = new Boolean(l.doubleValue() > r.doubleValue()); :}
249
{: RESULT = new Boolean(l.doubleValue() >= r.doubleValue()); :}
251
{: RESULT = new Boolean(l.doubleValue() == r.doubleValue()); :}
252
| LPAREN boolexpr:b RPAREN
256
| boolexpr:l AND boolexpr:r
257
{: RESULT = l && r; :}
258
| boolexpr:l OR boolexpr:r
259
{: RESULT = l || r; :}