Skip to content

Commit

Permalink
feat: Allow _ on number literals
Browse files Browse the repository at this point in the history
  • Loading branch information
mcbattirola authored and giann committed Sep 23, 2023
1 parent eb4e8ad commit f6707ba
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 6 deletions.
39 changes: 34 additions & 5 deletions src/scanner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -253,20 +253,34 @@ pub const Scanner = struct {
}

fn number(self: *Self) !Token {
while (isNumber(self.peek())) {
var peeked: u8 = self.peek();
while (isNumber(peeked) or peeked == '_') {
_ = self.advance();

peeked = self.peek();
}

if (self.source[self.current.offset - 1] == '_') {
return self.makeToken(.Error, "'_' must be between digits", null, null);
}

var is_float: bool = false;
if (self.peek() == '.' and isNumber(self.peekNext())) {
is_float = true;
_ = self.advance(); // Consume .

while (isNumber(self.peek())) {
peeked = self.peek();
while (isNumber(peeked) or peeked == '_') {
_ = self.advance();

peeked = self.peek();
}
}

if (self.source[self.current.offset - 1] == '_') {
return self.makeToken(.Error, "'_' must be between digits", null, null);
}

const float = if (is_float)
std.fmt.parseFloat(f64, self.source[self.current.start..self.current.offset]) catch {
return self.makeToken(
Expand Down Expand Up @@ -337,12 +351,20 @@ pub const Scanner = struct {

fn binary(self: *Self) Token {
var peeked: u8 = self.peek();
while (peeked == '0' or peeked == '1') {
if (peeked == '_') {
return self.makeToken(.Error, "'_' must be between digits", null, null);
}

while (peeked == '0' or peeked == '1' or peeked == '_') {
_ = self.advance();

peeked = self.peek();
}

if (self.source[self.current.offset - 1] == '_') {
return self.makeToken(.Error, "'_' must be between digits", null, null);
}

return self.makeToken(
.IntegerValue,
null,
Expand All @@ -359,15 +381,22 @@ pub const Scanner = struct {
}

fn hexa(self: *Self) Token {
_ = self.advance(); // Consume 'x'
if (self.peek() == '_') {
return self.makeToken(.Error, "'_' must be between digits", null, null);
}

_ = self.advance(); // Consume 'x'
var peeked: u8 = self.peek();
while (isNumber(peeked) or (peeked >= 'A' and peeked <= 'F') or (peeked >= 'a' and peeked <= 'f')) {
while (isNumber(peeked) or (peeked >= 'A' and peeked <= 'F') or (peeked >= 'a' and peeked <= 'f') or peeked == '_') {
_ = self.advance();

peeked = self.peek();
}

if (self.source[self.current.offset - 1] == '_') {
return self.makeToken(.Error, "'_' must be between digits", null, null);
}

return self.makeToken(
.IntegerValue,
null,
Expand Down
20 changes: 19 additions & 1 deletion tests/001-basic-types.buzz
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ test "Basic types" {
bool _ = true;
}

test "Underscore on number literals" {
int a = 100_000;

assert(a == 100000, message: "Could use an underscore on an int");

float b = 3.1_4;

assert(b == 3.14, message: "Could use an underscore on a float");

int bin = 0b1_0001;

assert(bin == 17, message: "Clould use an underscore on a binary int");

int h = 0xF_FFF;

assert(h == 65535, message: "Clould use an underscore on a hex int");
}

test "Char literal" {
int char = 'A';

Expand All @@ -19,4 +37,4 @@ test "Char literal" {
int slash = '\\';

assert(slash == 92, message: "Could escape \\ in char literal");
}
}
4 changes: 4 additions & 0 deletions tests/compile_errors/017-invalid-int-literal.buzz
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| '_' must be between digits
test "invalid literals" {
int a = 100_;
}
4 changes: 4 additions & 0 deletions tests/compile_errors/018-invalid-float-literal.buzz
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| '_' must be between digits
test "invalid literals" {
int a = 100.2_;
}
4 changes: 4 additions & 0 deletions tests/compile_errors/019-invalid-int-hex-literal.buzz
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| '_' must be between digits
test "invalid hex literal" {
int a = 0x_100;
}
4 changes: 4 additions & 0 deletions tests/compile_errors/020-invalid-int-bin-literal.buzz
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| '_' must be between digits
test "invalid bin literal" {
int a = 0b_100;
}

0 comments on commit f6707ba

Please sign in to comment.