1 module source.lexnumeric; 2 3 mixin template LexNumericImpl( 4 Token, 5 alias IntegralSuffixes, 6 alias FloatSuffixes, 7 alias CustomIntegralSuffixes = null, 8 alias CustomFloatSuffixes = null, 9 ) { 10 /** 11 * Integral and float literals. 12 */ 13 Token lexIntegralSuffix(uint begin) { 14 return lexLiteralSuffix!(IntegralSuffixes, CustomIntegralSuffixes)(begin); 15 } 16 17 Token lexFloatSuffix(uint begin) { 18 return lexLiteralSuffix!(FloatSuffixes, CustomFloatSuffixes)(begin); 19 } 20 21 Token lexFloatLiteral(alias isFun, alias popFun, char E)(uint begin) { 22 popFun(); 23 24 bool isFloat = false; 25 if (frontChar == '.') { 26 auto savePoint = index; 27 28 popChar(); 29 if (frontChar == '.') { 30 index = savePoint; 31 goto LexSuffix; 32 } 33 34 auto floatSavePoint = index; 35 36 popSkippableChars(); 37 38 if (wantIdentifier(frontChar)) { 39 index = savePoint; 40 goto LexSuffix; 41 } 42 43 index = floatSavePoint; 44 isFloat = true; 45 46 if (isFun(frontChar)) { 47 popChar(); 48 popFun(); 49 } 50 } 51 52 if ((frontChar | 0x20) == E) { 53 isFloat = true; 54 popChar(); 55 56 auto c = frontChar; 57 if (c == '+' || c == '-') { 58 popChar(); 59 } 60 61 popFun(); 62 } 63 64 LexSuffix: 65 return isFloat ? lexFloatSuffix(begin) : lexIntegralSuffix(begin); 66 } 67 68 /** 69 * Binary literals. 70 */ 71 static bool isBinary(char c) { 72 return c == '0' || c == '1'; 73 } 74 75 void popBinary() { 76 auto c = frontChar; 77 while (isBinary(c) || c == '_') { 78 popChar(); 79 c = frontChar; 80 } 81 } 82 83 Token lexNumeric(string s : "0B")() { 84 return lexNumeric!"0b"(); 85 } 86 87 Token lexNumeric(string s : "0b")() { 88 uint begin = index - 2; 89 90 while (frontChar == '_') { 91 popChar(); 92 } 93 94 if (!isBinary(frontChar)) { 95 return getError(begin, "Invalid binary sequence."); 96 } 97 98 popBinary(); 99 return lexIntegralSuffix(begin); 100 } 101 102 /** 103 * Hexadecimal literals. 104 */ 105 static bool isHexadecimal(char c) { 106 auto hc = c | 0x20; 107 return (c >= '0' && c <= '9') || (hc >= 'a' && hc <= 'f'); 108 } 109 110 void popHexadecimal() { 111 auto c = frontChar; 112 while (isHexadecimal(c) || c == '_') { 113 popChar(); 114 c = frontChar; 115 } 116 } 117 118 Token lexNumeric(string s : "0X")() { 119 return lexNumeric!"0x"(); 120 } 121 122 Token lexNumeric(string s : "0x")() { 123 uint begin = index - 2; 124 125 while (frontChar == '_') { 126 popChar(); 127 } 128 129 if (!isHexadecimal(frontChar)) { 130 return getError(begin, "Invalid hexadecimal sequence."); 131 } 132 133 return lexFloatLiteral!(isHexadecimal, popHexadecimal, 'p')(begin); 134 } 135 136 /** 137 * Decimal literals. 138 */ 139 static bool isDecimal(char c) { 140 return c >= '0' && c <= '9'; 141 } 142 143 void popDecimal() { 144 auto c = frontChar; 145 while (isDecimal(c) || c == '_') { 146 popChar(); 147 c = frontChar; 148 } 149 } 150 151 auto lexNumeric(string s)() if (s.length == 1 && isDecimal(s[0])) { 152 return lexNumeric(s[0]); 153 } 154 155 auto lexNumeric(char c) in { 156 assert(isDecimal(c)); 157 } do { 158 return lexFloatLiteral!(isDecimal, popDecimal, 'e')(index - 1); 159 } 160 }