scanner now recognizes numeric (f64) literals

This commit is contained in:
Sander Hautvast 2020-01-24 13:50:12 +01:00
parent 650a31889b
commit 071f584e92
3 changed files with 81 additions and 22 deletions

View file

@ -102,9 +102,35 @@ impl Scanner<'_> {
'\t' => {} '\t' => {}
'\r' => {} '\r' => {}
'\"' => self.string(), '\"' => self.string(),
_ => {} _ => {
if next_char.is_digit(10) {
self.number();
} else {
self.report_error(self.line, "unexpected character");
} }
} }
}
}
/// handle number literals
/// advances while characters are considered part of the number
/// finally adds a number token to the list.
fn number(&mut self) {
while self.peek(0).is_digit(10) {
self.advance();
}
if self.peek(0) == '.' && self.peek(1).is_digit(10) {
self.advance();
while self.peek(0).is_digit(10) {
self.advance();
}
}
let value: f64 = self.source[self.start..self.current].parse().expect("not a number");
self.add_token_literal(NUMBER, Box::new(value));
}
/// handle string literals /// handle string literals
/// advances until a terminating double quote is found and then adds the string token to the list /// advances until a terminating double quote is found and then adds the string token to the list

View file

@ -46,3 +46,14 @@ fn test_scan_string_literals() {
assert_eq!(token.lexeme, "\"hello world\""); assert_eq!(token.lexeme, "\"hello world\"");
assert_eq!(token.get_literal_as_string().unwrap(), "hello world"); assert_eq!(token.get_literal_as_string().unwrap(), "hello world");
} }
#[test]
fn test_scan_numeric_literals() {
let tokens = scan_tokens("0.1").unwrap();
assert_eq!(tokens.len(), 2);
let token = tokens.get(0).unwrap();
assert_eq!(token.token_type, NUMBER);
assert_eq!(token.lexeme, "0.1");
assert_eq!(token.get_literal_as_float().unwrap(), 0.1);
}

View file

@ -20,6 +20,10 @@ impl Token<'_>{
pub fn get_literal_as_string(&self) -> Option<&str> { pub fn get_literal_as_string(&self) -> Option<&str> {
self.literal.downcast_ref::<String>().map(|s| s.as_str()) self.literal.downcast_ref::<String>().map(|s| s.as_str())
} }
pub fn get_literal_as_float(&self) -> Option<f64> {
self.literal.downcast_ref::<f64>().map(|f| *f)
}
} }
impl fmt::Debug for Token<'_> { impl fmt::Debug for Token<'_> {
@ -40,30 +44,48 @@ impl fmt::Debug for Token<'_> {
#[derive(Eq, PartialEq, Debug, Clone, Copy)] #[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum TokenType { pub enum TokenType {
// Single-character tokens. // Single-character tokens.
LEFTPAREN, // ( LEFTPAREN,
RIGHTPAREN, // ) // (
LEFTBRACE, // [ RIGHTPAREN,
RIGHTBRACE, // ] // )
COMMA, // , LEFTBRACE,
DOT, // . // [
MINUS, // - RIGHTBRACE,
PLUS, // + // ]
SEMICOLON, // ; COMMA,
STAR, // * // ,
DOT,
// .
MINUS,
// -
PLUS,
// +
SEMICOLON,
// ;
STAR,
// *
SLASH, // / SLASH, // /
// One or two character tokens. // One or two character tokens.
BANG, // ! BANG,
BANGEQUAL, // != // !
EQUAL, // = BANGEQUAL,
EQUALEQUAL, // == // !=
GREATER, // > EQUAL,
GREATEREQUAL, // >= // =
LESS, // < EQUALEQUAL,
// ==
GREATER,
// >
GREATEREQUAL,
// >=
LESS,
// <
LESSEQUAL, // <= LESSEQUAL, // <=
// Literals. // Literals.
STRING, STRING,
NUMBER,
EOF // end of file EOF, // end of file
} }