Compare commits

..

2 commits

Author SHA1 Message Date
1e47b29685 fix scanner peek/peekNext 2019-06-04 17:28:48 -03:00
765cef87db add number and comment support 2019-06-04 17:24:07 -03:00
2 changed files with 52 additions and 7 deletions

View file

@ -16,7 +16,7 @@ fn run(allocator: *Allocator, data: []u8) !void {
var scanner = scanners.Scanner.init(allocator, data); var scanner = scanners.Scanner.init(allocator, data);
while (true) { while (true) {
var tok = scanner.nextToken() catch |err| { var tok_opt = scanner.nextToken() catch |err| {
try stdout.print( try stdout.print(
"error at '{}': {}\n", "error at '{}': {}\n",
scanner.currentLexeme(), scanner.currentLexeme(),
@ -25,9 +25,12 @@ fn run(allocator: *Allocator, data: []u8) !void {
return Result.CompileError; return Result.CompileError;
}; };
if (tok_opt) |tok| {
if (tok.ttype == .EOF) break; if (tok.ttype == .EOF) break;
try stdout.print("{x}\n", tok); try stdout.print("{x}\n", tok);
} }
}
return Result.Ok; return Result.Ok;
} }

View file

@ -148,12 +148,13 @@ pub const Scanner = struct {
fn peek(self: *Scanner) u8 { fn peek(self: *Scanner) u8 {
if (self.isAtEnd()) return 0; if (self.isAtEnd()) return 0;
return self.source[self.current]; if (self.current == 0) return 0;
return self.source[self.current - 1];
} }
fn peekNext(self: *Scanner) u8 { fn peekNext(self: *Scanner) u8 {
if (self.current + 1 >= self.source.len) return 0; if (self.current + 1 >= self.source.len) return 0;
return self.source[self.current + 1]; return self.source[self.current];
} }
fn skipWhitespace(self: *Scanner) void { fn skipWhitespace(self: *Scanner) void {
@ -173,15 +174,40 @@ pub const Scanner = struct {
} }
} }
pub fn nextToken(self: *Scanner) !Token { /// Consume a number.
/// Returns either an Integer or a Float token. Proper typing
/// of the number (i32 i64 u32 u64 f32 f64) are for the parser.
fn doNumber(self: *Scanner) Token {
var ttype = TokenType.Integer;
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())) {
ttype = TokenType.Float;
_ = self.advance();
while (isDigit(self.peek())) {
_ = self.advance();
}
}
return self.makeToken(ttype);
}
pub fn nextToken(self: *Scanner) !?Token {
self.skipWhitespace(); self.skipWhitespace();
self.start = self.current; self.start = self.current;
if (self.isAtEnd()) return self.makeToken(TokenType.EOF); if (self.isAtEnd()) return self.makeToken(TokenType.EOF);
var c = self.advance(); var c = self.advance();
if (isDigit(c)) return self.doNumber();
var token = switch (c) { var token: ?Token = switch (c) {
'(' => self.makeToken(.LeftParen), '(' => self.makeToken(.LeftParen),
')' => self.makeToken(.RightParen), ')' => self.makeToken(.RightParen),
'{' => self.makeToken(.LeftBrace), '{' => self.makeToken(.LeftBrace),
@ -197,6 +223,10 @@ pub const Scanner = struct {
'?' => self.makeToken(.QuestionMark), '?' => self.makeToken(.QuestionMark),
'$' => self.makeToken(.DollarSign), '$' => self.makeToken(.DollarSign),
'-' => self.makeToken(.Minus),
'+' => self.makeToken(.Plus),
'*' => self.makeToken(.Star),
'!' => self.makeMatchToken('=', .BangEqual, .Bang), '!' => self.makeMatchToken('=', .BangEqual, .Bang),
'=' => self.makeMatchToken('=', .EqualEqual, .Equal), '=' => self.makeMatchToken('=', .EqualEqual, .Equal),
@ -215,6 +245,18 @@ pub const Scanner = struct {
}, },
'>' => self.makeMatchToken('=', .GreaterEqual, .Greater), '>' => self.makeMatchToken('=', .GreaterEqual, .Greater),
'/' => blk: {
if (self.peekNext() == '/') {
while (self.peek() != '\n' and !self.isAtEnd()) {
_ = self.advance();
}
break :blk null;
} else {
break :blk self.makeToken(.Slash);
}
},
else => return ScannerError.Unexpected, else => return ScannerError.Unexpected,
}; };