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 }