Krolyxon
Commit 2a9918f

Branches

Refs →

jcalParser.java

143 lines · 3.9 KB · Java

1/* Todo
2* - Add support for trigonometric functions
3* - Remove all edge cases
4*/
5
6import java.util.Stack;
7import java.util.StringJoiner;
8
9public class Parser {
10 private String expr;
11 private Stack<Character> operatorStack;
12
13 public Parser(String infixExpr) {
14 expr = infixExpr.trim().replaceAll("\\s", ""); // remove whitespaces
15 }
16
17 public static boolean isOperand(char c) {
18 switch (c) {
19 case '0':
20 case '1':
21 case '2':
22 case '3':
23 case '4':
24 case '5':
25 case '6':
26 case '7':
27 case '8':
28 case '9':
29 return true;
30 default:
31 return false;
32 }
33 }
34
35 public static boolean isOperand(String c) {
36 return isOperand(c.charAt(0));
37 }
38
39 public int getPresedence(char c) {
40 switch (c) {
41 case '^':
42 return 3;
43 case '/':
44 return 2;
45 case '*':
46 return 2;
47 case '+':
48 return 1;
49 case '-':
50 return 1;
51 default:
52 return -1;
53 }
54 }
55
56 public boolean hasLeftAssociativity(char c) {
57 if (c == '^') {
58 return false;
59 } else {
60 return true;
61 }
62 }
63
64 public String toPostFix() {
65 operatorStack = new Stack<>();
66 StringJoiner output = new StringJoiner(" ");
67 StringBuilder operand = new StringBuilder();
68 char[] infix = expr.replaceAll(" ", "").toCharArray();
69
70 // Main Expression Iteration
71 for (int i = 0; i < infix.length; i++) {
72 char c = infix[i];
73 if (isOperand(c)) {
74 operand.append(infix[i]);
75 if (i < infix.length - 1) {
76 continue;
77 }
78 }
79
80 if (operand.length() > 0) {
81 output.add(operand.toString());
82 operand = new StringBuilder();
83 }
84
85 if (c == '(') {
86 operatorStack.push(c);
87 } else if (c == ')') {
88 while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
89 output.add(operatorStack.pop().toString());
90 }
91 operatorStack.pop();
92 } else {
93 while (!operatorStack.isEmpty() && getPresedence(c) <= getPresedence((char) operatorStack.peek())
94 && hasLeftAssociativity(c)) {
95 output.add(operatorStack.pop().toString());
96 }
97 operatorStack.push(c);
98 }
99 }
100
101 while (!operatorStack.isEmpty()) {
102 if (operatorStack.peek() == '(') {
103 return "This expression is invalid";
104 }
105 output.add(operatorStack.pop().toString());
106 }
107
108 // last digit gets duplicate entry for some reason, so have to remove it.
109 String op = output.toString();
110 return op.substring(0, op.length() -2);
111 }
112
113 private Double evaluate(String operator, Double op1, Double op2) {
114 switch (operator.charAt(0)) {
115 case '+':
116 return op2 + op1;
117 case '-':
118 return op1 - op2;
119 case '*':
120 return op2 * op1;
121 case '/':
122 return op1 / op2;
123 case '^':
124 return (Math.pow(op2, op1));
125 default:
126 return 0.0;
127 }
128 }
129
130 public double evalExpr(String postfix) {
131 Stack<Double> stack = new Stack<Double>();
132 for (String c : postfix.split(" ")) {
133 if (isOperand(c)) {
134 stack.push(Double.parseDouble(c));
135 } else {
136 Double op1 = (Double) (stack.pop());
137 Double op2 = (Double) (stack.pop());
138 stack.push(evaluate(c, op2, op1));
139 }
140 }
141 return stack.pop();
142 }
143}