about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2020-11-28T16·32+0100
committertazjin <mail@tazj.in>2020-11-28T16·55+0000
commit97505eb1e1de6eb09c786fff0042767ba413ec76 (patch)
tree9f2df91024206b11c9de6fc2566e1ff275586953
parent47aa92b87d235e22974efb1b8f495c39f4b92a71 (diff)
feat(tazjin/rlox): Implement number scanning r/1954
Change-Id: Ide0126d1c2274d56903092816ff9cd531c03f513
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2191
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
-rw-r--r--users/tazjin/rlox/src/scanner.rs38
1 files changed, 36 insertions, 2 deletions
diff --git a/users/tazjin/rlox/src/scanner.rs b/users/tazjin/rlox/src/scanner.rs
index 187ccb2f61..c6db9de8c5 100644
--- a/users/tazjin/rlox/src/scanner.rs
+++ b/users/tazjin/rlox/src/scanner.rs
@@ -28,7 +28,7 @@ pub enum TokenKind {
     // Literals.
     Identifier,
     String(String),
-    Number,
+    Number(f64),
 
     // Keywords.
     And,
@@ -127,6 +127,8 @@ impl<'a> Scanner<'a> {
 
             '"' => self.scan_string(),
 
+            digit if digit.is_digit(10) => self.scan_number(),
+
             unexpected => self.errors.push(Error {
                 line: self.line,
                 kind: ErrorKind::UnexpectedChar(unexpected),
@@ -159,8 +161,16 @@ impl<'a> Scanner<'a> {
         }
     }
 
+    fn peek_next(&self) -> char {
+        if (self.current + 1 >= self.source.len()) {
+            return '\0';
+        } else {
+            return self.source[self.current + 1];
+        }
+    }
+
     fn scan_string(&mut self) {
-        while (self.peek() != '"' && !self.is_at_end()) {
+        while self.peek() != '"' && !self.is_at_end() {
             if self.peek() == '\n' {
                 self.line += 1;
             }
@@ -186,6 +196,30 @@ impl<'a> Scanner<'a> {
         self.add_token(TokenKind::String(string));
     }
 
+    fn scan_number(&mut self) {
+        while self.peek().is_digit(10) {
+            self.advance();
+        }
+
+        // Look for a fractional part
+        if self.peek() == '.' && self.peek_next().is_digit(10) {
+            // consume '.'
+            self.advance();
+
+            while self.peek().is_digit(10) {
+                self.advance();
+            }
+        }
+
+        let num: f64 = self.source[self.start..self.current]
+            .iter()
+            .collect::<String>()
+            .parse()
+            .expect("float parsing should always work");
+
+        self.add_token(TokenKind::Number(num));
+    }
+
     fn scan_tokens(mut self) -> Vec<Token<'a>> {
         while !self.is_at_end() {
             self.start = self.current;