From 3ccbcbc1c228fd3ad3287ad85326c341549078e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Fri, 30 Dec 2022 19:10:14 +0100
Subject: [PATCH] Scanner - Numbers

---
 src/scanner.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/src/scanner.rs b/src/scanner.rs
index af5db1c..1e9df17 100644
--- a/src/scanner.rs
+++ b/src/scanner.rs
@@ -54,7 +54,7 @@ impl Scanner {
             '/' => {
                 if self.is_match('/') {
                     while self.peek() != '\n' && !self.is_at_end() {
-                        self.advance();
+                        self.current += 1;
                     }
                 } else {
                     self.add_token(TokenType::Slash)
@@ -91,14 +91,19 @@ impl Scanner {
             }
             // String litterals
             '"' => self.string_litteral(err_hdl),
+            // Numbers
+            '0'..='9' => self.number(err_hdl),
             // Handle whitespace
             ' ' | '\r' | '\t' => (),
             '\n' => self.line += 1,
             // Anything else is an error
-            ch => err_hdl.error(self.line, &format!("unexpected character {:#?}", ch)),
+            ch => {
+                err_hdl.error(self.line, &format!("unexpected character {:#?}", ch));
+            }
         }
     }
 
+    /// Read the rest of a string litteral
     fn string_litteral(&mut self, err_hdl: &mut ErrorHandler) {
         loop {
             let p = self.peek();
@@ -108,18 +113,47 @@ impl Scanner {
             if p == '\n' {
                 self.line += 1;
             }
-            self.advance();
+            self.current += 1;
         }
 
         if self.is_at_end() {
             err_hdl.error(self.line, "unterminated string");
         } else {
-            self.advance(); // Last '"'
+            self.current += 1; // Last '"'
             let value = self.get_substring(self.start + 1, self.current - 1);
             self.add_token(TokenType::String(value));
         }
     }
 
+    /// Read the rest of a number.
+    fn number(&mut self, err_hdl: &mut ErrorHandler) {
+        while self.peek().is_digit(10) {
+            self.current += 1;
+        }
+        if self.peek() == '.' && self.peek_next().is_digit(10) {
+            self.current += 1;
+            while self.peek().is_digit(10) {
+                self.current += 1;
+            }
+        }
+
+        let tok_string = self.get_substring(self.start, self.current);
+        match tok_string.parse::<f64>() {
+            Err(e) => {
+                err_hdl.error(
+                    self.line,
+                    &format!(
+                        "Could not parse {} as a floating point number: {:?}",
+                        tok_string, e
+                    ),
+                );
+            }
+            Ok(value) => {
+                self.add_token(TokenType::Number(value));
+            }
+        };
+    }
+
     /// Check whether the end of the input has been reached.
     fn is_at_end(&self) -> bool {
         self.current >= self.len
@@ -154,6 +188,16 @@ impl Scanner {
         }
     }
 
+    /// Returns the next character, or a NULL character if the end has been
+    /// reached.
+    fn peek_next(&self) -> char {
+        if self.current + 1 >= self.source.chars().count() {
+            '\0'
+        } else {
+            self.source.chars().nth(self.current + 1).unwrap()
+        }
+    }
+
     /// Read the current character.
     fn cur_char(&self) -> char {
         self.source.chars().nth(self.current).unwrap()