From fbaa65a2319745c8a236a5c9c66e3406f42447c3 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Mon, 24 Jun 2024 04:18:59 +0200 Subject: Support ‘…’ and ‘...’ in initializers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/codegen.c | 4 ++++ src/lexer.c | 13 ++++++++++++- src/lexer.h | 4 ++++ src/parser.c | 25 +++++++++++++++++++++---- src/parser.h | 5 +++-- 5 files changed, 44 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/codegen.c b/src/codegen.c index 6fc7848..665f071 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -240,6 +240,10 @@ codegendecl(struct cgctx ctx, idx_t i) assert(ctx.ast.kinds[i] == ASTDECL); + /* Don’t assign a default value to ‘x: int = …’ */ + if (ctx.aux.buf[p.lhs].decl.isundef) + return fwdnode(ctx.ast, i); + if (!ctx.types[i].isfloat && ctx.aux.buf[p.lhs].decl.isstatic) { strview_t sv = ctx.toks.strs[ctx.ast.lexemes[i]]; /* TODO: Namespace the name */ diff --git a/src/lexer.c b/src/lexer.c index 30686d8..a613585 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -70,6 +70,10 @@ lexstring(const uchar *code, size_t codesz) data.kinds[data.len++] = ch; break; + case RUNE_C(0x2026): /* U+2026 HORIZONTAL ELLIPSIS */ + data.kinds[data.len++] = LEXELIP; + break; + /* Single- or double-byte literals */ case '/': if (code < end && code[0] == '*') { @@ -80,7 +84,6 @@ lexstring(const uchar *code, size_t codesz) data.kinds[data.len++] = ch; break; - case '<': case '>': data.kinds[data.len++] = ch; @@ -91,6 +94,13 @@ lexstring(const uchar *code, size_t codesz) } break; + case '.': + if (unlikely(end - code < 2) || code[0] != '.' || code[1] != '.') + goto fallback; + code += 2; + data.kinds[data.len++] = LEXELIP; + break; + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': data.kinds[data.len] = LEXNUM; @@ -112,6 +122,7 @@ lexstring(const uchar *code, size_t codesz) break; default: +fallback: if (!rune_is_xids(ch)) continue; diff --git a/src/lexer.h b/src/lexer.h index 5436030..fb63fd8 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -13,6 +13,10 @@ enum { LEXEOF, /* End of token stream */ LEXIDENT, /* Identifier */ LEXNUM, /* Numeric constant */ + LEXELIP, /* Ellipsis */ + + /* NOTE: Make sure that the enumerations above this comment don’t + conflict with the following explicitly assigned enumerations! */ LEXAMP = '&', LEXCOLON = ':', diff --git a/src/parser.c b/src/parser.c index 5b12e21..46a1fb6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -128,6 +128,7 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl) } aux->buf[j].decl.isstatic = toplvl; + aux->buf[j].decl.isundef = false; if (toplvl && toks.kinds[toksidx] == LEXIDENT && strview_eq(SV("pub"), toks.strs[toksidx])) { @@ -165,11 +166,27 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl) err("parser: Expected colon, equals, or semicolon"); } - bool func = toks.kinds[toksidx] == LEXLPAR; - if (func && ast->kinds[i] == ASTDECL) - err("Cannot assign function to mutable variable"); + idx_t rhs; + bool func = false; + + switch (toks.kinds[toksidx]) { + case LEXLPAR: + func = true; + if (ast->kinds[i] == ASTDECL) + err("Cannot assign function to mutable variable"); + rhs = parsefunc(ast, aux, toks); + break; + case LEXELIP: + toksidx++; + if (ast->kinds[i] == ASTCDECL) + err("parser: Cannot assign to ‘…’ in constant declaration"); + rhs = AST_EMPTY; + aux->buf[j].decl.isundef = true; + break; + default: + rhs = parseexpr(ast, aux, toks); + } - idx_t rhs = (func ? parsefunc : parseexpr)(ast, aux, toks); ast->kids[i].rhs = rhs; if (!func && toks.kinds[toksidx++] != LEXSEMI) err("parser: Expected semicolon"); diff --git a/src/parser.h b/src/parser.h index 9f7bf5e..d8991c0 100644 --- a/src/parser.h +++ b/src/parser.h @@ -71,8 +71,9 @@ typedef struct { union { struct { idx_t type; - bool ispub; - bool isstatic; + bool ispub : 1; + bool isstatic : 1; + bool isundef : 1; } decl; } *buf; size_t len, cap; -- cgit v1.2.3