1 package calculator.antlr;
2
3 import java.math.BigDecimal;
4 import java.util.ArrayList;
5 import java.util.List;
6
7 import calculator.Expression;
8 import calculator.IllegalConstruction;
9 import calculator.atoms.*;
10 import calculator.calculatorBaseVisitor;
11 import calculator.calculatorParser.*;
12 import calculator.functions.*;
13 import calculator.operations.*;
14
15
16
17
18 public class ParserVisitor extends calculatorBaseVisitor<Expression> {
19
20
21
22
23 private Expression buildOperation(String opString, List<Expression> args) {
24 try {
25 switch (opString) {
26 case "+":
27 return new Plus(args);
28 case "-":
29 return new Minus(args);
30 case "*":
31 return new Times(args);
32 case "/":
33 return new Divides(args);
34 case "**":
35 return new Power(args);
36 default:
37 throw new IllegalArgumentException("Unknown operator: " + opString);
38 }
39 } catch (IllegalConstruction e) {
40 throw new RuntimeException(e);
41 }
42 }
43
44 private Expression buildFunction(String funcName, List<Expression> args) {
45 if (args.size() == 1) {
46 Expression arg = args.get(0);
47 try {
48 switch (funcName) {
49 case "cos":
50 return new Cosinus(arg);
51 case "sin":
52 return new Sinus(arg);
53 case "tan":
54 return new Tangente(arg);
55 case "acos":
56 return new Arccosinus(arg);
57 case "asin":
58 return new Arcsinus(arg);
59 case "atan":
60 return new Arctangente(arg);
61 case "cosh":
62 return new Cosh(arg);
63 case "sinh":
64 return new Sinh(arg);
65 case "tanh":
66 return new Tanh(arg);
67 case "sqrt":
68 return new Sqrt(arg);
69 case "ln":
70 return new Ln(arg);
71 default:
72 throw new UnsupportedOperationException("Function not implemented yet: " + funcName);
73 }
74 } catch (IllegalConstruction e) {
75 throw new RuntimeException(e);
76 }
77 }
78
79 if ("log".equals(funcName) && args.size() == 2) {
80 try {
81 return new Log(args.get(0), args.get(1));
82 } catch (IllegalConstruction e) {
83 throw new RuntimeException(e);
84 }
85 }
86
87 throw new UnsupportedOperationException("Invalid number of arguments for function " + funcName + ": " + args.size());
88 }
89
90
91
92
93 @Override
94 public Expression visitCompleteInfix(CompleteInfixContext ctx) {
95 return visit(ctx.expressionIN());
96 }
97
98
99
100
101 @Override
102 public Expression visitCompletePostfix(CompletePostfixContext ctx) {
103 return visit(ctx.expressionPOST());
104 }
105
106
107
108
109 @Override
110 public Expression visitCompletePrefix(CompletePrefixContext ctx) {
111 return visit(ctx.expressionPRE());
112 }
113
114
115
116
117 @Override
118 public Expression visitPre2Param(Pre2ParamContext ctx) {
119 List<Expression> args = new ArrayList<>();
120 args.add(visit(ctx.expressionPRE(0)));
121 args.add(visit(ctx.expressionPRE(1)));
122 return buildOperation(ctx.operator().getText(), args);
123 }
124
125
126
127
128
129
130 @Override
131 public Expression visitPrePlus2Param(PrePlus2ParamContext ctx) {
132 return buildOperation(ctx.operator().getText(), visitPreArgs(ctx.expressionPRE()));
133 }
134
135
136
137
138
139
140 @Override
141 public Expression visitPreMult(PreMultContext ctx) {
142 return buildOperation("*", visitPreArgs(ctx.expressionPRE()));
143 }
144
145
146
147
148
149
150 @Override
151 public Expression visitPreFunc(PreFuncContext ctx) {
152 return buildFunction(ctx.funcname().getText(), visitPreArgs(ctx.expressionPRE()));
153 }
154
155
156
157
158 @Override
159 public Expression visitPreAtom(PreAtomContext ctx) {
160 return visit(ctx.atom());
161 }
162
163
164
165
166 @Override
167 public Expression visitPreFunc1Param(PreFunc1ParamContext ctx) {
168 return buildFunction(ctx.funcname().getText(), List.of(visit(ctx.expressionPRE())));
169 }
170
171
172
173
174 @Override
175 public Expression visitPost2Param(Post2ParamContext ctx) {
176 List<Expression> args = new ArrayList<>();
177 args.add(visit(ctx.expressionPOST(0)));
178 args.add(visit(ctx.expressionPOST(1)));
179 return buildOperation(ctx.operator().getText(), args);
180 }
181
182
183
184
185
186
187 @Override
188 public Expression visitPostPlus2Param(PostPlus2ParamContext ctx) {
189 return buildOperation(ctx.operator().getText(), visitPostArgs(ctx.expressionPOST()));
190 }
191
192
193
194
195
196
197 @Override
198 public Expression visitPostMult(PostMultContext ctx) {
199 return buildOperation("*", visitPostArgs(ctx.expressionPOST()));
200 }
201
202
203
204
205
206
207 @Override
208 public Expression visitPostFunc(PostFuncContext ctx) {
209 return buildFunction(ctx.funcname().getText(), visitPostArgs(ctx.expressionPOST()));
210 }
211
212
213
214
215 @Override
216 public Expression visitPostAtom(PostAtomContext ctx) {
217 return visit(ctx.atom());
218 }
219
220
221
222
223 @Override
224 public Expression visitPostFunc1Param(PostFunc1ParamContext ctx) {
225 return buildFunction(ctx.funcname().getText(), List.of(visit(ctx.expressionPOST())));
226 }
227
228
229
230
231 @Override
232 public Expression visitINAddSub(INAddSubContext ctx) {
233 Expression result = visit(ctx.multExp(0));
234 for (int i = 1; i < ctx.multExp().size(); i++) {
235 String op = ctx.getChild(2 * i - 1).getText();
236 List<Expression> args = List.of(result, visit(ctx.multExp(i)));
237 result = buildOperation(op, args);
238 }
239 return result;
240 }
241
242
243
244
245 @Override
246 public Expression visitINTimesDiv(INTimesDivContext ctx) {
247 Expression result = visit(ctx.powExp(0));
248 for (int i = 1; i < ctx.powExp().size(); i++) {
249 String op = ctx.getChild(2 * i - 1).getText();
250 List<Expression> args = List.of(result, visit(ctx.powExp(i)));
251 result = buildOperation(op, args);
252 }
253 return result;
254 }
255
256
257
258
259 @Override
260 public Expression visitINMult(INMultContext ctx) {
261 List<Expression> factors = new ArrayList<>();
262 for (int i = 0; i < ctx.powExp().size(); i++) {
263 factors.add(visit(ctx.powExp(i)));
264 }
265 if (factors.size() == 1) {
266 return factors.get(0);
267 }
268 return buildOperation("*", factors);
269 }
270
271
272
273
274 @Override
275 public Expression visitINPow(INPowContext ctx) {
276 int atomCount = ctx.atomIN().size();
277 if (atomCount == 1) {
278 return visit(ctx.atomIN(0));
279 }
280
281
282 Expression result = visit(ctx.atomIN(atomCount - 1));
283 for (int i = atomCount - 2; i >= 0; i--) {
284 result = buildOperation("**", List.of(visit(ctx.atomIN(i)), result));
285 }
286 return result;
287 }
288
289
290
291
292 @Override
293 public Expression visitINSignedAtom(INSignedAtomContext ctx) {
294 List<Expression> factors = new ArrayList<>();
295
296 factors.add(visit(ctx.atom()));
297 for (int i = 0; i < ctx.constant().size(); i++) {
298 factors.add(visit(ctx.constant(i)));
299 }
300
301 Expression expression;
302 if (factors.size() == 1) {
303 expression = factors.get(0);
304 } else {
305 expression = buildOperation("*", factors);
306 }
307
308
309 for (int i = 0; i < ctx.MINUS().size(); i++) {
310 expression = buildOperation("-", List.of(new IntegerAtom(0), expression));
311 }
312
313 return expression;
314 }
315
316
317
318
319 @Override
320 public Expression visitINImplicitMult(INImplicitMultContext ctx) {
321 List<Expression> factors = new ArrayList<>();
322
323 int expIdx = 0;
324 if (!ctx.expressionIN().isEmpty() && "(".equals(ctx.getChild(0).getText())) {
325 factors.add(visit(ctx.expressionIN(expIdx++)));
326 }
327
328 factors.add(visit(ctx.atom()));
329
330 for (int i = 0; i < ctx.constant().size(); i++) {
331 factors.add(visit(ctx.constant(i)));
332 }
333
334 while (expIdx < ctx.expressionIN().size()) {
335 factors.add(visit(ctx.expressionIN(expIdx++)));
336 }
337
338 if (factors.size() == 1) {
339 return factors.get(0);
340 }
341 return buildOperation("*", factors);
342 }
343
344
345
346
347 @Override
348 public Expression visitINParenthesis(INParenthesisContext ctx) {
349 return visit(ctx.expressionIN());
350 }
351
352
353
354
355 @Override
356 public Expression visitINFunction(INFunctionContext ctx) {
357 return visit(ctx.functionIN());
358 }
359
360
361
362
363 @Override
364 public Expression visitAtomComplex(AtomComplexContext ctx) {
365 return visit(ctx.complex());
366 }
367
368
369
370
371 @Override
372 public Expression visitAtomNumber(AtomNumberContext ctx) {
373 return visit(ctx.number());
374 }
375
376
377
378
379 @Override
380 public Expression visitNumberConstant(NumberConstantContext ctx) {
381 return visit(ctx.constant());
382 }
383
384
385
386
387 @Override
388 public Expression visitNumberReal(NumberRealContext ctx) {
389 return visit(ctx.real());
390 }
391
392
393
394
395 @Override
396 public Expression visitNumberScientific(NumberScientificContext ctx) {
397 return visit(ctx.scientific());
398 }
399
400
401
402
403 @Override
404 public Expression visitScientificNumber(ScientificNumberContext ctx) {
405 return new Real(new BigDecimal(ctx.getText()));
406 }
407
408
409
410
411 @Override
412 public Expression visitRealNumber(RealNumberContext ctx) {
413 if (ctx.DOT() == null) {
414 return new IntegerAtom(Integer.parseInt(ctx.INT(0).getText()));
415 }
416 return new Real(new BigDecimal(ctx.getText()));
417 }
418
419
420
421
422 @Override
423 public Expression visitComplexNumber(ComplexNumberContext ctx) {
424 List<Expression> factors = new ArrayList<>();
425
426 if (ctx.number() != null) {
427 factors.add(visit(ctx.number()));
428 }
429
430 for (int i = 0; i < ctx.constant().size(); i++) {
431 factors.add(visit(ctx.constant(i)));
432 }
433
434 factors.add(new Complex(0.0, 1.0));
435
436 if (factors.size() == 1) {
437 return factors.get(0);
438 }
439 return buildOperation("*", factors);
440 }
441
442
443
444
445 @Override
446 public Expression visitConstPi(ConstPiContext ctx) {
447 return new Real(Math.PI);
448 }
449
450
451
452
453 @Override
454 public Expression visitConstEuler(ConstEulerContext ctx) {
455 return new Real(Math.E);
456 }
457
458
459
460
461 @Override
462 public Expression visitInfixFunctionCall(InfixFunctionCallContext ctx) {
463 List<Expression> args = new ArrayList<>();
464 for (calculator.calculatorParser.ExpressionINContext expCtx : ctx.expressionIN()) {
465 args.add(visit(expCtx));
466 }
467 return buildFunction(ctx.funcname().getText(), args);
468 }
469
470
471
472
473 private List<Expression> visitPreArgs(List<? extends calculator.calculatorParser.ExpressionPREContext> contexts) {
474 List<Expression> args = new ArrayList<>();
475 for (int i = 0; i < contexts.size(); i++) {
476 args.add(visit(contexts.get(i)));
477 }
478 return args;
479 }
480
481
482
483
484 private List<Expression> visitPostArgs(List<? extends calculator.calculatorParser.ExpressionPOSTContext> contexts) {
485 List<Expression> args = new ArrayList<>();
486 for (int i = 0; i < contexts.size(); i++) {
487 args.add(visit(contexts.get(i)));
488 }
489 return args;
490 }
491
492 }