@@ -196,11 +196,78 @@ export class Tokenizer {
196196 private isDigit ( c : string ) : boolean {
197197 return / ^ [ 0 - 9 ] / . test ( c ) ;
198198 }
199-
199+
200+ private isHexa ( c : string ) : boolean {
201+ return / ^ [ 0 - 9 A - F ] $ / i. test ( c ) ;
202+ }
203+
204+ private isOcta ( c : string ) : boolean {
205+ return / ^ [ 0 - 7 ] / . test ( c ) ;
206+ }
207+
208+ private isBinary ( c : string ) : boolean {
209+ return / ^ [ 0 - 1 ] / . test ( c ) ;
210+ }
211+
200212 private isIdentifier ( c : string ) : boolean {
201213 return c === '_' || this . isAlpha ( c ) || this . isDigit ( c ) ;
202214 }
203-
215+
216+ private baseNumber ( ) {
217+ switch ( this . peek ( ) ) {
218+ case 'x' :
219+ this . advance ( ) ;
220+ if ( ! this . isHexa ( this . peek ( ) ) ) {
221+ throw new TokenizerErrors . InvalidNumberError ( this . line , this . col , this . source , this . start , this . current ) ;
222+ }
223+ while ( this . isHexa ( this . peek ( ) ) ) {
224+ this . advance ( ) ;
225+ }
226+ break ;
227+ case 'o' :
228+ this . advance ( ) ;
229+ if ( ! this . isOcta ( this . peek ( ) ) ) {
230+ throw new TokenizerErrors . InvalidNumberError ( this . line , this . col , this . source , this . start , this . current ) ;
231+ }
232+ while ( this . isOcta ( this . peek ( ) ) ) {
233+ this . advance ( ) ;
234+ }
235+ break ;
236+ case 'b' :
237+ this . advance ( ) ;
238+ if ( ! this . isBinary ( this . peek ( ) ) ) {
239+ throw new TokenizerErrors . InvalidNumberError ( this . line , this . col , this . source , this . start , this . current ) ;
240+ }
241+ while ( this . isBinary ( this . peek ( ) ) ) {
242+ this . advance ( ) ;
243+ }
244+ break ;
245+ default :
246+ while ( this . isDigit ( this . peek ( ) ) ) {
247+ this . advance ( ) ;
248+ }
249+ if ( this . peek ( ) === '.' ) {
250+ this . advance ( ) ;
251+ while ( this . isDigit ( this . peek ( ) ) ) {
252+ this . advance ( ) ;
253+ }
254+ }
255+ if ( this . peek ( ) === 'e' ) {
256+ this . advance ( ) ;
257+ if ( this . peek ( ) === '-' ) {
258+ this . advance ( ) ;
259+ }
260+ if ( ! this . isDigit ( this . peek ( ) ) ) {
261+ throw new TokenizerErrors . InvalidNumberError ( this . line , this . col , this . source , this . start , this . current ) ;
262+ }
263+ while ( this . isDigit ( this . peek ( ) ) ) {
264+ this . advance ( ) ;
265+ }
266+ }
267+ }
268+ this . addToken ( TokenType . NUMBER ) ;
269+ }
270+
204271 private number ( ) {
205272 while ( this . isDigit ( this . peek ( ) ) ) {
206273 this . advance ( ) ;
@@ -212,6 +279,20 @@ export class Tokenizer {
212279 this . advance ( ) ;
213280 }
214281 }
282+ // Exponent part
283+ if ( this . peek ( ) === 'e' ) {
284+ this . advance ( ) ;
285+ if ( this . peek ( ) === '-' ) {
286+ this . advance ( ) ;
287+ }
288+ if ( ! this . isDigit ( this . peek ( ) ) ) {
289+ throw new TokenizerErrors . InvalidNumberError ( this . line , this . col , this . source , this . start , this . current ) ;
290+ }
291+ while ( this . isDigit ( this . peek ( ) ) ) {
292+ this . advance ( ) ;
293+ }
294+ }
295+
215296 this . addToken ( TokenType . NUMBER ) ;
216297 }
217298
@@ -356,6 +437,8 @@ export class Tokenizer {
356437 break ;
357438 // Number... I wish JS had match statements :(
358439 case '0' :
440+ this . baseNumber ( ) ;
441+ break ;
359442 case '1' :
360443 case '2' :
361444 case '3' :
0 commit comments