KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > percederberg > grammatica > test > ArithmeticCalculator


1 /*
2  * ArithmeticCalculator.java
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2.1
7  * of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307, USA.
18  *
19  * Copyright (c) 2003-2005 Per Cederberg. All rights reserved.
20  */

21
22 package net.percederberg.grammatica.test;
23
24 import java.io.StringReader JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.HashMap JavaDoc;
27
28 import net.percederberg.grammatica.parser.Node;
29 import net.percederberg.grammatica.parser.ParseException;
30 import net.percederberg.grammatica.parser.Production;
31 import net.percederberg.grammatica.parser.Token;
32
33 /**
34  * A simple arithmetic calculator.
35  *
36  * @author Per Cederberg, <per at percederberg dot net>
37  * @version 1.0
38  */

39 class ArithmeticCalculator extends ArithmeticAnalyzer {
40
41     /**
42      * The map with all variable names and values.
43      */

44     private HashMap JavaDoc variables;
45
46     /**
47      * Creates a new arithmetic calculator.
48      */

49     public ArithmeticCalculator() {
50         this(new HashMap JavaDoc());
51     }
52
53     /**
54      * Creates a new arithmetic calculator.
55      *
56      * @param variables the variable bindings to use
57      */

58     public ArithmeticCalculator(HashMap JavaDoc variables) {
59         this.variables = variables;
60     }
61
62     /**
63      * Calculates the numeric value of an expression.
64      *
65      * @param expression the expression to calculate
66      *
67      * @return the numeric value of the expression
68      *
69      * @throws Exception if the expression contained an error
70      */

71     public int calculate(String JavaDoc expression) throws Exception JavaDoc {
72         ArithmeticParser parser;
73         Node node;
74
75         parser = new ArithmeticParser(new StringReader JavaDoc(expression), this);
76         parser.prepare();
77         node = parser.parse();
78         return ((Integer JavaDoc) node.getValue(0)).intValue();
79     }
80
81     /**
82      * Adds the addition operator as a node value.
83      *
84      * @param node the node being exited
85      *
86      * @return the node to add to the parse tree
87      */

88     protected Node exitAdd(Token node) {
89         node.addValue("+");
90         return node;
91     }
92
93     /**
94      * Adds the subtraction operator as a node value.
95      *
96      * @param node the node being exited
97      *
98      * @return the node to add to the parse tree
99      */

100     protected Node exitSub(Token node) {
101         node.addValue("-");
102         return node;
103     }
104
105     /**
106      * Adds the multiplication operator as a node value.
107      *
108      * @param node the node being exited
109      *
110      * @return the node to add to the parse tree
111      */

112     protected Node exitMul(Token node) {
113         node.addValue("*");
114         return node;
115     }
116
117     /**
118      * Adds the division operator as a node value.
119      *
120      * @param node the node being exited
121      *
122      * @return the node to add to the parse tree
123      */

124     protected Node exitDiv(Token node) {
125         node.addValue("/");
126         return node;
127     }
128
129     /**
130      * Adds the number as a node value.
131      *
132      * @param node the node being exited
133      *
134      * @return the node to add to the parse tree
135      */

136     protected Node exitNumber(Token node) {
137         node.addValue(new Integer JavaDoc(node.getImage()));
138         return node;
139     }
140
141     /**
142      * Adds the identifier value as a node value.
143      *
144      * @param node the node being exited
145      *
146      * @return the node to add to the parse tree
147      */

148     protected Node exitIdentifier(Token node) {
149         node.addValue(variables.get(node.getImage()));
150         return node;
151     }
152
153     /**
154      * Adds the expression result as a node value.
155      *
156      * @param node the node being exited
157      *
158      * @return the node to add to the parse tree
159      */

160     protected Node exitExpression(Production node) {
161         ArrayList JavaDoc values = getChildValues(node);
162         Integer JavaDoc value1;
163         Integer JavaDoc value2;
164         String JavaDoc op;
165         int result;
166
167         if (values.size() == 1) {
168             result = ((Integer JavaDoc) values.get(0)).intValue();
169         } else {
170             value1 = (Integer JavaDoc) values.get(0);
171             value2 = (Integer JavaDoc) values.get(2);
172             op = (String JavaDoc) values.get(1);
173             result = operate(op, value1, value2);
174         }
175         node.addValue(new Integer JavaDoc(result));
176         return node;
177     }
178
179     /**
180      * Adds the child values as node values.
181      *
182      * @param node the node being exited
183      *
184      * @return the node to add to the parse tree
185      */

186     protected Node exitExpressionRest(Production node) {
187         node.addValues(getChildValues(node));
188         return node;
189     }
190
191     /**
192      * Adds the term result as a node value.
193      *
194      * @param node the node being exited
195      *
196      * @return the node to add to the parse tree
197      */

198     protected Node exitTerm(Production node) {
199         ArrayList JavaDoc values = getChildValues(node);
200         Integer JavaDoc value1;
201         Integer JavaDoc value2;
202         String JavaDoc op;
203         int result;
204
205         if (values.size() == 1) {
206             result = ((Integer JavaDoc) values.get(0)).intValue();
207         } else {
208             value1 = (Integer JavaDoc) values.get(0);
209             value2 = (Integer JavaDoc) values.get(2);
210             op = (String JavaDoc) values.get(1);
211             result = operate(op, value1, value2);
212         }
213         node.addValue(new Integer JavaDoc(result));
214         return node;
215     }
216
217     /**
218      * Adds the child values as node values.
219      *
220      * @param node the node being exited
221      *
222      * @return the node to add to the parse tree
223      */

224     protected Node exitTermRest(Production node) {
225         node.addValues(getChildValues(node));
226         return node;
227     }
228
229     /**
230      * Adds the factor value as a node value.
231      *
232      * @param node the node being exited
233      *
234      * @return the node to add to the parse tree
235      *
236      * @throws ParseException if the node analysis discovered errors
237      */

238     protected Node exitFactor(Production node) throws ParseException {
239         int result;
240
241         if (node.getChildCount() == 1) {
242             result = getIntValue(getChildAt(node, 0), 0);
243         } else {
244             result = getIntValue(getChildAt(node, 1), 0);
245         }
246         node.addValue(new Integer JavaDoc(result));
247         return node;
248     }
249
250     /**
251      * Adds the child values as node values.
252      *
253      * @param node the node being exited
254      *
255      * @return the node to add to the parse tree
256      */

257     protected Node exitAtom(Production node) {
258         node.addValues(getChildValues(node));
259         return node;
260     }
261
262     /**
263      * Performs a numerical operation.
264      *
265      * @param op the operator to use
266      * @param value1 the first value
267      * @param value2 the second value
268      *
269      * @return the result of performing the operation
270      */

271     private int operate(String JavaDoc op, Integer JavaDoc value1, Integer JavaDoc value2) {
272         int i = value1.intValue();
273         int j = value2.intValue();
274
275         switch (op.charAt(0)) {
276         case '+':
277             return i + j;
278         case '-':
279             return i - j;
280         case '*':
281             return i * j;
282         case '/':
283             return i / j;
284         default:
285             throw new RuntimeException JavaDoc("unknown operator: " + op);
286         }
287     }
288 }
289
Popular Tags