aboutsummaryrefslogtreecommitdiff
path: root/calculator-java/src/main/java/ch/bfh/parser/FactorParser.java
blob: 282a05ea8b96c4695e31e7752b8240237c7e64f2 (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
package ch.bfh.parser;

import ch.bfh.lexer.CalculatorLexer;
import ch.bfh.lexer.Token;

class FactorParser extends Parser {

    ExpressionParser expression; // only used when parenthesis are found
    boolean isNegative = false;
    boolean somethingWasParsed = false;

    public FactorParser(CalculatorLexer cl, Token lastToken) {
        this.cl = cl;
        this.lastToken = lastToken;
        parse();
    }

    @Override
    protected void parse() {
        Token token = lastToken;
        lastToken = null;
        loop:
        while (token != null && token.type != Token.EOL) {
            switch (token.type) {
                case Token.MUL:
                case Token.DIV:
                case Token.ADD:
                    if (somethingWasParsed) { // finished parsing the Factor
                        lastToken = token; // sending the token to the parent
                        break loop;
                    } else
                        throw new ParserException("Empty expression before '" + token.str + "'.");
                case Token.SUB:
                    if (!somethingWasParsed)
                        if (!isNegative)
                            isNegative = true;
                        else
                            throw new ParserException("A factor cannot contain two '-'.");
                    else { // Meaning we could have parsed '-4' or '4' and '-' is the next digit which is op for the overall expression
                        lastToken = token;
                        break loop;
                    }
                    break;
                case Token.NUM:
                    if (!somethingWasParsed) {
                        value = token.value;
                        somethingWasParsed = true;
                    } else
                        throw new ParserException("Missing operator between the two Factors.");
                    break;
                case Token.ID:
                    if (!somethingWasParsed) {
                        expression = variables.get(token.str);
                        if (expression == null)
                            throw new ParserException("'"+token.str+"' is not yet defined.");
                        somethingWasParsed = true;
                    } else
                        throw new ParserException("Missing operator between the two Factors.");
                    break;
                case Token.PAL:
                    if (!somethingWasParsed) {
                        expression = new ExpressionParser(cl, token, true);
                        if (expression.lastToken.type != Token.PAR)
                            throw new ParserException("No matching closing parenthesis were found.");
                        somethingWasParsed = true;
                    } else
                        throw new ParserException("Missing operator between the two Factors.");
                    break;
                case Token.PAR:  // Going as high as possible --> possibly the end of an expression created by a Factor :)
                    if (somethingWasParsed)
                        lastToken = token;
                    else throw new ParserException("Missing expression before closing the parenthesis.");
                    break loop;
                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();
        }
    }

    @Override
    public double getValue() {

        if (expression != null)
            if (isNegative)
                return expression.getValue() * (-1);
            else
                return expression.getValue();
        if (isNegative)
            return value * (-1);
        return value;
    }
}