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 IdentifierParselet : PrefixParselet { 48 override Precedence getPrecedence() immutable { 49 return Precedence.NAME_AND_NEGATE; 50 } 51 52 override Expression parse(Parser p, Token token) immutable { 53 if (auto val = token.value in p.getVariables()) { 54 return new NumberExpression(*val); 55 } 56 return new ConstantExpression(token.value); 57 } 58 } 59 60 class NegateParselet : PrefixParselet { 61 override Precedence getPrecedence() immutable { 62 return Precedence.NAME_AND_NEGATE; 63 } 64 65 override Expression parse(Parser p, Token token) immutable { 66 return new NegateExpression(p.parseExpression(Precedence.NAME_AND_NEGATE)); 67 } 68 } 69 70 class EolParselet : PrefixParselet { 71 override Precedence getPrecedence() immutable { 72 return Precedence.START; 73 } 74 75 override Expression parse(Parser p, Token token) immutable { 76 return new EolExpression(); 77 } 78 } 79 80 class FuncParselet : PrefixParselet { 81 override Precedence getPrecedence() immutable { 82 return Precedence.FUNC; 83 } 84 85 override Expression parse(Parser p, Token token) immutable { 86 p.expect(TokenType.PR_OPEN); 87 auto param = p.parseGroupExpression(); 88 return new FuncExpression(token.value, param); 89 } 90 } 91 92 class GroupParselet : PrefixParselet { 93 override Precedence getPrecedence() immutable { 94 return Precedence.GROUP; 95 } 96 97 override Expression parse(Parser p, Token token) immutable { 98 return new GroupExpression(p.parseGroupExpression()); 99 } 100 } 101 102 class MultDivParselet : InfixParselet { 103 override Precedence getPrecedence() immutable { 104 return Precedence.MULT_AND_DIV; 105 } 106 107 override Expression parse(Parser p, Expression left, Token token) immutable { 108 auto right = p.parseExpression(Precedence.MULT_AND_DIV); 109 switch (token.type) { 110 case TokenType.OP_MULT: 111 return new OperatorExpression!"*"(left, right); 112 case TokenType.OP_DIV: 113 return new OperatorExpression!"/"(left, right); 114 default: 115 throw new ParseException("Unknown token for MultDiv parselet"); 116 } 117 } 118 } 119 120 class AddMinusParselet : InfixParselet { 121 override Precedence getPrecedence() immutable { 122 return Precedence.ADD_AND_MINUS; 123 } 124 125 override Expression parse(Parser p, Expression left, Token token) immutable { 126 auto right = p.parseExpression(Precedence.ADD_AND_MINUS); 127 switch (token.type) { 128 case TokenType.OP_ADD: 129 return new OperatorExpression!"+"(left, right); 130 case TokenType.OP_MINUS: 131 return new OperatorExpression!"-"(left, right); 132 default: 133 throw new ParseException("Unknown token for AddMinus parselet"); 134 } 135 } 136 } 137 138 class PowerParselet : InfixParselet { 139 override Precedence getPrecedence() immutable { 140 return Precedence.POWER; 141 } 142 143 override Expression parse(Parser p, Expression left, Token token) immutable { 144 return new OperatorExpression!"^^"(left, p.parseExpression(Precedence.POWER)); 145 } 146 }