commit 4361a31c8aac9e9f0663ced216b6b58af74bda2f
parent 99d77e15fc16eaa2eb0781893034d5aefa8b7241
Author: Sebastian <sebastian@sebsite.pw>
Date: Fri, 29 Apr 2022 23:24:00 -0400
lex: fix nested tuple access lexing
Given a tuple named t, the expression t.0.1 now works as intended,
rather than erroring because 0.1 was lexed as a floating point literal.
This is done by requiring that a number literal lexed immediately after
a dot token is an integer.
Fixes: https://todo.sr.ht/~sircmpwn/hare/376
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/include/lex.h b/include/lex.h
@@ -168,6 +168,7 @@ struct lexer {
struct token un;
struct location loc;
bool disable_labels;
+ bool require_int;
};
void lex_init(struct lexer *lexer, FILE *f, const char *filename);
diff --git a/src/lex.c b/src/lex.c
@@ -315,6 +315,10 @@ lex_literal(struct lexer *lexer, struct token *out)
if (!strchr(basechrs, c)) {
switch (c) {
case '.':
+ if (lexer->require_int) {
+ push(lexer, '.', true);
+ goto finalize;
+ }
if (isfloat || suff || exp) {
push(lexer, c, true);
goto finalize;
@@ -362,6 +366,7 @@ lex_literal(struct lexer *lexer, struct token *out)
}
finalize:
+ lexer->require_int = false;
out->token = T_LITERAL;
if (isfloat) {
out->storage = STORAGE_FCONST;
@@ -648,6 +653,7 @@ lex3(struct lexer *lexer, struct token *out, uint32_t c)
default:
push(lexer, c, false);
out->token = T_DOT;
+ lexer->require_int = true;
break;
}
break;
@@ -912,14 +918,16 @@ _lex(struct lexer *lexer, struct token *out)
return out->token;
}
- if (c <= 0x7F && (isalpha(c) || c == '_' || c == '@')) {
+ if (c <= 0x7F && isdigit(c)) {
push(lexer, c, false);
- return lex_name(lexer, out);
+ return lex_literal(lexer, out);
}
- if (c <= 0x7F && isdigit(c)) {
+ lexer->require_int = false;
+
+ if (c <= 0x7F && (isalpha(c) || c == '_' || c == '@')) {
push(lexer, c, false);
- return lex_literal(lexer, out);
+ return lex_name(lexer, out);
}
char p[5];
diff --git a/tests/21-tuples.ha b/tests/21-tuples.ha
@@ -6,8 +6,10 @@ fn storage() void = {
};
fn indexing() void = {
- let x: (int, size) = (42, 1337);
- assert(x.0 == 42 && x.1 == 1337);
+ let x: ((int, uint), size) = ((42, 69), 1337);
+ assert(x.0.0 == 42);
+ assert(x.0.1 == 69);
+ assert(x.1 == 1337);
};
fn func(in: (int, size)) (int, size) = (in.0 + 1, in.1 + 1);