2
2
//! code is translated into seperate tokens.
3
3
4
4
pub use super :: token:: Tok ;
5
+ use num_bigint:: BigInt ;
6
+ use num_traits:: Num ;
5
7
use std:: collections:: HashMap ;
6
8
use std:: str:: FromStr ;
7
9
@@ -280,10 +282,56 @@ where
280
282
}
281
283
282
284
fn lex_number ( & mut self ) -> Spanned < Tok > {
285
+ let start_pos = self . get_pos ( ) ;
286
+ if self . chr0 == Some ( '0' ) {
287
+ if self . chr1 == Some ( 'x' ) || self . chr1 == Some ( 'X' ) {
288
+ // Hex!
289
+ self . next_char ( ) ;
290
+ self . next_char ( ) ;
291
+ self . lex_number_radix ( start_pos, 16 )
292
+ } else if self . chr1 == Some ( 'o' ) || self . chr1 == Some ( 'O' ) {
293
+ // Octal style!
294
+ self . next_char ( ) ;
295
+ self . next_char ( ) ;
296
+ self . lex_number_radix ( start_pos, 8 )
297
+ } else if self . chr1 == Some ( 'b' ) || self . chr1 == Some ( 'B' ) {
298
+ // Binary!
299
+ self . next_char ( ) ;
300
+ self . next_char ( ) ;
301
+ self . lex_number_radix ( start_pos, 2 )
302
+ } else {
303
+ self . lex_normal_number ( )
304
+ }
305
+ } else {
306
+ self . lex_normal_number ( )
307
+ }
308
+ }
309
+
310
+ fn lex_number_radix ( & mut self , start_pos : Location , radix : u32 ) -> Spanned < Tok > {
283
311
let mut value_text = String :: new ( ) ;
284
312
313
+ loop {
314
+ if self . is_number ( radix) {
315
+ value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
316
+ } else if self . chr0 == Some ( '_' ) {
317
+ self . next_char ( ) ;
318
+ } else {
319
+ break ;
320
+ }
321
+ }
322
+
323
+ let end_pos = self . get_pos ( ) ;
324
+ let value = BigInt :: from_str_radix ( & value_text, radix) . unwrap ( ) ;
325
+ Ok ( ( start_pos, Tok :: Int { value : value } , end_pos) )
326
+ }
327
+
328
+ fn lex_normal_number ( & mut self ) -> Spanned < Tok > {
285
329
let start_pos = self . get_pos ( ) ;
286
- while self . is_number ( ) {
330
+
331
+ let mut value_text = String :: new ( ) ;
332
+
333
+ // Normal number:
334
+ while self . is_number ( 10 ) {
287
335
value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
288
336
}
289
337
@@ -292,7 +340,7 @@ where
292
340
// Take '.':
293
341
if self . chr0 == Some ( '.' ) {
294
342
value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
295
- while self . is_number ( ) {
343
+ while self . is_number ( 10 ) {
296
344
value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
297
345
}
298
346
}
@@ -306,18 +354,47 @@ where
306
354
value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
307
355
}
308
356
309
- while self . is_number ( ) {
357
+ while self . is_number ( 10 ) {
310
358
value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
311
359
}
312
360
}
313
361
314
- let end_pos = self . get_pos ( ) ;
315
362
let value = f64:: from_str ( & value_text) . unwrap ( ) ;
316
- Ok ( ( start_pos, Tok :: Float { value : value } , end_pos) )
363
+ // Parse trailing 'j':
364
+ if self . chr0 == Some ( 'j' ) {
365
+ self . next_char ( ) ;
366
+ let end_pos = self . get_pos ( ) ;
367
+ Ok ( (
368
+ start_pos,
369
+ Tok :: Complex {
370
+ real : 0.0 ,
371
+ imag : value,
372
+ } ,
373
+ end_pos,
374
+ ) )
375
+ } else {
376
+ let end_pos = self . get_pos ( ) ;
377
+ Ok ( ( start_pos, Tok :: Float { value : value } , end_pos) )
378
+ }
317
379
} else {
318
- let end_pos = self . get_pos ( ) ;
319
- let value = i32:: from_str ( & value_text) . unwrap ( ) ;
320
- Ok ( ( start_pos, Tok :: Int { value : value } , end_pos) )
380
+ // Parse trailing 'j':
381
+ if self . chr0 == Some ( 'j' ) {
382
+ self . next_char ( ) ;
383
+ let end_pos = self . get_pos ( ) ;
384
+ let imag = f64:: from_str ( & value_text) . unwrap ( ) ;
385
+ Ok ( (
386
+ start_pos,
387
+ Tok :: Complex {
388
+ real : 0.0 ,
389
+ imag : imag,
390
+ } ,
391
+ end_pos,
392
+ ) )
393
+ } else {
394
+ let end_pos = self . get_pos ( ) ;
395
+ let value = value_text. parse :: < BigInt > ( ) . unwrap ( ) ;
396
+ Ok ( ( start_pos, Tok :: Int { value : value } , end_pos) )
397
+ }
321
398
}
322
399
}
323
400
@@ -445,10 +522,25 @@ where
445
522
}
446
523
}
447
524
448
- fn is_number ( & self ) -> bool {
449
- match self . chr0 {
450
- Some ( '0' ...'9' ) => return true ,
451
- _ => return false ,
525
+ fn is_number ( & self , radix : u32 ) -> bool {
526
+ match radix {
527
+ 2 => match self . chr0 {
528
+ Some ( '0' ...'1' ) => return true ,
529
+ _ => return false ,
530
+ } ,
531
+ 8 => match self . chr0 {
532
+ Some ( '0' ...'7' ) => return true ,
533
+ _ => return false ,
534
+ } ,
535
+ 10 => match self . chr0 {
536
+ Some ( '0' ...'9' ) => return true ,
537
+ _ => return false ,
538
+ } ,
539
+ 16 => match self . chr0 {
540
+ Some ( '0' ...'9' ) | Some ( 'a' ...'f' ) | Some ( 'A' ...'F' ) => return true ,
541
+ _ => return false ,
542
+ } ,
543
+ x => unimplemented ! ( "Radix not implemented: {}" , x) ,
452
544
}
453
545
}
454
546
@@ -920,6 +1012,7 @@ where
920
1012
#[ cfg( test) ]
921
1013
mod tests {
922
1014
use super :: { make_tokenizer, NewlineHandler , Tok } ;
1015
+ use num_bigint:: BigInt ;
923
1016
use std:: iter:: FromIterator ;
924
1017
use std:: iter:: Iterator ;
925
1018
@@ -959,14 +1052,46 @@ mod tests {
959
1052
) ;
960
1053
}
961
1054
1055
+ #[ test]
1056
+ fn test_numbers ( ) {
1057
+ let source = String :: from ( "0x2f 0b1101 0 123 0.2 2j 2.2j" ) ;
1058
+ let tokens = lex_source ( & source) ;
1059
+ assert_eq ! (
1060
+ tokens,
1061
+ vec![
1062
+ Tok :: Int {
1063
+ value: BigInt :: from( 47 ) ,
1064
+ } ,
1065
+ Tok :: Int {
1066
+ value: BigInt :: from( 13 ) ,
1067
+ } ,
1068
+ Tok :: Int {
1069
+ value: BigInt :: from( 0 ) ,
1070
+ } ,
1071
+ Tok :: Int {
1072
+ value: BigInt :: from( 123 ) ,
1073
+ } ,
1074
+ Tok :: Float { value: 0.2 } ,
1075
+ Tok :: Complex {
1076
+ real: 0.0 ,
1077
+ imag: 2.0 ,
1078
+ } ,
1079
+ Tok :: Complex {
1080
+ real: 0.0 ,
1081
+ imag: 2.2 ,
1082
+ } ,
1083
+ ]
1084
+ ) ;
1085
+ }
1086
+
962
1087
macro_rules! test_line_comment {
963
1088
( $( $name: ident: $eol: expr, ) * ) => {
964
1089
$(
965
1090
#[ test]
966
1091
fn $name( ) {
967
1092
let source = String :: from( format!( r"99232 # {}" , $eol) ) ;
968
1093
let tokens = lex_source( & source) ;
969
- assert_eq!( tokens, vec![ Tok :: Int { value: 99232 } ] ) ;
1094
+ assert_eq!( tokens, vec![ Tok :: Int { value: BigInt :: from ( 99232 ) } ] ) ;
970
1095
}
971
1096
) *
972
1097
}
@@ -989,9 +1114,9 @@ mod tests {
989
1114
assert_eq!(
990
1115
tokens,
991
1116
vec![
992
- Tok :: Int { value: 123 } ,
1117
+ Tok :: Int { value: BigInt :: from ( 123 ) } ,
993
1118
Tok :: Newline ,
994
- Tok :: Int { value: 456 } ,
1119
+ Tok :: Int { value: BigInt :: from ( 456 ) } ,
995
1120
]
996
1121
)
997
1122
}
@@ -1016,11 +1141,17 @@ mod tests {
1016
1141
name: String :: from( "avariable" ) ,
1017
1142
} ,
1018
1143
Tok :: Equal ,
1019
- Tok :: Int { value: 99 } ,
1144
+ Tok :: Int {
1145
+ value: BigInt :: from( 99 )
1146
+ } ,
1020
1147
Tok :: Plus ,
1021
- Tok :: Int { value: 2 } ,
1148
+ Tok :: Int {
1149
+ value: BigInt :: from( 2 )
1150
+ } ,
1022
1151
Tok :: Minus ,
1023
- Tok :: Int { value: 0 } ,
1152
+ Tok :: Int {
1153
+ value: BigInt :: from( 0 )
1154
+ } ,
1024
1155
]
1025
1156
) ;
1026
1157
}
@@ -1045,7 +1176,7 @@ mod tests {
1045
1176
Tok :: Newline ,
1046
1177
Tok :: Indent ,
1047
1178
Tok :: Return ,
1048
- Tok :: Int { value: 99 } ,
1179
+ Tok :: Int { value: BigInt :: from ( 99 ) } ,
1049
1180
Tok :: Newline ,
1050
1181
Tok :: Dedent ,
1051
1182
]
@@ -1088,7 +1219,7 @@ mod tests {
1088
1219
Tok :: Newline ,
1089
1220
Tok :: Indent ,
1090
1221
Tok :: Return ,
1091
- Tok :: Int { value: 99 } ,
1222
+ Tok :: Int { value: BigInt :: from ( 99 ) } ,
1092
1223
Tok :: Newline ,
1093
1224
Tok :: Dedent ,
1094
1225
Tok :: Dedent ,
@@ -1120,9 +1251,9 @@ mod tests {
1120
1251
} ,
1121
1252
Tok :: Equal ,
1122
1253
Tok :: Lsqb ,
1123
- Tok :: Int { value: 1 } ,
1254
+ Tok :: Int { value: BigInt :: from ( 1 ) } ,
1124
1255
Tok :: Comma ,
1125
- Tok :: Int { value: 2 } ,
1256
+ Tok :: Int { value: BigInt :: from ( 2 ) } ,
1126
1257
Tok :: Rsqb ,
1127
1258
Tok :: Newline ,
1128
1259
]
0 commit comments