From 69aa7b493da7a0536199ed4a69c734567ab6cbfc Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 31 May 2019 22:08:41 -0300 Subject: [PATCH] add number tokens --- src/main.zig | 3 +++ src/scanner.zig | 53 ++++++++++++++++++++++++++++++++++++++++++++++++- src/token.zig | 2 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 3423204..807041d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -21,6 +21,9 @@ fn run(allocator: *Allocator, data: []u8) !void { .Slice => |value| { try value.printToken(stdout); }, + .Number => |value| { + try value.printToken(stdout); + }, } hadError = false; diff --git a/src/scanner.zig b/src/scanner.zig index 8bbc5a8..051a98f 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -5,6 +5,10 @@ const main = @import("main.zig"); const TokenList = std.ArrayList(token.Token); +fn isDigit(char: u8) bool { + return char >= '0' and char <= '9'; +} + pub const Scanner = struct { source: []u8, tokens: TokenList, @@ -55,6 +59,18 @@ pub const Scanner = struct { }); } + /// Keep in mind Lox only has a single number type and that is a float one. + fn addNumberToken(self: *Scanner, ttype: token.TokenType, num: f32) !void { + try self.addToken(token.Token{ + .Number = token.NumberToken.init( + ttype, + self.currentLexeme(), + self.line, + num, + ), + }); + } + fn addToken( self: *Scanner, tok: token.Token, @@ -114,6 +130,37 @@ pub const Scanner = struct { ); } + fn peekNext(self: *Scanner) u8 { + if (self.current + 1 >= self.source.len) return 0; + return self.source[self.current + 1]; + } + + /// Consume a number + fn doNumber(self: *Scanner) !void { + while (isDigit(self.peek())) { + _ = self.advance(); + } + + // check if its a number like 12.34, where the '.' character + // exists and the one next to it is a digit. + if (self.peek() == '.' and isDigit(self.peekNext())) { + _ = self.advance(); + + while (isDigit(self.peek())) { + _ = self.advance(); + } + } + + // after going through all of the number, we can just use fmt.parseFloat + + var num = try std.fmt.parseFloat( + f32, + self.source[self.start..self.current], + ); + + try self.addNumberToken(.NUMBER, num); + } + /// Scan through our tokens and add them to the Scanner's token list. fn scanToken(self: *Scanner) !void { var c = self.advance(); @@ -154,7 +201,11 @@ pub const Scanner = struct { '"' => try self.doString(), else => { - try main.doError(self.line, "Unexpected character"); + if (isDigit(c)) { + try self.doNumber(); + } else { + try main.doError(self.line, "Unexpected character"); + } }, } } diff --git a/src/token.zig b/src/token.zig index 4460dad..c4400a3 100644 --- a/src/token.zig +++ b/src/token.zig @@ -98,8 +98,10 @@ pub fn TokenFactory( pub const SimpleToken = TokenFactory(void); pub const SliceToken = TokenFactory([]u8); +pub const NumberToken = TokenFactory(f32); pub const Token = union(enum) { Simple: SimpleToken, Slice: SliceToken, + Number: NumberToken, };