1 module calcool.parselets;
2 
3 import calcool.expression;
4 import calcool.token;
5 import calcool.parser;
6 import calcool.exceptions;
7 
8 enum Precedence : uint {
9     START = 0,
10     ADD_AND_MINUS = 1,
11     MULT_AND_DIV,
12     POWER,
13     NAME_AND_NEGATE,
14     FUNC,
15     GROUP
16 }
17 
18 interface Parselet {
19     Precedence getPrecedence() immutable;
20 }
21 
22 interface PrefixParselet : Parselet {
23     Expression parse(Parser, Token) immutable;
24 }
25 
26 interface InfixParselet : Parselet {
27     Expression parse(Parser, Expression, Token) immutable;
28 }
29 
30 public:
31 class NumberParselet : PrefixParselet {
32     override Precedence getPrecedence() immutable {
33         return Precedence.NAME_AND_NEGATE;
34     }
35 
36     override Expression parse(Parser, Token token) immutable {
37         if (token.type != TokenType.NUMBER) {
38             throw new ParseException("Unknown token passed to number parselet");
39         }
40 
41         import std.conv : to;
42 
43         return new NumberExpression(token.value.to!real);
44     }
45 }
46 
47 class NegateParselet : PrefixParselet {
48     override Precedence getPrecedence() immutable {
49         return Precedence.NAME_AND_NEGATE;
50     }
51 
52     override Expression parse(Parser p, Token token) immutable {
53         return new NegateExpression(p.parseExpression(Precedence.NAME_AND_NEGATE));
54     }
55 }
56 
57 class EolParselet : PrefixParselet {
58     override Precedence getPrecedence() immutable {
59         return Precedence.START;
60     }
61 
62     override Expression parse(Parser p, Token token) immutable {
63         return new EolExpression();
64     }
65 }
66 
67 class FuncParselet : PrefixParselet {
68     override Precedence getPrecedence() immutable {
69         return Precedence.FUNC;
70     }
71 
72     override Expression parse(Parser p, Token token) immutable {
73         p.expect(TokenType.PR_OPEN);
74         auto param = p.parseGroupExpression();
75         return new FuncExpression(token.value, param);
76     }
77 }
78 
79 class GroupParselet : PrefixParselet {
80     override Precedence getPrecedence() immutable {
81         return Precedence.GROUP;
82     }
83 
84     override Expression parse(Parser p, Token token) immutable {
85         return new GroupExpression(p.parseGroupExpression());
86     }
87 }
88 
89 class MultDivParselet : InfixParselet {
90     override Precedence getPrecedence() immutable {
91         return Precedence.MULT_AND_DIV;
92     }
93 
94     override Expression parse(Parser p, Expression left, Token token) immutable {
95         auto right = p.parseExpression(Precedence.MULT_AND_DIV);
96         switch (token.type) {
97         case TokenType.OP_MULT:
98             return new OperatorExpression!"*"(left, right);
99         case TokenType.OP_DIV:
100             return new OperatorExpression!"/"(left, right);
101         default:
102             throw new ParseException("Unknown token for MultDiv parselet");
103         }
104     }
105 }
106 
107 class AddMinusParselet : InfixParselet {
108     override Precedence getPrecedence() immutable {
109         return Precedence.ADD_AND_MINUS;
110     }
111 
112     override Expression parse(Parser p, Expression left, Token token) immutable {
113         auto right = p.parseExpression(Precedence.ADD_AND_MINUS);
114         switch (token.type) {
115         case TokenType.OP_ADD:
116             return new OperatorExpression!"+"(left, right);
117         case TokenType.OP_MINUS:
118             return new OperatorExpression!"-"(left, right);
119         default:
120             throw new ParseException("Unknown token for AddMinus parselet");
121         }
122     }
123 }
124 
125 class PowerParselet : InfixParselet {
126     override Precedence getPrecedence() immutable {
127         return Precedence.POWER;
128     }
129 
130     override Expression parse(Parser p, Expression left, Token token) immutable {
131         return new OperatorExpression!"^^"(left, p.parseExpression(Precedence.POWER));
132     }
133 }