feat: lex escape characters inside strings
This commit is contained in:
parent
b8c542d88e
commit
71d617928a
@ -19,21 +19,43 @@ pub fn lex(input: []const u8, start: usize) LexError!?LexReturn {
|
|||||||
|
|
||||||
// lex everything but quote and newline
|
// lex everything but quote and newline
|
||||||
// TODO: escape characters
|
// TODO: escape characters
|
||||||
|
|
||||||
var current_pos = start + 1;
|
var current_pos = start + 1;
|
||||||
while (current_pos < cap and input[current_pos] != '"' and input[current_pos] != '\n') {
|
|
||||||
|
while (current_pos < cap) {
|
||||||
|
const next_char = input[current_pos];
|
||||||
|
// string is finished, return it
|
||||||
|
if (next_char == '"') {
|
||||||
|
return .{
|
||||||
|
Token.init(input[start .. current_pos + 1], TokenType.String, start),
|
||||||
|
current_pos + 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// new line, return error
|
||||||
|
else if (next_char == '\n') {
|
||||||
|
return LexError.IncompleteString;
|
||||||
|
}
|
||||||
|
// lex escape characters
|
||||||
|
else if (next_char == '\\') {
|
||||||
|
// if next char is EOF, return error
|
||||||
|
if (current_pos + 1 == cap) {
|
||||||
|
return LexError.IncompleteString;
|
||||||
|
}
|
||||||
|
// if next char is newline, return error
|
||||||
|
else if (input[current_pos + 1] == '\n') {
|
||||||
|
return LexError.IncompleteString;
|
||||||
|
}
|
||||||
|
// here just consume whatever char is after
|
||||||
|
// TODO: if next char is not an escape char, return warning?
|
||||||
|
current_pos += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
current_pos += 1;
|
current_pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// expect ending quote
|
// this could only reach when EOF is hit, return error
|
||||||
if (current_pos == cap or input[current_pos] == '\n') {
|
return LexError.IncompleteString;
|
||||||
// Error: EOF before ending the string
|
|
||||||
return LexError.IncompleteString;
|
|
||||||
} else {
|
|
||||||
return .{
|
|
||||||
Token.init(input[start .. current_pos + 1], TokenType.String, start),
|
|
||||||
current_pos + 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "should lex empty string" {
|
test "should lex empty string" {
|
||||||
@ -100,3 +122,49 @@ test "should fail on newline before closing string" {
|
|||||||
|
|
||||||
try std.testing.expect(false);
|
try std.testing.expect(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "should lex string with escape character 1" {
|
||||||
|
const input = "\"test\\\"string\"";
|
||||||
|
const output = try lex(input, 0);
|
||||||
|
|
||||||
|
if (output) |tuple| {
|
||||||
|
const t = tuple[0];
|
||||||
|
try std.testing.expectEqualDeep("\"test\\\"string\"", t.value);
|
||||||
|
try std.testing.expectEqual(14, tuple[1]);
|
||||||
|
} else {
|
||||||
|
try std.testing.expect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "should lex string with escape character 2" {
|
||||||
|
const input = "\"test\\\\string\"";
|
||||||
|
const output = try lex(input, 0);
|
||||||
|
|
||||||
|
if (output) |tuple| {
|
||||||
|
const t = tuple[0];
|
||||||
|
try std.testing.expectEqualDeep("\"test\\\\string\"", t.value);
|
||||||
|
try std.testing.expectEqual(14, tuple[1]);
|
||||||
|
} else {
|
||||||
|
try std.testing.expect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "should fail on EOF after backslash" {
|
||||||
|
const input = "\"hello \\";
|
||||||
|
_ = lex(input, 0) catch |err| {
|
||||||
|
try std.testing.expectEqual(LexError.IncompleteString, err);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
try std.testing.expect(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "should fail on newline after backslash" {
|
||||||
|
const input = "\"hello \\\n";
|
||||||
|
_ = lex(input, 0) catch |err| {
|
||||||
|
try std.testing.expectEqual(LexError.IncompleteString, err);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
try std.testing.expect(false);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user