001: package org.jacorb.idl;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import java.util.HashMap;
024: import java.lang.Double;
025:
026: /**
027: * Based on the MathEvaluator class by The-Son LAI,
028: * <a href="mailto:Lts@writeme.com">Lts@writeme.com</a>
029: *
030: * <i>Expression evaluator for IDL constant expression</i>
031: *
032: * Supports the following functions:
033: * +, -, *, /, ^, %, ^, | , <<, >> <br>
034: *
035: * When the getValue() is called, a Double object is returned.
036: * If it returns null, an error occured.<p>
037:
038: * @version $Id: ConstExprEvaluator.java,v 1.6 2006/06/02 13:02:56 alphonse.bendt Exp $
039: * @author Gerald Brose,
040: * The-Son LAI <a href="mailto:Lts@writeme.com">Lts@writeme.com</a>
041: */
042:
043: public class ConstExprEvaluator {
044: protected static Operator[] operators = null;
045: private Node node = null;
046: private String expression = null;
047: private HashMap variables = new HashMap();
048:
049: /**
050: * creates an empty ConstExprEvaluator.
051: * You need to use setExpression(String s) to assign an expression string to it.
052: */
053:
054: public ConstExprEvaluator() {
055: init();
056: }
057:
058: /**
059: * creates a ConstExprEvaluator and assign the expression string.
060: */
061:
062: public ConstExprEvaluator(String s) {
063: init();
064: setExpression(s);
065: }
066:
067: private void init() {
068: if (operators == null)
069: initializeOperators();
070: }
071:
072: /**
073: * sets the expression
074: */
075:
076: public void setExpression(String s) {
077: expression = s;
078: }
079:
080: /**
081: * resets the evaluator
082: */
083:
084: public void reset() {
085: node = null;
086: expression = null;
087: variables = new HashMap();
088: }
089:
090: /**
091: * evaluates and returns the value of the expression
092: */
093:
094: public Double getValue() {
095: if (expression == null) {
096: return null;
097: }
098:
099: try {
100: node = new Node(expression);
101: return evaluate(node);
102: } catch (Exception e) {
103: lexer.emit_error("unexpected exception: " + e.getMessage());
104: // TODO throw exception?
105: return null;
106: }
107: }
108:
109: private static Double evaluate(Node n) {
110: if (n.hasOperator() && n.hasChild()) {
111: if (n.getOperator().getType() == 1)
112: n.setValue(evaluateExpression(n.getOperator(),
113: evaluate(n.getLeft()), null));
114: else if (n.getOperator().getType() == 2)
115: n.setValue(evaluateExpression(n.getOperator(),
116: evaluate(n.getLeft()), evaluate(n.getRight())));
117: }
118: return n.getValue();
119: }
120:
121: private static Double evaluateExpression(Operator o, Double f1,
122: Double f2) {
123: String op = o.getOperator();
124: Double res = null;
125:
126: if ("+".equals(op))
127: res = new Double(f1.doubleValue() + f2.doubleValue());
128: else if ("-".equals(op))
129: res = new Double(f1.doubleValue() - f2.doubleValue());
130: else if ("*".equals(op))
131: res = new Double(f1.doubleValue() * f2.doubleValue());
132: else if ("/".equals(op))
133: res = new Double(f1.doubleValue() / f2.doubleValue());
134: else if ("%".equals(op))
135: res = new Double(f1.doubleValue() % f2.doubleValue());
136: else if ("|".equals(op))
137: res = new Double(Double.longBitsToDouble(Double
138: .doubleToLongBits(f1.doubleValue())
139: | Double.doubleToLongBits(f2.doubleValue())));
140: else if ("&".equals(op))
141: res = new Double(Double.longBitsToDouble(Double
142: .doubleToLongBits(f1.doubleValue())
143: & Double.doubleToLongBits(f2.doubleValue())));
144: else if ("^".equals(op))
145: res = new Double(Double.longBitsToDouble(Double
146: .doubleToLongBits(f1.doubleValue())
147: ^ Double.doubleToLongBits(f2.doubleValue())));
148: else if ("<<".equals(op))
149: res = new Double(Double.longBitsToDouble(Double
150: .doubleToLongBits(f1.doubleValue()) << Double
151: .doubleToLongBits(f2.doubleValue())));
152: else if (">>".equals(op))
153: res = new Double(Double.longBitsToDouble(Double
154: .doubleToLongBits(f1.doubleValue()) >> Double
155: .doubleToLongBits(f2.doubleValue())));
156:
157: return res;
158: }
159:
160: private void initializeOperators() {
161: operators = new Operator[10];
162:
163: // bit-wise operators
164: operators[0] = new Operator("|", 2, 0);
165:
166: operators[1] = new Operator("^", 2, 2);
167:
168: operators[2] = new Operator("&", 2, 4);
169:
170: operators[3] = new Operator(">>", 2, 6);
171: operators[4] = new Operator("<<", 2, 6);
172: // arithmetic operators
173: operators[5] = new Operator("+", 2, 8);
174: operators[6] = new Operator("-", 2, 8);
175:
176: operators[7] = new Operator("*", 2, 10);
177: operators[8] = new Operator("/", 2, 10);
178: operators[9] = new Operator("%", 2, 10);
179: }
180:
181: /**
182: * gets the variable's value that was assigned previously
183: */
184:
185: public Double getVariable(String s) {
186: return (Double) variables.get(s);
187: }
188:
189: private Double getDouble(String s) {
190: if (s == null)
191: return null;
192:
193: Double res = null;
194: try {
195: res = new Double(Double.parseDouble(s));
196: } catch (Exception e) {
197: return getVariable(s);
198: }
199:
200: return res;
201: }
202:
203: protected Operator[] getOperators() {
204: return operators;
205: }
206:
207: protected class Operator {
208: private String op;
209: private int type;
210: private int priority;
211:
212: public Operator(String o, int t, int p) {
213: op = o;
214: type = t;
215: priority = p;
216: }
217:
218: public String getOperator() {
219: return op;
220: }
221:
222: public void setOperator(String o) {
223: op = o;
224: }
225:
226: public int getType() {
227: return type;
228: }
229:
230: public int getPriority() {
231: return priority;
232: }
233: }
234:
235: protected class Node {
236: public String nString = null;
237: public Operator nOperator = null;
238: public Node nLeft = null;
239: public Node nRight = null;
240: public Node nParent = null;
241: public int nLevel = 0;
242: public Double nValue = null;
243:
244: public Node(String s) throws Exception {
245: init(null, s, 0);
246: }
247:
248: public Node(Node parent, String s, int level) throws Exception {
249: init(parent, s, level);
250: }
251:
252: private void init(Node parent, String s, int level)
253: throws Exception {
254: s = removeIllegalCharacters(s);
255: s = removeBrackets(s);
256: s = addZero(s);
257: if (checkBrackets(s) != 0)
258: throw new Exception("Wrong number of brackets in [" + s
259: + "]");
260:
261: nParent = parent;
262: nString = s;
263: nValue = getDouble(s);
264: nLevel = level;
265: int sLength = s.length();
266: int inBrackets = 0;
267: int startOperator = 0;
268:
269: for (int i = 0; i < sLength; i++) {
270: if (s.charAt(i) == '(')
271: inBrackets++;
272: else if (s.charAt(i) == ')')
273: inBrackets--;
274: else {
275: // the expression must be at "root" level
276: if (inBrackets == 0) {
277: Operator o = getOperator(nString, i);
278: if (o != null) {
279: // if first operator or lower priority operator
280: if (nOperator == null
281: || nOperator.getPriority() >= o
282: .getPriority()) {
283: nOperator = o;
284: startOperator = i;
285: }
286: }
287: }
288: }
289: }
290:
291: if (nOperator != null) {
292: // one operand, should always be at the beginning
293: if (startOperator == 0 && nOperator.getType() == 1) {
294: // the brackets must be ok
295: if (checkBrackets(s.substring(nOperator
296: .getOperator().length())) == 0) {
297: nLeft = new Node(this , s.substring(nOperator
298: .getOperator().length()), nLevel + 1);
299: nRight = null;
300: return;
301: }
302:
303: throw new Exception(
304: "Error during parsing... missing brackets in ["
305: + s + "]");
306: }
307: // two operands
308: else if (startOperator > 0 && nOperator.getType() == 2) {
309: nLeft = new Node(this , s
310: .substring(0, startOperator), nLevel + 1);
311: nRight = new Node(this , s.substring(startOperator
312: + nOperator.getOperator().length()),
313: nLevel + 1);
314: }
315: }
316: }
317:
318: private Operator getOperator(String s, int start) {
319: Operator[] operators = getOperators();
320: String temp = s.substring(start);
321: temp = getNextWord(temp);
322: for (int i = 0; i < operators.length; i++) {
323: if (temp.startsWith(operators[i].getOperator()))
324: return operators[i];
325: }
326: return null;
327: }
328:
329: private String getNextWord(String s) {
330: int sLength = s.length();
331: for (int i = 1; i < sLength; i++) {
332: char c = s.charAt(i);
333: if ((c > 'z' || c < 'a') && (c > '9' || c < '0'))
334: return s.substring(0, i);
335: }
336: return s;
337: }
338:
339: /**
340: * checks if there is any missing brackets
341: * @return true if s is valid
342: */
343: protected int checkBrackets(String s) {
344: int sLength = s.length();
345: int inBracket = 0;
346:
347: for (int i = 0; i < sLength; i++) {
348: if (s.charAt(i) == '(' && inBracket >= 0)
349: inBracket++;
350: else if (s.charAt(i) == ')')
351: inBracket--;
352: }
353:
354: return inBracket;
355: }
356:
357: /**
358: * returns a string that doesnt start with a + or a -
359: */
360: protected String addZero(String s) {
361: if (s.startsWith("+") || s.startsWith("-")) {
362: int sLength = s.length();
363: for (int i = 0; i < sLength; i++) {
364: if (getOperator(s, i) != null)
365: return "0" + s;
366: }
367: }
368:
369: return s;
370: }
371:
372: protected boolean hasChild() {
373: return (nLeft != null || nRight != null);
374: }
375:
376: protected boolean hasOperator() {
377: return (nOperator != null);
378: }
379:
380: protected boolean hasLeft() {
381: return (nLeft != null);
382: }
383:
384: protected Node getLeft() {
385: return nLeft;
386: }
387:
388: protected boolean hasRight() {
389: return (nRight != null);
390: }
391:
392: protected Node getRight() {
393: return nRight;
394: }
395:
396: protected Operator getOperator() {
397: return nOperator;
398: }
399:
400: protected int getLevel() {
401: return nLevel;
402: }
403:
404: protected Double getValue() {
405: return nValue;
406: }
407:
408: protected void setValue(Double f) {
409: nValue = f;
410: }
411:
412: protected String getString() {
413: return nString;
414: }
415:
416: /**
417: * Removes spaces, tabs and brackets at the begining
418: */
419:
420: public String removeBrackets(String s) {
421: String res = s;
422: if (s.length() > 2
423: && res.startsWith("(")
424: && res.endsWith(")")
425: && checkBrackets(s.substring(1, s.length() - 1)) == 0) {
426: res = res.substring(1, res.length() - 1);
427: }
428: if (res != s)
429: return removeBrackets(res);
430: else
431: return res;
432: }
433:
434: /**
435: * Removes illegal characters
436: */
437:
438: public String removeIllegalCharacters(String s) {
439: char[] illegalCharacters = { ' ' };
440: String res = s;
441:
442: for (int j = 0; j < illegalCharacters.length; j++) {
443: int i = res.lastIndexOf(illegalCharacters[j], res
444: .length());
445: while (i != -1) {
446: String temp = res;
447: res = temp.substring(0, i);
448: res += temp.substring(i + 1);
449: i = res.lastIndexOf(illegalCharacters[j], s
450: .length());
451: }
452: }
453: return res;
454: }
455:
456: }
457: }
|