aboutsummaryrefslogtreecommitdiff
path: root/src/lexer/numbers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lexer/numbers.rs')
-rw-r--r--src/lexer/numbers.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/lexer/numbers.rs b/src/lexer/numbers.rs
new file mode 100644
index 000000000..4c7edfe1c
--- /dev/null
+++ b/src/lexer/numbers.rs
@@ -0,0 +1,68 @@
1use lexer::ptr::Ptr;
2use lexer::classes::*;
3
4use {SyntaxKind};
5use syntax_kinds::*;
6
7pub(crate) fn scan_number(c: char, ptr: &mut Ptr) -> SyntaxKind {
8 if c == '0' {
9 match ptr.next().unwrap_or('\0') {
10 'b' | 'o' => {
11 ptr.bump();
12 scan_digits(ptr, false);
13 }
14 'x' => {
15 ptr.bump();
16 scan_digits(ptr, true);
17 }
18 '0'...'9' | '_' | '.' | 'e' | 'E' => {
19 scan_digits(ptr, true);
20 }
21 _ => return INT_NUMBER,
22 }
23 } else {
24 scan_digits(ptr, false);
25 }
26
27 // might be a float, but don't be greedy if this is actually an
28 // integer literal followed by field/method access or a range pattern
29 // (`0..2` and `12.foo()`)
30 if ptr.next_is('.') && !(ptr.nnext_is('.') || ptr.nnext_is_p(is_ident_start)) {
31 // might have stuff after the ., and if it does, it needs to start
32 // with a number
33 ptr.bump();
34 scan_digits(ptr, false);
35 scan_float_exponent(ptr);
36 return FLOAT_NUMBER;
37 }
38 // it might be a float if it has an exponent
39 if ptr.next_is('e') || ptr.next_is('E') {
40 scan_float_exponent(ptr);
41 return FLOAT_NUMBER;
42 }
43 INT_NUMBER
44}
45
46fn scan_digits(ptr: &mut Ptr, allow_hex: bool) {
47 while let Some(c) = ptr.next() {
48 match c {
49 '_' | '0'...'9' => {
50 ptr.bump();
51 }
52 'a'...'f' | 'A' ... 'F' if allow_hex => {
53 ptr.bump();
54 }
55 _ => return
56 }
57 }
58}
59
60fn scan_float_exponent(ptr: &mut Ptr) {
61 if ptr.next_is('e') || ptr.next_is('E') {
62 ptr.bump();
63 if ptr.next_is('-') || ptr.next_is('+') {
64 ptr.bump();
65 }
66 scan_digits(ptr, false);
67 }
68}