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 }