1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.qedeq.kernel.bo.parser;
17
18 import java.util.ArrayList;
19 import java.util.List;
20
21 import org.qedeq.base.io.TextInput;
22 import org.qedeq.base.trace.Trace;
23
24
25
26
27
28
29 public abstract class MathParser {
30
31
32 private static final Class CLASS = MathParser.class;
33
34
35 private MementoTextInput input;
36
37
38 private List operators;
39
40
41
42
43 public MathParser() {
44
45 }
46
47
48
49
50
51
52
53 public void setParameters(final MementoTextInput input, final List operators) {
54 this.input = input;
55 this.operators = operators;
56 }
57
58
59
60
61
62
63
64 public void setParameters(final TextInput input, final List operators) {
65 setParameters(new MementoTextInput(input), operators);
66 }
67
68
69
70
71
72
73
74 public void setParameters(final StringBuffer input, final List operators) {
75 setParameters(new TextInput(input), operators);
76 }
77
78
79
80
81
82
83
84 public void setParameters(final String input, final List operators) {
85 setParameters(new TextInput(input), operators);
86 }
87
88 protected final List getOperators() {
89 return operators;
90 }
91
92
93
94
95
96
97
98 public final Term readTerm() throws ParserException {
99 final String method = "Term readTerm()";
100 Trace.begin(CLASS, this, method);
101 try {
102 final Term term = readMaximalTerm(0);
103 if (eot(getToken())) {
104 readToken();
105 }
106 return term;
107 } finally {
108 Trace.end(CLASS, this, method);
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121
122 private final Term readMaximalTerm(final int priority) throws ParserException {
123 final String method = "readMaximalTerm(int)";
124 Trace.begin(CLASS, this, method);
125 Term term = null;
126 try {
127 if (eot(getToken())) {
128 Trace.param(CLASS, this, method, "return term", "null");
129 return null;
130 }
131 term = readPrefixTerm();
132 term = addNextInfixTerms(priority, term);
133 Trace.param(CLASS, this, method,
134 "return term", (term != null ? term.getQedeq() : "null"));
135 return term;
136 } finally {
137 Trace.end(CLASS, this, method);
138 }
139 }
140
141 private Term addNextInfixTerms(final int priority, final Term initialTerm)
142 throws ParserException {
143 final String method = "Term addNextInfixTerms(int, Term)";
144 Trace.begin(CLASS, this, method);
145 Term term = initialTerm;
146 try {
147 Operator newOperator = null;
148 Operator oldOperator = null;
149
150 do {
151 markPosition();
152 newOperator = readOperator();
153 Trace.param(CLASS, this, method,
154 "newOperator", (newOperator != null ? newOperator.getQedeq() : "null"));
155 if (newOperator == null || newOperator.getPriority() <= priority) {
156 Trace.trace(CLASS, this, method, "newOperator is null or of less priority");
157 rewindPosition();
158 Trace.param(CLASS, this, method,
159 "read term", (term != null ? term.getQedeq() : "null"));
160 return term;
161 }
162 if (newOperator.isPrefix()) {
163 Trace.trace(CLASS, this, method, "newOperator is prefix");
164
165 rewindPosition();
166 Trace.param(CLASS, this, method,
167 "read term", (term != null ? term.getQedeq() : "null"));
168 return term;
169 }
170 if (newOperator.isPostfix()) {
171 rewindPosition();
172 throw new IllegalArgumentException("Postfix Operators not yet supported");
173 }
174 clearMark();
175 if (oldOperator == null || oldOperator.getPriority() >= newOperator.getPriority()) {
176 Trace.trace(CLASS, this, method,
177 "oldOperator is null or has more priority than new");
178 Term term2 = readMaximalTerm(newOperator.getPriority());
179 if (term2 == null) {
180
181 throw new TooFewArgumentsException(getPosition(), 2);
182 }
183 if (oldOperator == newOperator) {
184 if (oldOperator.getMax() != -1 && term.size() + 1 >= oldOperator.getMax()) {
185 throw new TooMuchArgumentsException(getPosition(), oldOperator,
186 oldOperator.getMax());
187 }
188 Trace.trace(CLASS, this, method, "new term is added to old term");
189 term.addArgument(term2);
190 } else {
191
192 Trace.trace(CLASS, this, method,
193 "old term is first argument of new operator");
194 term = new Term(newOperator, term);
195 term.addArgument(term2);
196 }
197 } else {
198 Trace.trace(CLASS, this,
199 method, "oldOperator is not null or has less priority than new");
200 Term term2 = readMaximalTerm(newOperator.getPriority());
201 if (term2 == null) {
202
203 throw new TooFewArgumentsException(getPosition(), 2);
204 }
205 term = new Term(newOperator, term);
206 term.addArgument(term2);
207 }
208 oldOperator = newOperator;
209 } while (true);
210 } finally {
211 Trace.end(CLASS, this, method);
212 }
213 }
214
215
216
217
218
219
220
221
222 private final Term readPrefixTerm() throws ParserException {
223 final String method = "readPrefixTerm()";
224 Trace.begin(CLASS, this, method);
225 Term term = null;
226 try {
227 final List readOperators = readOperators();
228 if (readOperators != null && readOperators.size() > 0) {
229 Trace.trace(CLASS, this, method, "operators found");
230 term = readPrefixOperator(readOperators);
231 } else {
232 Trace.trace(CLASS, this, method, "no operators found");
233 final String token;
234 token = getToken();
235 if (token == null) {
236 Trace.param(CLASS, this, method, "read term", "null");
237 return null;
238 }
239 if ("(".equals(token)) {
240 readToken();
241 Trace.trace(CLASS, this, method, "start bracket found: " + token);
242 term = readMaximalTerm(0);
243 final String lastToken = readToken();
244 if (!")".equals(lastToken)) {
245 throw new ClosingBracketMissingException(getPosition(), "(", lastToken);
246 }
247
248 } else if ("[".equals(token)) {
249 readToken();
250 Trace.trace(CLASS, this, method, "start bracket found: " + token);
251 term = readMaximalTerm(0);
252 final String lastToken = readToken();
253 if (!"]".equals(lastToken)) {
254 throw new ClosingBracketMissingException(getPosition(), "[", lastToken);
255 }
256 } else {
257 readToken();
258 Trace.param(CLASS, this, method, "atom", token);
259 term = new Term(new TermAtom(token));
260 }
261 }
262 Trace.param(CLASS, this, method,
263 "read term", (term != null ? term.getQedeq() : "null"));
264 return term;
265 } finally {
266 Trace.end(CLASS, this, method);
267 }
268 }
269
270
271
272
273
274
275
276
277
278 private Term readPrefixOperator(final List operators) throws ParserException {
279 Term term = null;
280 markPosition();
281 for (int number = 0; number < operators.size(); number++) {
282 rewindPosition();
283 markPosition();
284 Operator operator = (Operator) operators.get(number);
285
286 if (!operator.isPrefix()) {
287 clearMark();
288 throw new UnexpectedOperatorException(getPosition(), operator);
289 }
290
291 term = new Term(operator);
292
293 if (operator.isFunction()) {
294
295 if (operator.getMax() == 0) {
296 break;
297 }
298 List list = readTupel();
299 if (list == null) {
300 list = new ArrayList();
301 }
302
303 if (list.size() < operator.getMin()) {
304 if (number + 1 < operators.size()) {
305 continue;
306 }
307 clearMark();
308 throw new TooFewArgumentsException(getPosition(),
309 operator.getMin());
310 }
311
312 if (operator.getMax() != -1 && list.size() > operator.getMax()) {
313 if (number + 1 < operators.size()) {
314 continue;
315 }
316 clearMark();
317 throw new TooMuchArgumentsException(getPosition(), operator,
318 operator.getMax());
319 }
320 for (int i = 0; i < list.size(); i++) {
321 term.addArgument((Term) list.get(i));
322 }
323 break;
324 }
325
326 int i = 0;
327 while (i < operator.getMin()) {
328 if (i > 0 && operator.getSeparatorSymbol() != null) {
329 final String separator = getToken();
330 if (!operator.getSeparatorSymbol().equals(separator)) {
331 if (number + 1 < operators.size()) {
332 continue;
333 }
334 clearMark();
335 throw new SeparatorNotFoundException(getPosition(),
336 operator.getSeparatorSymbol());
337 }
338 readToken();
339 }
340 final Term add = readMaximalTerm(operator.getPriority());
341 if (add == null) {
342 if (number + 1 < operators.size()) {
343 continue;
344 }
345 clearMark();
346 throw new TooFewArgumentsException(getPosition(), operator.getMin());
347 }
348 term.addArgument(add);
349 i++;
350 }
351 while (operator.getMax() == -1 || i < operator.getMax()) {
352 if (i > 0 && operator.getSeparatorSymbol() != null) {
353 final String separator = getToken();
354 if (!operator.getSeparatorSymbol().equals(separator)) {
355 break;
356 }
357 readToken();
358 }
359 if (operator.getEndSymbol() != null) {
360 final String end = getToken();
361 if (operator.getEndSymbol().equals(end)) {
362 break;
363 }
364 }
365 Term add = null;
366 markPosition();
367 try {
368 add = readMaximalTerm(operator.getPriority());
369 clearMark();
370 } catch (Exception e) {
371 rewindPosition();
372 }
373 if (add == null) {
374 break;
375 }
376 term.addArgument(add);
377 i++;
378 }
379 if (operator.getEndSymbol() != null) {
380 final String end = getToken();
381 if (!operator.getEndSymbol().equals(end)) {
382 if (number + 1 < operators.size()) {
383 continue;
384 }
385 clearMark();
386 throw new EndSymbolNotFoundException(getPosition(),
387 operator.getEndSymbol());
388 }
389 readToken();
390 }
391 break;
392 }
393 clearMark();
394 return term;
395 }
396
397
398
399
400
401
402
403
404 private final List readTupel() throws ParserException {
405 final String method = "List readTupel()";
406 Trace.begin(CLASS, this, method);
407 try {
408 final String firstToken;
409 firstToken = getToken();
410 if (!"(".equals(firstToken)) {
411 Trace.trace(CLASS, this, method, "no start bracket found");
412 return null;
413 }
414 readToken();
415 List list = new ArrayList();
416 Term term = null;
417 while (null != (term = readMaximalTerm(0))) {
418 list.add(term);
419 final String separatorToken = getToken();
420 if (!",".equals(separatorToken)) {
421 break;
422 }
423 readToken();
424 }
425 final String lastToken = readToken();
426 if (!")".equals(lastToken)) {
427 throw new ClosingBracketMissingException(getPosition(), ")", lastToken);
428 }
429 return list;
430 } finally {
431 Trace.end(CLASS, this, method);
432 }
433 }
434
435
436
437
438
439
440 private final Operator readOperator() {
441 final String method = "Operator readOperator()";
442 Trace.begin(CLASS, this, method);
443
444 try {
445 markPosition();
446 final String token;
447 token = readToken();
448 if (token == null) {
449 rewindPosition();
450 Trace.trace(CLASS, this, method, "no operator found");
451 return null;
452 }
453 final Operator operator = getOperator(token);
454 if (operator == null) {
455 rewindPosition();
456 Trace.trace(CLASS, this, method, "no operator found");
457 return null;
458 }
459 clearMark();
460 Trace.param(CLASS, this, method, "operator", operator.getQedeq());
461 return operator;
462 } finally {
463 Trace.end(CLASS, this, method);
464 }
465 }
466
467
468
469
470
471
472
473
474 private final List readOperators() {
475 final String method = "List readOperators()";
476 Trace.begin(CLASS, this, method);
477
478 try {
479 markPosition();
480 final String token;
481 token = readToken();
482 if (token == null) {
483 rewindPosition();
484 Trace.trace(CLASS, this, method, "no operators found");
485 return null;
486 }
487 final List ops = getOperators(token);
488 if (ops == null || ops.size() == 0) {
489 rewindPosition();
490 Trace.trace(CLASS, this, method, "no operators found");
491 return null;
492 }
493 clearMark();
494 for (int i = 0; i < ops.size(); i++) {
495 Trace.param(CLASS, this, method, "operator[" + i + "]", ops.get(i));
496 }
497 return ops;
498 } finally {
499 Trace.end(CLASS, this, method);
500 }
501 }
502
503
504
505
506
507
508
509
510 protected abstract Operator getOperator(String token);
511
512
513
514
515
516
517
518
519 protected abstract List getOperators(String token);
520
521
522
523
524
525
526
527
528
529 protected abstract String readToken();
530
531
532
533
534
535
536
537
538
539 public final String getToken() {
540 markPosition();
541 final String result = readToken();
542 rewindPosition();
543 return result;
544 }
545
546
547
548
549 protected final void markPosition() {
550 input.markPosition();
551 }
552
553
554
555
556
557
558 protected final long rewindPosition() {
559 return input.rewindPosition();
560 }
561
562
563
564
565 protected final void clearMark() {
566 input.clearMark();
567 }
568
569
570
571
572
573
574 private long getPosition() {
575 return input.getPosition();
576 }
577
578
579
580
581
582
583
584
585 protected final int getChar() {
586 return input.getChar();
587 }
588
589
590
591
592
593
594
595
596 protected final int readChar() {
597 return input.read();
598 }
599
600
601
602
603
604
605
606 protected abstract boolean eot(String token);
607
608
609
610
611
612
613 public final boolean eof() {
614 return input.isEmpty();
615 }
616
617
618
619
620
621
622 public final int getRewindStackSize() {
623 return input.getRewindStackSize();
624 }
625
626 }