1 /
55
56
57 package org.apache.poi.hssf.record.formula;
58
59 import java.util.List;
60 import java.util.ArrayList;
61 import java.util.Stack;
62
63 import java.io.FileOutputStream;
64 import java.io.File;
65
66
67
80 public class FormulaParser {
81
82 private String formulaString;
83 private int pointer=0;
84
85 private List tokens = new java.util.Stack();
86
87 private List result = new ArrayList();
88 private int numParen;
89
90 private static char TAB = '\t';
91 private static char CR = '\n';
92
93 private char Look;
94
95
96
103 public FormulaParser(String formula){
104 formulaString = formula;
105 pointer=0;
106 }
107
108
109
110 private void GetChar() {
111 Look=formulaString.charAt(pointer++);
112
113 }
114
115
116
117 private void Error(String s) {
118 System.out.println("Error: "+s);
119 }
120
121
122
123
124 private void Abort(String s) {
125 Error(s);
126
127 throw new RuntimeException("Cannot Parse, sorry");
128 }
129
130
131
132
133 private void Expected(String s) {
134 Abort(s + " Expected");
135 }
136
137
138
139
140 private boolean IsAlpha(char c) {
141 return Character.isLetter(c) || c == '$';
142 }
143
144
145
146
147 private boolean IsDigit(char c) {
148
149 return Character.isDigit(c);
150 }
151
152
153
154
155 private boolean IsAlNum(char c) {
156 return (IsAlpha(c) || IsDigit(c));
157 }
158
159
160
161
162 private boolean IsAddop( char c) {
163 return (c =='+' || c =='-');
164 }
165
166
167
168 private boolean IsWhite( char c) {
169 return (c ==' ' || c== TAB);
170 }
171
172
173
174
175 private void SkipWhite() {
176 while (IsWhite(Look)) {
177 GetChar();
178 }
179 }
180
181
182
183
184 private void Match(char x) {
185 if (Look != x) {
186 Expected("" + x + "");
187 }else {
188 GetChar();
189 SkipWhite();
190 }
191 }
192
193
194
195 private String GetName() {
196 String Token;
197 Token = "";
198 if (!IsAlpha(Look)) {
199 Expected("Name");
200 }
201 while (IsAlNum(Look)) {
202 Token = Token + Character.toUpperCase(Look);
203 GetChar();
204 }
205
206 SkipWhite();
207 return Token;
208 }
209
210
211
212 private String GetNum() {
213 String Value ="";
214 if (!IsDigit(Look)) Expected("Integer");
215 while (IsDigit(Look)){
216 Value = Value + Look;
217 GetChar();
218 }
219 SkipWhite();
220 return Value;
221 }
222
223
224 private void Emit(String s){
225 System.out.print(TAB+s);
226 }
227
228
229 private void EmitLn(String s) {
230 Emit(s);
231 System.out.println();;
232 }
233
234
235 private void Ident() {
236 String name;
237 name = GetName();
238 if (Look == '('){
239
240 Match('(');
241 int numArgs = Arguments();
242 Match(')');
243
244 tokens.add(function(name,(byte)numArgs));
245 } else if (Look == ':') {
246 String first = name;
247 Match(':');
248 String second = GetName();
249 tokens.add(new AreaPtg(first+":"+second));
250 } else {
251
252 boolean cellRef = true ;
253 if (cellRef) {
254 tokens.add(new ReferencePtg(name));
255 }else {
256
257 }
258 }
259 }
260
261 private Ptg function(String name,byte numArgs) {
262 Ptg retval = null;
263
264 if (numArgs == 1 && name.equals("SUM")) {
265 AttrPtg ptg = new AttrPtg();
266 ptg.setData((short)1);
267 ptg.setSum(true);
268 retval = ptg;
269 } else {
270 FunctionPtg ptg = new FunctionPtg(name,numArgs);
271 retval = ptg;
272 }
273
274 return retval;
275 }
276
277
278 private int Arguments() {
279 int numArgs = 0;
280 if (Look != ')') {
281 numArgs++;
282 Expression();
283 }
284 while (Look == ',') {
285 Match(',');
286 Expression();
287 numArgs++;
288 }
289 return numArgs;
290 }
291
292
293 private void Factor() {
294 if (Look == '(' ) {
295 Match('(');
296 Expression();
297 Match(')');
298 tokens.add(new ParenthesisPtg());
299 return;
300 } else if (IsAlpha(Look)){
301 Ident();
302 }else{
303 String number = GetNum();
304 if (Look=='.') {
305 Match('.');
306 String decimalPart = null;
307 if (IsDigit(Look)) number = number +"."+ GetNum();
308 tokens.add(new NumberPtg(number));
309 } else {
310 tokens.add(new IntPtg(number));
311 }
312 }
313 }
314
315
316
317 private void Multiply(){
318 Match('*');
319 Factor();
320 tokens.add(new MultiplyPtg());
321
322 }
323
324
325
326 private void Divide() {
327 Match('/');
328 Factor();
329 tokens.add(new DividePtg());
330
331 }
332
333
334
335 private void Term(){
336 Factor();
337 while (Look == '*' || Look == '/' || Look == '^' || Look == '&') {
338
339 if (Look == '*') Multiply();
340 if (Look == '/') Divide();
341 if (Look == '^') Power();
342 if (Look == '&') Concat();
343 }
344 }
345
346
347 private void Add() {
348 Match('+');
349 Term();
350 tokens.add(new AddPtg());
351 }
352
353
354 private void Concat() {
355 Match('&');
356 Term();
357 tokens.add(new ConcatPtg());
358 }
359
360
361
362
363 private void Subtract() {
364 Match('-');
365 Term();
366 tokens.add(new SubtractPtg());
367 }
368
369 private void Power() {
370 Match('^');
371 Term();
372 tokens.add(new PowerPtg());
373 }
374
375
376
377 private void Expression() {
378 if (IsAddop(Look)) {
379 EmitLn("CLR D0");
380 } else {
381 Term();
382 }
383 while (IsAddop(Look)) {
384 if ( Look == '+' ) Add();
385 if (Look == '-') Subtract();
386
387
388 }
389 }
390
391
392
393
394
404
405
406
407
408 private void init() {
409 GetChar();
410 SkipWhite();
411 }
412
413
416 public void parse() {
417 synchronized (tokens) {
418 init();
419 Expression();
420 }
421 }
422
423
426 public Ptg[] getRPNPtg() {
427 synchronized (tokens) {
428 if (tokens == null) throw new IllegalStateException("Please parse a string before trying to access the parse result");
429 Ptg[] retval = new Ptg[tokens.size()];
430 return (Ptg[]) tokens.toArray(retval);
431 }
432 }
433
434
438 public static String toFormulaString(List lptgs) {
439 String retval = null;
440 Ptg[] ptgs = new Ptg[lptgs.size()];
441 ptgs = (Ptg[])lptgs.toArray(ptgs);
442 retval = toFormulaString(ptgs);
443 return retval;
444 }
445
446
449 public static String toFormulaString(Ptg[] ptgs) {
450 java.util.Stack stack = new java.util.Stack();
451 int numPtgs = ptgs.length;
452 OperationPtg o;
453 int numOperands;
454 String[] operands;
455 for (int i=0;i<numPtgs;i++) {
456 if (ptgs[i] instanceof OperationPtg) {
457 o = (OperationPtg) ptgs[i];
458 numOperands = o.getNumberOfOperands();
459 operands = new String[numOperands];
460 for (int j=0;j<numOperands;j++) {
461 operands[numOperands-j-1] = (String) stack.pop();
462
463 }
464 String result = o.toFormulaString(operands);
465 stack.push(result);
466 } else {
467 stack.push(ptgs[i].toFormulaString());
468 }
469 }
470 return (String) stack.pop();
471 }
472
473
476 public String toString() {
477 StringBuffer buf = new StringBuffer();
478 for (int i=0;i<tokens.size();i++) {
479 buf.append( ( (Ptg)tokens.get(i)).toFormulaString());
480 buf.append(' ');
481 }
482 return buf.toString();
483 }
484
485
486 }