blob: e68983b8560cef153dfd55c134e6c40784e09b7e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package ch.bfh.parser;
import ch.bfh.lexer.CalculatorLexer;
import ch.bfh.lexer.Token;
import java.util.ArrayList;
class ExpressionParser extends Parser {
protected ArrayList<Parser> parsers = new ArrayList<>();
protected ArrayList<Token> ops = new ArrayList<>();
private boolean isParenthesised = false;
protected ExpressionParser(CalculatorLexer cl, Token lastToken, boolean isParenthesised) {
this.cl = cl;
this.lastToken = lastToken;
this.isParenthesised = isParenthesised; //If an expression starts with the lastToken set as '(' it could mean that the Expression first term will be a parenthesised expression
parse(); //But it could also mean that this Expression is the parenthesised one, that is why this variable is required.
}
@Override
protected void parse() {
Token token;
if(lastToken != null && !isParenthesised)
token = lastToken;
else
token = cl.nextToken();
TermParser l = null;
TermParser r = null; // left and right Terms
Token op = null; // operation of the current l and right expressions
loop:
while (token != null && token.type != Token.EOL) {
switch (token.type) {
case Token.ADD: // '+' is not authorised if not op
if (l != null && op == null) { // if the '+' sign is between two term (op)
op = token;
this.ops.add(op);
} else if (l != null && r != null) { // if we already found a 'l op r' we roll
l = r;
r = null;
op = token;
this.ops.add(op);
}else if (l == null)
throw new ParserException("Redundant use of '+' is forbidden.");
else
throw new ParserException(token, "repetition of operator -> a term was expected.");
break;
case Token.SUB:
if (l != null && op == null) { // if the '-' sign is between two term (op)
op = token;
this.ops.add(op);
break;
} else if (l != null && r != null) { // if we already found a 'l op r' we roll
l = r;
r = null;
op = token;
this.ops.add(op);
} // Then the '-' is the start of a new expression and not an operation
case Token.PAL:
case Token.ID:
case Token.NUM:
if (l == null) {
l = new TermParser(cl, token);
this.parsers.add(l);
token = l.lastToken;
} else {
r = new TermParser(cl, token);
this.parsers.add(r);
token = r.lastToken;
}
continue loop;
case Token.PAR:
if (lastToken != null && lastToken.type == Token.PAL) { // if equal to '(' it means it was created by a Factor
lastToken = token;
break loop;
} else
throw new ParserException("No matching opening parenthesis were found.");
case Token.MUL:
case Token.DIV:
throw new ParserException(token,"a term was expected.");
case Token.EQU:
case Token.LET:
throw new ParserException("The inputted token '"+token.str+"' can only be placed in a variable declaration context (let var = Expression).");
case Token.END:
throw new ParserException("The keyword 'exit' can only be placed at the beginning of an expression.");
}
token = cl.nextToken();
}
if (op != null && r == null)
throw new ParserException("Missing term after the last operator '"+op.str+"'.");
}
@Override
public double getValue(){
double result = 0.0;
if (!this.parsers.isEmpty()) {
result = this.parsers.get(0).getValue();
for (int i = 1; i < this.parsers.size(); i++) {
switch (this.ops.get(i-1).type){
case Token.ADD:
result += this.parsers.get(i).getValue();
break;
case Token.SUB:
result -= this.parsers.get(i).getValue();
break;
}
}
}
return result;
}
}
|