commit b34c6beecd811a5aa7ac5bdbd2cc67c6ba99a032
parent 0e5337e33c91ef60bf270d726103e970d665e1d5
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Mon, 15 Jun 2026 17:09:58 -0700
Merge Phase 2: parser input ring (ParserInput 3-cell ring)
Diffstat:
6 files changed, 442 insertions(+), 373 deletions(-)
diff --git a/lang/c/parse/parse.c b/lang/c/parse/parse.c
@@ -2,7 +2,8 @@
*
* Contains:
* - kw_names[] table (used by parse_c to intern keywords)
- * - Diagnostics/token helpers (perr, advance, peek1, fetch_tok, ...)
+ * - Diagnostics/token helpers (perr, advance, peek1) over the input ring
+ * (parser_advance, parser_fill_to, parser_peek; see parse_priv.h)
* - Scope/tag operations
* - Type helpers (ty_int, ty_size_t)
* - Local-variable slot allocation (make_local, make_local_aligned)
@@ -15,6 +16,7 @@
* All expression, type, initializer, and statement code lives in
* parse_expr.c, parse_type.c, parse_init.c, and parse_stmt.c. */
+#include <assert.h>
#include <stdarg.h>
#include <string.h>
@@ -85,7 +87,7 @@ static SrcLoc tok_loc(Parser* p, const Tok* t) {
_Noreturn void perr(Parser* p, const char* fmt, ...) {
va_list ap;
- SrcLoc loc = tok_loc(p, &p->cur);
+ SrcLoc loc = tok_loc(p, p_cur(p));
va_start(ap, fmt);
compiler_panicv(p->c, loc, fmt, ap);
}
@@ -104,13 +106,16 @@ static size_t str_prefix_len(u16 flags) {
#define STR_ENC_MASK (TF_STR_WIDE | TF_STR_U8 | TF_STR_U16 | TF_STR_U32)
-/* Fuse two adjacent TOK_STR tokens into one per C11 §6.4.5 ¶5. */
-static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
- u16 ae = (u16)(a.flags & STR_ENC_MASK);
- u16 be = (u16)(b.flags & STR_ENC_MASK);
+/* Fuse two adjacent TOK_STR cells into one per C11 §6.4.5 ¶5, writing the fused
+ * result back into *dst in place: dst->loc (first literal's location) is kept,
+ * while dst->text (TEXT_SYM interned) and dst->flags (combined encoding) are
+ * overwritten. The synthetic spelling is interned so it outlives pp_free. */
+static void fuse_string_lits_into(Parser* p, CFeCell* dst, const CFeCell* b) {
+ u16 ae = (u16)(dst->flags & STR_ENC_MASK);
+ u16 be = (u16)(b->flags & STR_ENC_MASK);
u16 fused_enc;
- KitSlice a_sl = pp_text_slice(p->pp, &a);
- KitSlice b_sl = pp_text_slice(p->pp, &b);
+ KitSlice a_sl = pp_text_slice(p->pp, dst);
+ KitSlice b_sl = pp_text_slice(p->pp, b);
size_t alen = a_sl.len, blen = b_sl.len;
const char* as = a_sl.s;
const char* bs = b_sl.s;
@@ -121,7 +126,6 @@ static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
Heap* h = kit_compiler_context(p->c)->heap;
char* buf;
size_t k = 0;
- Tok out;
if (!as || !bs) perr(p, "bad string literal in concatenation");
if (ae != 0 && be != 0 && ae != be) {
perr(p,
@@ -129,8 +133,8 @@ static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
"encoding prefixes");
}
fused_enc = ae ? ae : be;
- apfx = str_prefix_len(a.flags);
- bpfx = str_prefix_len(b.flags);
+ apfx = str_prefix_len(dst->flags);
+ bpfx = str_prefix_len(b->flags);
if (alen < apfx + 2 || as[apfx] != '"' || as[alen - 1] != '"' ||
blen < bpfx + 2 || bs[bpfx] != '"' || bs[blen - 1] != '"') {
perr(p, "malformed string literal in concatenation");
@@ -156,61 +160,82 @@ static Tok fuse_string_lits(Parser* p, Tok a, Tok b) {
k += b_content_len;
}
buf[k++] = '"';
- out = a;
- out.text =
+ dst->text =
text_sym_ref(kit_sym_intern(p->pool->c, (KitSlice){.s = buf, .len = k}));
- out.flags = (u16)((a.flags & ~STR_ENC_MASK) | fused_enc);
+ dst->flags = (u16)((dst->flags & ~STR_ENC_MASK) | fused_enc);
h->free(h, buf, 0);
- return out;
}
-/* Pull one logical token from pp, collapsing adjacent TOK_STR runs. */
-static Tok fetch_tok(Parser* p) {
- Tok t;
- if (p->has_pending) {
- t = p->pending;
- p->has_pending = 0;
+/* Fill one ring slot with the next logical token, collapsing adjacent TOK_STR
+ * runs. Source priority: replay buffer (if active), then a pushed-back pending
+ * cell, then pp. A non-string cell pulled while collapsing a TOK_STR run is
+ * stashed in the one-cell pending slot. */
+static void parser_fill_one(Parser* p, CFeCell* slot) {
+ if (p->replay_active) {
+ if (p->replay_pos < p->replay_len) {
+ *slot = p->replay[p->replay_pos++];
+ return;
+ }
+ p->replay_active = 0;
+ }
+ if (p->input.has_pending) {
+ *slot = p->input.pending;
+ p->input.has_pending = 0;
} else {
- pp_next_parse(p->pp, &t);
+ pp_next_parse(p->pp, slot);
}
- if (t.kind != TOK_STR) return t;
+ if (slot->kind != TOK_STR) return;
for (;;) {
- Tok n;
+ CFeCell n;
+ /* A replay run records lexeme cells with adjacent strings already fused, so
+ * fusion only ever pulls follow-on cells from pp. */
pp_next_parse(p->pp, &n);
if (n.kind != TOK_STR) {
- p->pending = n;
- p->has_pending = 1;
- return t;
+ p->input.pending = n;
+ p->input.has_pending = 1;
+ return;
}
- t = fuse_string_lits(p, t, n);
+ fuse_string_lits_into(p, slot, &n);
}
}
-void advance(Parser* p) {
- if (p->replay_active) {
- if (p->replay_pos < p->replay_len) {
- p->cur = p->replay[p->replay_pos++];
- return;
- }
- p->replay_active = 0;
- }
- if (p->has_next) {
- p->cur = p->next;
- p->has_next = 0;
- } else {
- p->cur = fetch_tok(p);
+/* Fill the ring tail until `depth` is valid (i.e. depth+1 cells from cur). */
+void parser_fill_to(Parser* p, u32 depth) {
+ ParserInput* in = &p->input;
+ assert(depth < 3u);
+ while (in->nvalid <= depth) {
+ assert(in->nvalid < 3u);
+ parser_fill_one(p, &in->cells[parser_ring_idx(in, in->nvalid)]);
+ in->nvalid++;
}
+ assert(in->cur < 3u && in->nvalid <= 3u);
+}
+
+/* Advance to the next token: rotate cur and fill the freed tail slot on demand.
+ * Never copies/moves live cells between slots. */
+void parser_advance(Parser* p) {
+ ParserInput* in = &p->input;
+ in->cur = (u8)((in->cur + 1u) % 3u);
+ if (in->nvalid) in->nvalid--;
+ parser_fill_to(p, 0);
+ assert(in->cur < 3u && in->nvalid >= 1u && in->nvalid <= 3u);
}
+/* Borrowed pointer to the cell at lookahead `depth` (0 == current), valid until
+ * the next advance or replay-source switch. */
+const CFeCell* parser_peek(Parser* p, u32 depth) {
+ ParserInput* in = &p->input;
+ if (in->nvalid <= depth) parser_fill_to(p, depth);
+ return &in->cells[parser_ring_idx(in, depth)];
+}
+
+void advance(Parser* p) { parser_advance(p); }
+
+/* LL(1) lookahead: returns the depth-1 cell by value (a copy), matching all
+ * callers and avoiding any borrowed-pointer lifetime trap. */
Tok peek1(Parser* p) {
- if (p->replay_active && p->replay_pos < p->replay_len) {
- return p->replay[p->replay_pos];
- }
- if (!p->has_next) {
- p->next = fetch_tok(p);
- p->has_next = 1;
- }
- return p->next;
+ parser_fill_to(p, 1);
+ return p->input.cells[parser_ring_idx(&p->input, 1)];
}
void expect_punct(Parser* p, u32 punct, const char* what) {
@@ -220,7 +245,7 @@ void expect_punct(Parser* p, u32 punct, const char* what) {
}
int accept_punct(Parser* p, u32 punct) {
- if (is_punct(&p->cur, punct)) {
+ if (is_punct(p_cur(p), punct)) {
advance(p);
return 1;
}
@@ -231,7 +256,7 @@ int accept_punct(Parser* p, u32 punct) {
* parser's replay buffer. */
void record_braced_block(Parser* p) {
int depth = 0;
- if (!is_punct(&p->cur, '{')) perr(p, "internal: record on non-'{'");
+ if (!is_punct(p_cur(p), '{')) perr(p, "internal: record on non-'{'");
p->replay_len = 0;
for (;;) {
if (p->replay_len == p->replay_cap) {
@@ -244,28 +269,36 @@ void record_braced_block(Parser* p) {
p->replay = nv;
p->replay_cap = new_cap;
}
- p->replay[p->replay_len++] = p->cur;
- if (is_punct(&p->cur, '{')) {
+ p->replay[p->replay_len++] = *p_cur(p);
+ if (is_punct(p_cur(p), '{')) {
++depth;
- } else if (is_punct(&p->cur, '}')) {
+ } else if (is_punct(p_cur(p), '}')) {
--depth;
if (depth == 0) break;
- } else if (p->cur.kind == TOK_EOF) {
+ } else if (p_cur(p)->kind == TOK_EOF) {
perr(p, "unexpected end of file in initializer");
}
advance(p);
}
}
-/* After record_braced_block, rewind to replay from the start. */
-void replay_rewind(Parser* p) {
- if (p->replay_len == 0) perr(p, "internal: replay_rewind with empty buffer");
- p->cur = p->replay[0];
+/* Switch the input source to the parser's replay buffer, starting at replay[0].
+ * A source switch invalidates outstanding ring lookahead, so the ring is reset:
+ * cur=0, the single valid cell is replay[0], and any stashed pending cell is
+ * dropped. The caller must have set replay/replay_cap/replay_len beforehand. */
+void parser_replay_begin(Parser* p) {
+ if (p->replay_len == 0) perr(p, "internal: replay_begin with empty buffer");
+ p->input.cur = 0;
+ p->input.nvalid = 1;
+ p->input.cells[0] = p->replay[0];
+ p->input.has_pending = 0;
p->replay_pos = 1;
p->replay_active = 1;
- p->has_next = 0;
}
+/* After record_braced_block, rewind to replay from the start. */
+void replay_rewind(Parser* p) { parser_replay_begin(p); }
+
/* Count top-level items in a recorded brace list. */
u32 count_recorded_top_level_items(const Tok* vec, u32 len) {
u32 count;
@@ -689,9 +722,10 @@ static int type_array_depth(const Type* ty) {
static void eval_param_vla_count(Parser* p, const ParamVLABoundExpr* expr,
FrameSlot slot) {
- Tok save_cur = p->cur;
- Tok save_next = p->next;
- int save_has_next = p->has_next;
+ /* Whole-ring save/restore (POD, trivially copyable) plus the replay
+ * quintuple. The replay-source switch resets the ring, so the saved
+ * ParserInput must be restored verbatim afterward. */
+ ParserInput save_input = p->input;
Tok* save_replay = p->replay;
u32 save_cap = p->replay_cap;
u32 save_len = p->replay_len;
@@ -707,25 +741,19 @@ static void eval_param_vla_count(Parser* p, const ParamVLABoundExpr* expr,
memset(&replay[expr->ntoks], 0, sizeof(Tok));
replay[expr->ntoks].kind = TOK_EOF;
- p->cur = replay[0];
- p->next.kind = TOK_EOF;
- p->has_next = 0;
p->replay = replay;
p->replay_cap = expr->ntoks + 1u;
p->replay_len = expr->ntoks + 1u;
- p->replay_pos = 1;
- p->replay_active = 1;
+ parser_replay_begin(p);
parse_assign_expr(p);
to_rvalue(p);
- if (p->cur.kind != TOK_EOF) {
+ if (p_cur(p)->kind != TOK_EOF) {
perr(p, "unexpected token in VLA parameter bound");
}
store_top_to_size_slot(p, slot);
- p->cur = save_cur;
- p->next = save_next;
- p->has_next = save_has_next;
+ p->input = save_input;
p->replay = save_replay;
p->replay_cap = save_cap;
p->replay_len = save_len;
@@ -821,7 +849,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
/*is_member=*/0);
if (specs->storage == DS_TYPEDEF) {
- if (is_punct(&p->cur, '=')) {
+ if (is_punct(p_cur(p), '=')) {
perr(p, "typedef declarator cannot have initializer");
}
{
@@ -852,7 +880,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
"invalid storage-class specifier for block-scope function "
"declaration");
}
- if (is_punct(&p->cur, '=')) {
+ if (is_punct(p_cur(p), '=')) {
perr(p, "function declarator cannot have initializer");
}
(void)declare_function(p, name, var_ty, specs, loc, NULL, dinfo.asm_label,
@@ -981,7 +1009,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
}
/* Non-VLA local. */
{
- int has_init = is_punct(&p->cur, '=');
+ int has_init = is_punct(p_cur(p), '=');
FrameSlot s;
if (has_init && var_ty && var_ty->kind == TY_ARRAY &&
var_ty->arr.incomplete) {
@@ -1010,7 +1038,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) {
if (accept_punct(p, '=')) {
c_cg_set_loc(p, loc);
if ((var_ty->kind == TY_STRUCT || var_ty->kind == TY_UNION) &&
- !is_punct(&p->cur, '{')) {
+ !is_punct(p_cur(p), '{')) {
parse_assign_expr(p);
emit_struct_copy_into_slot(p, s, var_ty, 0, var_ty);
} else if (var_ty->kind == TY_ARRAY || var_ty->kind == TY_STRUCT ||
@@ -1070,10 +1098,10 @@ void parse_param_list(Parser* p, ParamInfo** infos_out, u16* nparams_out,
*infos_out = NULL;
*nparams_out = 0;
- if (is_punct(&p->cur, ')')) {
+ if (is_punct(p_cur(p), ')')) {
return;
}
- if (is_kw(p, &p->cur, KW_VOID)) {
+ if (is_kw(p, p_cur(p), KW_VOID)) {
Tok n2 = peek1(p);
if (is_punct(&n2, ')')) {
advance(p); /* `void` */
@@ -1382,7 +1410,7 @@ static void parse_external_decl(Parser* p) {
validate_decl_type_constraints(p, &specs, tty,
tty && tty->kind == TY_FUNC,
/*is_member=*/0);
- if (is_punct(&p->cur, '=')) {
+ if (is_punct(p_cur(p), '=')) {
perr(p, "typedef declarator cannot have initializer");
}
{
@@ -1422,7 +1450,7 @@ static void parse_external_decl(Parser* p) {
&fn_section_id, &fn_decl_flags, &fn_alias_target);
attr_list_append(&fent->attrs, dattrs);
- if (is_punct(&p->cur, '{')) {
+ if (is_punct(p_cur(p), '{')) {
int suppress_body_codegen = specs.storage == DS_EXTERN &&
((specs.flags | fn_decl_flags) & DF_INLINE);
if (fent->defined) perr(p, "redefinition of function");
@@ -1475,7 +1503,7 @@ static void parse_external_decl(Parser* p) {
/* Global object declaration. */
for (;;) {
- int has_init = is_punct(&p->cur, '=');
+ int has_init = is_punct(p_cur(p), '=');
int is_pure_extern =
(specs.storage == DS_EXTERN || specs.storage == DS_REGISTER) &&
!has_init;
@@ -1579,7 +1607,7 @@ static void parse_file_scope_asm(Parser* p) {
size_t nbytes;
advance(p); /* asm / __asm__ */
for (;;) {
- if (is_kw(p, &p->cur,
+ if (is_kw(p, p_cur(p),
KW_VOLATILE)) { /* matches `volatile` and `__volatile__` */
advance(p);
continue;
@@ -1587,10 +1615,10 @@ static void parse_file_scope_asm(Parser* p) {
break;
}
expect_punct(p, '(', "'(' after file-scope asm");
- if (p->cur.kind != TOK_STR) {
+ if (p_cur(p)->kind != TOK_STR) {
perr(p, "expected string literal in file-scope asm");
}
- bytes = decode_string_literal(p, &p->cur, &nbytes);
+ bytes = decode_string_literal(p, p_cur(p), &nbytes);
advance(p);
expect_punct(p, ')', "')' after file-scope asm");
expect_punct(p, ';', "';' after file-scope asm");
@@ -1602,16 +1630,16 @@ static void parse_file_scope_asm(Parser* p) {
}
static void parse_translation_unit(Parser* p) {
- while (p->cur.kind != TOK_EOF) {
- if (p->cur.kind == TOK_NEWLINE || is_pp_hash(&p->cur)) {
+ while (p_cur(p)->kind != TOK_EOF) {
+ if (p_cur(p)->kind == TOK_NEWLINE || is_pp_hash(p_cur(p))) {
advance(p);
continue;
}
- if (is_kw(p, &p->cur, KW_STATIC_ASSERT)) {
+ if (is_kw(p, p_cur(p), KW_STATIC_ASSERT)) {
parse_static_assert(p);
continue;
}
- if (is_kw(p, &p->cur, KW_ASM) || is_kw(p, &p->cur, KW_BUILTIN_ASM)) {
+ if (is_kw(p, p_cur(p), KW_ASM) || is_kw(p, p_cur(p), KW_BUILTIN_ASM)) {
parse_file_scope_asm(p);
continue;
}
@@ -1802,7 +1830,9 @@ void parse_c(Compiler* c, Pool* pool, Pp* pp, DeclTable* decls, CG* cg,
p.scope = scope_new(&p, NULL);
- p.cur = fetch_tok(&p);
+ /* Prime the input ring: p was zero-initialized (cur=0, nvalid=0), so this
+ * fills cells[0] with the first token. */
+ parser_fill_to(&p, 0);
parse_translation_unit(&p);
}
diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c
@@ -483,7 +483,7 @@ static void c_const_guard_note_at(Parser* p, SrcLoc loc, const char* message) {
}
static void c_const_guard_note(Parser* p, const char* message) {
- c_const_guard_note_at(p, pp_materialize_loc(p->pp, p->cur.loc), message);
+ c_const_guard_note_at(p, pp_materialize_loc(p->pp, p_cur(p)->loc), message);
}
static void c_const_guard_not_eval_push(Parser* p) {
@@ -945,8 +945,8 @@ static int parse_builtin_clear_cache_call(Parser* p, Sym name, SrcLoc loc) {
}
static MemOrder parse_atomic_mem_order(Parser* p) {
- if (p->cur.kind == TOK_NUM) {
- return (MemOrder)eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
+ if (p_cur(p)->kind == TOK_NUM) {
+ return (MemOrder)eval_const_int(p, pp_materialize_loc(p->pp, p_cur(p)->loc));
}
parse_assign_expr(p);
to_rvalue(p);
@@ -994,13 +994,13 @@ static int offsetof_find_member(Parser* p, const Type* rec_ty, Sym mname,
static const Type* offsetof_designator(Parser* p, const Type* base, u32* off) {
const Type* cur = base;
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected member name in __builtin_offsetof");
}
for (;;) {
if (cur->kind == TY_STRUCT || cur->kind == TY_UNION) {
- Sym mname = tok_ident(&p->cur);
+ Sym mname = tok_ident(p_cur(p));
const Type* mty = NULL;
u32 moff = 0;
if (!offsetof_find_member(p, cur, mname, &mty, &moff))
@@ -1013,17 +1013,17 @@ static const Type* offsetof_designator(Parser* p, const Type* base, u32* off) {
} else {
perr(p, "__builtin_offsetof step into non-aggregate");
}
- if (is_punct(&p->cur, '.')) {
+ if (is_punct(p_cur(p), '.')) {
advance(p);
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected member name after '.'");
}
continue;
}
- if (is_punct(&p->cur, '[')) {
+ if (is_punct(p_cur(p), '[')) {
advance(p);
- i64 idx = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
+ i64 idx = eval_const_int(p, pp_materialize_loc(p->pp, p_cur(p)->loc));
expect_punct(p, ']', "']' in __builtin_offsetof");
if (cur->kind != TY_ARRAY) {
perr(p, "__builtin_offsetof '[' on non-array");
@@ -1455,8 +1455,8 @@ static int parse_kit_syscall_call(Parser* p, Sym name, SrcLoc loc) {
}
static int try_parse_builtin_call(Parser* p) {
- Sym name = tok_ident(&p->cur);
- SrcLoc loc = pp_materialize_loc(p->pp, p->cur.loc);
+ Sym name = tok_ident(p_cur(p));
+ SrcLoc loc = pp_materialize_loc(p->pp, p_cur(p)->loc);
if (c_const_guard_active(p) && name != p->sym_b_offsetof &&
name != p->sym_b_constant_p) {
@@ -1568,7 +1568,7 @@ static int try_parse_builtin_call(Parser* p) {
if (name == p->sym_b_return_address || name == p->sym_b_frame_address) {
/* GCC requires the level to be an integer constant expression. */
int is_return = (name == p->sym_b_return_address);
- i64 level = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
+ i64 level = eval_const_int(p, pp_materialize_loc(p->pp, p_cur(p)->loc));
expect_punct(p, ')',
"')' after __builtin_return_address/__builtin_frame_address");
if (level < 0)
@@ -1683,7 +1683,7 @@ static int try_parse_builtin_call(Parser* p) {
}
if (name == p->sym_a_always_lock_free || name == p->sym_a_is_lock_free) {
- i64 size = eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc));
+ i64 size = eval_const_int(p, pp_materialize_loc(p->pp, p_cur(p)->loc));
expect_punct(p, ',', "',' in atomic lock-free builtin");
parse_assign_expr(p);
to_rvalue(p);
@@ -1733,7 +1733,7 @@ static int try_parse_builtin_call(Parser* p) {
coerce_top_to_type(p, val_ty);
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
- (void)eval_const_int(p, pp_materialize_loc(p->pp, p->cur.loc)); /* weak */
+ (void)eval_const_int(p, pp_materialize_loc(p->pp, p_cur(p)->loc)); /* weak */
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
MemOrder succ = parse_atomic_mem_order(p);
expect_punct(p, ',', "',' in __atomic_compare_exchange_n");
@@ -1823,7 +1823,7 @@ static int try_parse_builtin_call(Parser* p) {
* ============================================================ */
static void parse_primary(Parser* p) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
if (t.kind == TOK_NUM) {
i64 v = parse_int_literal(p, &t);
const Type* lty = int_literal_type(p, &t);
@@ -1858,7 +1858,7 @@ static void parse_primary(Parser* p) {
/* try_parse_builtin_call may rewrite the current ident in-place
* (e.g. __builtin_memcpy → memcpy) and return 0, asking us to
* resume normal lookup with the rewritten name. */
- t = p->cur;
+ t = *p_cur(p);
/* C99 §6.4.2.2: `__func__` inside a function-body acts as
* static const char __func__[] = "<function-name>";
* GCC also exposes `__FUNCTION__` and `__PRETTY_FUNCTION__` with
@@ -2016,7 +2016,7 @@ static void parse_postfix(Parser* p) {
parse_primary(p);
vla_bounds = p->last_pushed_vla_bounds;
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
if (is_punct(&t, P_INC)) {
c_const_guard_note_at(
p, pp_materialize_loc(p->pp, t.loc),
@@ -2061,7 +2061,7 @@ static void parse_postfix(Parser* p) {
}
advance(p); /* '(' */
u32 nargs = 0;
- if (!is_punct(&p->cur, ')')) {
+ if (!is_punct(p_cur(p), ')')) {
for (;;) {
const Type* param_ty =
(nargs < fn_type->fn.nparams) ? fn_type->fn.params[nargs] : NULL;
@@ -2153,11 +2153,11 @@ static void parse_postfix(Parser* p) {
perr(p,
"request for member in something that is not a struct or union");
}
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected member name after '.'");
}
- mname = tok_ident(&p->cur);
+ mname = tok_ident(p_cur(p));
advance(p);
lt = type_unqual(p->pool, lt);
if (!find_record_member_path(p, lt, mname, &mty, &off, &bf_off, &bf_w,
@@ -2184,11 +2184,11 @@ static void parse_postfix(Parser* p) {
if (!rec_ty || (rec_ty->kind != TY_STRUCT && rec_ty->kind != TY_UNION)) {
perr(p, "'->' on pointer to non-struct/union");
}
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected member name after '->'");
}
- mname = tok_ident(&p->cur);
+ mname = tok_ident(p_cur(p));
advance(p);
if (!find_record_member_path(p, rec_ty, mname, &mty, &off, &bf_off, &bf_w,
&bf_ss))
@@ -2202,7 +2202,7 @@ static void parse_postfix(Parser* p) {
}
void parse_unary(Parser* p) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
if (is_punct(&t, '(')) {
Tok n = peek1(p);
if (starts_type_name(p, &n)) {
@@ -2211,7 +2211,7 @@ void parse_unary(Parser* p) {
advance(p); /* '(' */
dst = parse_type_name(p);
expect_punct(p, ')', "')' after type-name");
- if (is_punct(&p->cur, '{')) {
+ if (is_punct(p_cur(p), '{')) {
FrameSlotDesc fsd;
FrameSlot slot;
const Type* lit_ty = dst;
@@ -2229,10 +2229,10 @@ void parse_unary(Parser* p) {
c_cg_push_local_typed(p, slot, lit_ty);
return;
}
- if (c_const_guard_active(p) && p->cur.kind == TOK_FLT) {
+ if (c_const_guard_active(p) && p_cur(p)->kind == TOK_FLT) {
const Type* tu = type_unqual(p->pool, dst);
if (tu && type_is_int(tu)) {
- double fv = parse_float_literal(p, &p->cur);
+ double fv = parse_float_literal(p, p_cur(p));
advance(p);
c_cg_push_int(p, (i64)fv, tu);
return;
@@ -2299,12 +2299,12 @@ void parse_unary(Parser* p) {
p, pp_materialize_loc(p->pp, t.loc),
"address constant is not an integer constant expression");
advance(p); /* '&&' */
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected label name after '&&'");
}
- name = tok_ident(&p->cur);
- loc = pp_materialize_loc(p->pp, p->cur.loc);
+ name = tok_ident(p_cur(p));
+ loc = pp_materialize_loc(p->pp, p_cur(p)->loc);
advance(p);
c_cg_push_label_addr(p, take_label_addr(p, name, loc));
return;
@@ -2361,7 +2361,7 @@ void parse_unary(Parser* p) {
const Type* ty = NULL;
FrameSlot vla_slot = FRAME_SLOT_NONE;
advance(p);
- if (is_punct(&p->cur, '(')) {
+ if (is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
if (starts_type_name(p, &n)) {
advance(p);
@@ -2422,7 +2422,7 @@ void parse_unary(Parser* p) {
for (;;) {
const Type* assoc_ty = NULL;
int is_default = 0;
- if (is_kw(p, &p->cur, KW_DEFAULT)) {
+ if (is_kw(p, p_cur(p), KW_DEFAULT)) {
advance(p);
is_default = 1;
if (saw_default) perr(p, "_Generic has duplicate default association");
@@ -2462,9 +2462,9 @@ void parse_unary(Parser* p) {
Tok* buf = arena_array(p->pool->arena, Tok, cap);
u32 len = 0;
int paren_depth = 0, brack_depth = 0, brace_depth = 0;
- while (p->cur.kind != TOK_EOF) {
+ while (p_cur(p)->kind != TOK_EOF) {
if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0) {
- if (is_punct(&p->cur, ',') || is_punct(&p->cur, ')')) break;
+ if (is_punct(p_cur(p), ',') || is_punct(p_cur(p), ')')) break;
}
if (len == cap) {
u32 new_cap = cap * 2;
@@ -2474,18 +2474,18 @@ void parse_unary(Parser* p) {
buf = nv;
cap = new_cap;
}
- buf[len++] = p->cur;
- if (is_punct(&p->cur, '('))
+ buf[len++] = *p_cur(p);
+ if (is_punct(p_cur(p), '('))
++paren_depth;
- else if (is_punct(&p->cur, ')'))
+ else if (is_punct(p_cur(p), ')'))
--paren_depth;
- else if (is_punct(&p->cur, '['))
+ else if (is_punct(p_cur(p), '['))
++brack_depth;
- else if (is_punct(&p->cur, ']'))
+ else if (is_punct(p_cur(p), ']'))
--brack_depth;
- else if (is_punct(&p->cur, '{'))
+ else if (is_punct(p_cur(p), '{'))
++brace_depth;
- else if (is_punct(&p->cur, '}'))
+ else if (is_punct(p_cur(p), '}'))
--brace_depth;
advance(p);
}
@@ -2507,21 +2507,21 @@ void parse_unary(Parser* p) {
int paren_depth = 0;
int brack_depth = 0;
int brace_depth = 0;
- while (p->cur.kind != TOK_EOF) {
+ while (p_cur(p)->kind != TOK_EOF) {
if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0) {
- if (is_punct(&p->cur, ',') || is_punct(&p->cur, ')')) break;
+ if (is_punct(p_cur(p), ',') || is_punct(p_cur(p), ')')) break;
}
- if (is_punct(&p->cur, '('))
+ if (is_punct(p_cur(p), '('))
++paren_depth;
- else if (is_punct(&p->cur, ')'))
+ else if (is_punct(p_cur(p), ')'))
--paren_depth;
- else if (is_punct(&p->cur, '['))
+ else if (is_punct(p_cur(p), '['))
++brack_depth;
- else if (is_punct(&p->cur, ']'))
+ else if (is_punct(p_cur(p), ']'))
--brack_depth;
- else if (is_punct(&p->cur, '{'))
+ else if (is_punct(p_cur(p), '{'))
++brace_depth;
- else if (is_punct(&p->cur, '}'))
+ else if (is_punct(p_cur(p), '}'))
--brace_depth;
advance(p);
}
@@ -2529,20 +2529,18 @@ void parse_unary(Parser* p) {
if (!accept_punct(p, ',')) break;
}
if (!emitted && default_buf) {
+ /* Whole-ring save/restore (POD) plus the replay quintuple; the
+ * replay-source switch resets the ring. */
+ ParserInput save_input = p->input;
Tok* save_replay = p->replay;
u32 save_cap = p->replay_cap;
u32 save_len = p->replay_len;
u32 save_pos = p->replay_pos;
u8 save_active = p->replay_active;
- Tok save_cur = p->cur;
- int save_has_next = p->has_next;
p->replay = default_buf;
p->replay_cap = default_len;
p->replay_len = default_len;
- p->replay_pos = 1;
- p->replay_active = 1;
- p->cur = default_buf[0];
- p->has_next = 0;
+ parser_replay_begin(p);
parse_assign_expr(p);
emitted = 1;
p->replay = save_replay;
@@ -2550,8 +2548,7 @@ void parse_unary(Parser* p) {
p->replay_len = save_len;
p->replay_pos = save_pos;
p->replay_active = save_active;
- p->cur = save_cur;
- p->has_next = save_has_next;
+ p->input = save_input;
}
expect_punct(p, ')', "')' after _Generic");
if (!emitted) {
@@ -2563,7 +2560,7 @@ void parse_unary(Parser* p) {
const Type* ty;
advance(p);
expect_punct(p, '(', "'('");
- if (starts_type_name(p, &p->cur)) {
+ if (starts_type_name(p, p_cur(p))) {
ty = parse_type_name(p);
} else {
c_const_guard_not_eval_push(p);
@@ -2672,7 +2669,7 @@ static BinOp int_div_rem_binop(BinOp op, const Type* common) {
static void parse_mul(Parser* p) {
parse_unary(p);
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
SrcLoc op_loc;
BinOp bop;
if (is_punct(&t, '*')) {
@@ -2788,7 +2785,7 @@ static void emit_add_or_sub(Parser* p, BinOp bop) {
static void parse_add(Parser* p) {
parse_mul(p);
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
BinOp bop;
if (is_punct(&t, '+')) {
bop = BO_IADD;
@@ -2808,7 +2805,7 @@ static void parse_add(Parser* p) {
static void parse_shift(Parser* p) {
parse_add(p);
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
SrcLoc op_loc;
BinOp bop;
if (is_punct(&t, P_SHL)) {
@@ -2847,7 +2844,7 @@ static void parse_shift(Parser* p) {
static void parse_rel(Parser* p) {
parse_shift(p);
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
CmpOp cop;
if (is_punct(&t, '<')) {
cop = CMP_LT_S;
@@ -2908,7 +2905,7 @@ static void parse_rel(Parser* p) {
static void parse_eq(Parser* p) {
parse_rel(p);
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
CmpOp cop;
if (is_punct(&t, P_EQ)) {
cop = CMP_EQ;
@@ -2951,7 +2948,7 @@ static void parse_eq(Parser* p) {
static void parse_band(Parser* p) {
parse_eq(p);
- while (is_punct(&p->cur, '&')) {
+ while (is_punct(p_cur(p), '&')) {
advance(p);
to_rvalue(p);
parse_eq(p);
@@ -2967,7 +2964,7 @@ static void parse_band(Parser* p) {
static void parse_bxor(Parser* p) {
parse_band(p);
- while (is_punct(&p->cur, '^')) {
+ while (is_punct(p_cur(p), '^')) {
advance(p);
to_rvalue(p);
parse_band(p);
@@ -2983,7 +2980,7 @@ static void parse_bxor(Parser* p) {
static void parse_bor(Parser* p) {
parse_bxor(p);
- while (is_punct(&p->cur, '|')) {
+ while (is_punct(p_cur(p), '|')) {
advance(p);
to_rvalue(p);
parse_bxor(p);
@@ -3016,7 +3013,7 @@ static void ll_store_const(Parser* p, FrameSlot tmp, const Type* ty, i64 v) {
static void parse_land(Parser* p) {
parse_bor(p);
- while (is_punct(&p->cur, P_AND)) {
+ while (is_punct(p_cur(p), P_AND)) {
CGLabel L_false = c_cg_label_new(p);
CGLabel L_end = c_cg_label_new(p);
const Type* result_ty = ty_int(p);
@@ -3062,7 +3059,7 @@ static void parse_land(Parser* p) {
static void parse_lor(Parser* p) {
parse_land(p);
- while (is_punct(&p->cur, P_OR)) {
+ while (is_punct(p_cur(p), P_OR)) {
CGLabel L_true = c_cg_label_new(p);
CGLabel L_end = c_cg_label_new(p);
const Type* result_ty = ty_int(p);
@@ -3108,7 +3105,7 @@ static void parse_lor(Parser* p) {
static void parse_ternary(Parser* p) {
parse_lor(p);
- if (!is_punct(&p->cur, '?')) return;
+ if (!is_punct(p_cur(p), '?')) return;
CGLabel L_else = c_cg_label_new(p);
CGLabel L_then = c_cg_label_new(p);
CGLabel L_end = c_cg_label_new(p);
@@ -3246,7 +3243,7 @@ static void parse_ternary(Parser* p) {
void parse_assign_expr(Parser* p) {
parse_ternary(p);
- Tok t = p->cur;
+ Tok t = *p_cur(p);
SrcLoc op_loc = pp_materialize_loc(p->pp, t.loc);
BinOp compound;
int is_simple_assign;
@@ -3381,7 +3378,7 @@ void parse_assign_expr(Parser* p) {
void parse_expr(Parser* p) {
parse_assign_expr(p);
- while (is_punct(&p->cur, ',')) {
+ while (is_punct(p_cur(p), ',')) {
c_const_guard_note(p, "comma operator in integer constant expression");
advance(p);
c_cg_drop(p);
diff --git a/lang/c/parse/parse_init.c b/lang/c/parse/parse_init.c
@@ -35,11 +35,11 @@ int is_char_kind(const Type* ty) {
return ty->kind == TY_CHAR || ty->kind == TY_SCHAR || ty->kind == TY_UCHAR;
}
-/* Decode the string token at p->cur without advancing. Returns a heap-
+/* Decode the current string token without advancing. Returns a heap-
* allocated byte buffer (caller frees) and writes length (including NUL)
* to *nlen_out. */
static u8* peek_string_bytes(Parser* p, size_t* nlen_out) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
if (t.kind != TOK_STR) perr(p, "internal: peek_string_bytes on non-string");
return decode_string_literal(p, &t, nlen_out);
}
@@ -73,10 +73,7 @@ static void init_aggregate_remainder(Parser* p, FrameSlot slot,
static void replay_recorded_initializer_expr(Parser* p) {
if (p->replay_len == 0)
perr(p, "internal: empty initializer expression replay");
- p->cur = p->replay[0];
- p->replay_pos = 1;
- p->replay_active = 1;
- p->has_next = 0;
+ parser_replay_begin(p);
}
static void record_initializer_expr_for_replay(Parser* p) {
@@ -96,25 +93,25 @@ static void record_initializer_expr_for_replay(Parser* p) {
buf = nb;
cap = new_cap;
}
- buf[len++] = p->cur;
+ buf[len++] = *p_cur(p);
- if (p->cur.kind == TOK_EOF) break;
+ if (p_cur(p)->kind == TOK_EOF) break;
if (paren_depth == 0 && brack_depth == 0 && brace_depth == 0 &&
- (is_punct(&p->cur, ',') || is_punct(&p->cur, '}'))) {
+ (is_punct(p_cur(p), ',') || is_punct(p_cur(p), '}'))) {
break;
}
- if (is_punct(&p->cur, '('))
+ if (is_punct(p_cur(p), '('))
++paren_depth;
- else if (is_punct(&p->cur, ')'))
+ else if (is_punct(p_cur(p), ')'))
--paren_depth;
- else if (is_punct(&p->cur, '['))
+ else if (is_punct(p_cur(p), '['))
++brack_depth;
- else if (is_punct(&p->cur, ']'))
+ else if (is_punct(p_cur(p), ']'))
--brack_depth;
- else if (is_punct(&p->cur, '{'))
+ else if (is_punct(p_cur(p), '{'))
++brace_depth;
- else if (is_punct(&p->cur, '}'))
+ else if (is_punct(p_cur(p), '}'))
--brace_depth;
advance(p);
@@ -134,8 +131,8 @@ static int try_init_aggregate_from_expr(Parser* p, FrameSlot slot,
int compatible;
if (!ty || (ty->kind != TY_STRUCT && ty->kind != TY_UNION)) return 0;
- if (is_punct(&p->cur, '{') || is_punct(&p->cur, '.') ||
- is_punct(&p->cur, '[')) {
+ if (is_punct(p_cur(p), '{') || is_punct(p_cur(p), '.') ||
+ is_punct(p_cur(p), '[')) {
return 0;
}
@@ -380,10 +377,10 @@ static void parse_designator_chain(Parser* p, const Type* outer_ty,
InitDesignatorCont cont;
memset(&cont, 0, sizeof cont);
for (;;) {
- if (is_punct(&p->cur, '[')) {
+ if (is_punct(p_cur(p), '[')) {
i64 idx;
u32 esz;
- SrcLoc cloc = tok_loc_init(p, &p->cur);
+ SrcLoc cloc = tok_loc_init(p, p_cur(p));
const Type* parent_ty = cur_ty;
u32 parent_off = cur_off;
advance(p);
@@ -403,7 +400,7 @@ static void parse_designator_chain(Parser* p, const Type* outer_ty,
cont.next_index = (u32)idx + 1u;
if (first) *top_index_out = (u32)idx;
first = 0;
- } else if (is_punct(&p->cur, '.')) {
+ } else if (is_punct(p_cur(p), '.')) {
Sym fname;
const Type* fty;
u32 foff;
@@ -414,11 +411,11 @@ static void parse_designator_chain(Parser* p, const Type* outer_ty,
const Type* parent_ty = cur_ty;
u32 parent_off = cur_off;
advance(p);
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected field name after '.'");
}
- fname = tok_ident(&p->cur);
+ fname = tok_ident(p_cur(p));
advance(p);
if (!cur_ty || (cur_ty->kind != TY_STRUCT && cur_ty->kind != TY_UNION)) {
perr(p, "field designator on non-record type");
@@ -504,11 +501,11 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty,
* count) terminates it. */
for (;;) {
if (braced) {
- if (is_punct(&p->cur, '}') || p->cur.kind == TOK_EOF) break;
+ if (is_punct(p_cur(p), '}') || p_cur(p)->kind == TOK_EOF) break;
} else if (i >= ty->rec.nfields) {
break;
}
- if (braced && is_punct(&p->cur, '.')) {
+ if (braced && is_punct(p_cur(p), '.')) {
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
@@ -534,7 +531,7 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty,
u32 top_off = offset + L->fields[top_idx].offset;
if (designator_continues_inside(p, ty, offset, top_f->type, top_off,
&cont) &&
- accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
+ accept_punct(p, ',') && !is_punct(p_cur(p), '}')) {
init_aggregate_remainder(p, slot, arr_ty, cont.parent_offset,
cont.parent_ty, cont.next_index);
}
@@ -559,7 +556,7 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty,
++i;
break;
}
- if (is_punct(&p->cur, '}')) {
+ if (is_punct(p_cur(p), '}')) {
++i;
break;
}
@@ -594,7 +591,7 @@ static void init_aggregate_remainder(Parser* p, FrameSlot slot,
init_at(p, slot, arr_ty, offset + i * esz, ty->arr.elem);
if (i + 1u >= ty->arr.count) return;
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
for (++i; i < ty->arr.count; ++i) {
zero_init_at(p, slot, arr_ty, offset + i * esz, ty->arr.elem);
@@ -608,7 +605,7 @@ static void init_aggregate_remainder(Parser* p, FrameSlot slot,
init_field_at(p, slot, arr_ty, offset, ty, i);
if (i + 1u >= ty->rec.nfields) return;
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
for (++i; i < ty->rec.nfields; ++i) {
const Field* f = &ty->rec.fields[i];
@@ -634,12 +631,12 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
if (ty->kind == TY_ARRAY) {
const Type* elem_ty = ty->arr.elem;
u32 esz = c_abi_sizeof(p->abi, p->pool, elem_ty);
- if (p->cur.kind == TOK_STR &&
- string_literal_initializes_array(p, elem_ty, &p->cur)) {
+ if (p_cur(p)->kind == TOK_STR &&
+ string_literal_initializes_array(p, elem_ty, p_cur(p))) {
init_string_at(p, slot, arr_ty, offset, elem_ty, ty->arr.count);
return;
}
- if (is_punct(&p->cur, '{') && peek1(p).kind == TOK_STR) {
+ if (is_punct(p_cur(p), '{') && peek1(p).kind == TOK_STR) {
Tok str = peek1(p);
if (string_literal_initializes_array(p, elem_ty, &str)) {
advance(p);
@@ -649,7 +646,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
return;
}
}
- if (!is_punct(&p->cur, '{')) {
+ if (!is_punct(p_cur(p), '{')) {
init_aggregate_remainder(p, slot, arr_ty, offset, ty, 0);
return;
}
@@ -657,9 +654,9 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
{
u32 i = 0;
u32 zero_lo = 0;
- if (!is_punct(&p->cur, '}')) {
+ if (!is_punct(p_cur(p), '}')) {
for (;;) {
- if (is_punct(&p->cur, '[')) {
+ if (is_punct(p_cur(p), '[')) {
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
@@ -673,7 +670,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
init_at(p, slot, arr_ty, sub_off, sub_ty);
if (designator_continues_inside(p, ty, offset, elem_ty,
offset + top_idx * esz, &cont) &&
- accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
+ accept_punct(p, ',') && !is_punct(p_cur(p), '}')) {
init_aggregate_remainder(p, slot, arr_ty, cont.parent_offset,
cont.parent_ty, cont.next_index);
}
@@ -688,7 +685,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
if (zero_lo < i) zero_lo = i;
}
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
}
expect_punct(p, '}', "'}' after array initializer");
@@ -702,7 +699,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
return;
}
if (ty->kind == TY_STRUCT) {
- if (!is_punct(&p->cur, '{')) {
+ if (!is_punct(p_cur(p), '{')) {
if (try_init_aggregate_from_expr(p, slot, arr_ty, offset, ty)) return;
init_aggregate_remainder(p, slot, arr_ty, offset, ty, 0);
return;
@@ -723,7 +720,7 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset,
if (had_brace) expect_punct(p, '}', "'}'");
return;
}
- if (had_brace && is_punct(&p->cur, '.')) {
+ if (had_brace && is_punct(p_cur(p), '.')) {
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
@@ -847,13 +844,13 @@ static double parse_static_float_primary(Parser* p) {
expect_punct(p, ')', "')' in floating constant expression");
return v;
}
- if (p->cur.kind == TOK_FLT) {
- v = parse_float_literal(p, &p->cur);
+ if (p_cur(p)->kind == TOK_FLT) {
+ v = parse_float_literal(p, p_cur(p));
advance(p);
return v;
}
- if (p->cur.kind == TOK_NUM) {
- v = (double)parse_int_literal(p, &p->cur);
+ if (p_cur(p)->kind == TOK_NUM) {
+ v = (double)parse_int_literal(p, p_cur(p));
advance(p);
return v;
}
@@ -1065,7 +1062,7 @@ static CStaticConst parse_static_compound_literal_after_type(Parser* p,
SrcLoc loc) {
CStaticConst r;
memset(&r, 0, sizeof r);
- if (!is_punct(&p->cur, '{')) {
+ if (!is_punct(p_cur(p), '{')) {
perr(p, "expected compound literal initializer in static initializer");
}
r.kind = C_STATIC_CONST_ADDR;
@@ -1120,7 +1117,7 @@ static void check_static_integer_initializer_range(Parser* p, const Type* ty,
}
static CConstInt parse_null_pointer_constant(Parser* p, SrcLoc loc) {
- if (is_punct(&p->cur, '(')) {
+ if (is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
if (starts_type_name(p, &n)) {
const Type* cast_ty;
@@ -1151,7 +1148,7 @@ static CConstInt parse_null_pointer_constant(Parser* p, SrcLoc loc) {
/* Try to parse the current expression as a static initializer address
* constant. Leaves non-address expressions untouched. */
static int try_parse_static_address_const(Parser* p, CStaticConst* out) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
Sym name = 0;
int saw_amp = 0;
i64 element_addend = 0;
@@ -1175,7 +1172,7 @@ static int try_parse_static_address_const(Parser* p, CStaticConst* out) {
if (is_punct(&t, '&')) {
saw_amp = 1;
advance(p);
- if (is_punct(&p->cur, '(')) {
+ if (is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
if (starts_type_name(p, &n)) {
const Type* lit_ty;
@@ -1187,11 +1184,11 @@ static int try_parse_static_address_const(Parser* p, CStaticConst* out) {
return 1;
}
}
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected identifier after '&' in static initializer");
}
- name = tok_ident(&p->cur);
+ name = tok_ident(p_cur(p));
advance(p);
} else if (t.kind == TOK_IDENT &&
ident_kw_inline(p, tok_ident(&t)) == KW_NONE) {
@@ -1206,10 +1203,10 @@ static int try_parse_static_address_const(Parser* p, CStaticConst* out) {
}
tgt = e->v.sym;
tgt_ty = e->type;
- if (saw_amp && is_punct(&p->cur, '[')) {
+ if (saw_amp && is_punct(p_cur(p), '[')) {
SrcLoc cloc;
advance(p);
- cloc = tok_loc_init(p, &p->cur);
+ cloc = tok_loc_init(p, p_cur(p));
element_addend = eval_const_int(p, cloc);
expect_punct(p, ']', "']' after array-subscript constant");
if (tgt_ty && tgt_ty->kind == TY_ARRAY) {
@@ -1219,12 +1216,12 @@ static int try_parse_static_address_const(Parser* p, CStaticConst* out) {
byte_addend += element_addend;
}
}
- while (is_punct(&p->cur, '+') || is_punct(&p->cur, '-')) {
- int neg = is_punct(&p->cur, '-');
+ while (is_punct(p_cur(p), '+') || is_punct(p_cur(p), '-')) {
+ int neg = is_punct(p_cur(p), '-');
SrcLoc cloc;
i64 v;
advance(p);
- cloc = tok_loc_init(p, &p->cur);
+ cloc = tok_loc_init(p, p_cur(p));
v = eval_const_int(p, cloc);
if (neg) v = -v;
if (tgt_ty && tgt_ty->kind == TY_ARRAY) {
@@ -1249,25 +1246,25 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) {
memset(&r, 0, sizeof r);
r.kind = C_STATIC_CONST_INT;
if (ty && ty->kind == TY_PTR) {
- if (is_punct(&p->cur, P_AND)) {
+ if (is_punct(p_cur(p), P_AND)) {
/* GNU labels-as-values: `&&label` in a static pointer initializer,
* e.g. a direct-threaded dispatch table `static void *tab[] = {...}`. */
Sym lname;
SrcLoc lloc;
advance(p); /* '&&' */
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected label name after '&&' in static initializer");
}
- lname = tok_ident(&p->cur);
- lloc = tok_loc_init(p, &p->cur);
+ lname = tok_ident(p_cur(p));
+ lloc = tok_loc_init(p, p_cur(p));
advance(p);
r.kind = C_STATIC_CONST_LABEL_ADDR;
r.label = take_label_addr(p, lname, lloc);
r.addend = 0;
return r;
}
- if (is_punct(&p->cur, '(')) {
+ if (is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
/* Grouping parens around the pointer initializer, e.g. `("str")`,
* `(&x)`, or `((expr))`. A `(type-name)` is a cast or compound literal
@@ -1280,7 +1277,7 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) {
return r;
}
}
- if (is_punct(&p->cur, '(')) {
+ if (is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
if (starts_type_name(p, &n)) {
const Type* cast_ty;
@@ -1289,7 +1286,7 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) {
cast_ty = parse_type_name(p);
cast_unqual = type_unqual(p->pool, cast_ty);
expect_punct(p, ')', "')' after cast or compound literal type-name");
- if (is_punct(&p->cur, '{')) {
+ if (is_punct(p_cur(p), '{')) {
const Type* lit_unqual = type_unqual(p->pool, cast_ty);
if (!lit_unqual || lit_unqual->kind != TY_ARRAY) {
perr(p,
@@ -1303,9 +1300,9 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) {
perr(p, "invalid cast in null pointer constant");
}
if (cast_unqual->kind == TY_PTR &&
- (p->cur.kind == TOK_STR || is_punct(&p->cur, '&') ||
- (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE)) &&
+ (p_cur(p)->kind == TOK_STR || is_punct(p_cur(p), '&') ||
+ (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE)) &&
try_parse_static_address_const(p, &r)) {
return r;
}
@@ -1338,7 +1335,7 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) {
static void parse_static_bitfield_at(Parser* p, u8* buf, u32 buflen,
u32 rec_offset, const ABIFieldLayout* fl,
const Type* field_ty) {
- SrcLoc cloc = tok_loc_init(p, &p->cur);
+ SrcLoc cloc = tok_loc_init(p, p_cur(p));
CStaticConst parsed = parse_static_const(p, field_ty, cloc);
u32 storage_off = rec_offset + fl->offset;
u32 storage_size = fl->storage_size;
@@ -1374,7 +1371,7 @@ static void parse_static_aggregate_remainder(Parser* p, u8* buf, u32 buflen,
parse_static_init_at(p, buf, buflen, offset + i * esz, elem);
if (i + 1u >= ty->arr.count) return;
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
return;
}
@@ -1395,7 +1392,7 @@ static void parse_static_aggregate_remainder(Parser* p, u8* buf, u32 buflen,
}
if (i + 1u >= ty->rec.nfields) return;
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
return;
}
@@ -1412,7 +1409,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
* own handling (parse_static_const / eval_const), where a compound literal
* can instead yield an address or value. */
if ((ty->kind == TY_STRUCT || ty->kind == TY_UNION || ty->kind == TY_ARRAY) &&
- is_punct(&p->cur, '(')) {
+ is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
if (starts_type_name(p, &n)) {
advance(p);
@@ -1430,12 +1427,12 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
u32 esz = c_abi_sizeof(p->abi, p->pool, elem);
u32 i = 0;
int had_brace;
- if (p->cur.kind == TOK_STR &&
- string_literal_initializes_array(p, elem, &p->cur)) {
+ if (p_cur(p)->kind == TOK_STR &&
+ string_literal_initializes_array(p, elem, p_cur(p))) {
parse_static_string_at(p, buf, buflen, offset, elem, ty->arr.count);
return;
}
- if (is_punct(&p->cur, '{') && peek1(p).kind == TOK_STR) {
+ if (is_punct(p_cur(p), '{') && peek1(p).kind == TOK_STR) {
Tok str = peek1(p);
if (string_literal_initializes_array(p, elem, &str)) {
advance(p);
@@ -1450,9 +1447,9 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
parse_static_aggregate_remainder(p, buf, buflen, offset, ty, 0);
return;
}
- if (!is_punct(&p->cur, '}')) {
+ if (!is_punct(p_cur(p), '}')) {
for (;;) {
- if (is_punct(&p->cur, '[')) {
+ if (is_punct(p_cur(p), '[')) {
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
@@ -1462,7 +1459,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
parse_static_init_at(p, buf, buflen, sub_off, sub_ty);
if (designator_continues_inside(p, ty, offset, elem,
offset + top_idx * esz, &cont) &&
- accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
+ accept_punct(p, ',') && !is_punct(p_cur(p), '}')) {
parse_static_aggregate_remainder(p, buf, buflen, cont.parent_offset,
cont.parent_ty, cont.next_index);
}
@@ -1475,7 +1472,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
++i;
}
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
}
expect_punct(p, '}', "'}' after array initializer");
@@ -1492,9 +1489,9 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
/* Designators may re-target any field regardless of the running position
* `i`, so the loop is bounded by '}'/EOF; `i` only drives positional
* placement (and is range-checked before use). */
- while (!is_punct(&p->cur, '}') && p->cur.kind != TOK_EOF) {
+ while (!is_punct(p_cur(p), '}') && p_cur(p)->kind != TOK_EOF) {
const Field* f;
- if (is_punct(&p->cur, '.')) {
+ if (is_punct(p_cur(p), '.')) {
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
@@ -1507,7 +1504,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
u32 top_off = offset + L->fields[top_idx].offset;
if (designator_continues_inside(p, ty, offset, top_f->type, top_off,
&cont) &&
- accept_punct(p, ',') && !is_punct(&p->cur, '}')) {
+ accept_punct(p, ',') && !is_punct(p_cur(p), '}')) {
parse_static_aggregate_remainder(p, buf, buflen, cont.parent_offset,
cont.parent_ty, cont.next_index);
}
@@ -1540,7 +1537,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
if (had_brace) expect_punct(p, '}', "'}' after union initializer");
return;
}
- if (had_brace && is_punct(&p->cur, '.')) {
+ if (had_brace && is_punct(p_cur(p), '.')) {
const Type* sub_ty;
u32 sub_off;
u32 top_idx = 0;
@@ -1566,7 +1563,7 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset,
/* Scalar / pointer. */
{
int had_brace = accept_punct(p, '{');
- SrcLoc cloc = tok_loc_init(p, &p->cur);
+ SrcLoc cloc = tok_loc_init(p, p_cur(p));
u32 sz = c_abi_sizeof(p->abi, p->pool, ty);
CStaticConst cv;
if (offset + sz > buflen) perr(p, "initializer overflows object");
diff --git a/lang/c/parse/parse_priv.h b/lang/c/parse/parse_priv.h
@@ -234,6 +234,37 @@ struct GotoLabel {
};
/* ============================================================
+ * Parser input ring
+ * ============================================================ */
+
+/* The parser consumes pp output through a fixed 3-cell ring (see
+ * doc/plan/FRONTEND-SHAPE.md "Parser Input Ring"). cells[cur] is the current
+ * token (depth 0); the two trailing slots provide LL(2) lookahead headroom. The
+ * C parser is strictly LL(1) today (only depths 0/1 are read), so the depth-2
+ * slot stays unfilled until something calls parser_peek(p, 2). No VLAs: the
+ * lookahead window is fixed; variable replay uses the parser arena. Cells are
+ * always lexeme view. */
+typedef struct ParserInput {
+ CFeCell cells[3]; /* fixed cur + LL(2) lookahead ring; no VLA */
+ u8 cur; /* index of the current token in cells[] */
+ u8 nvalid; /* number of valid slots from cur, 0..3 */
+ CFeCell pending; /* string-literal fusion / one-token pushback */
+ u8 has_pending;
+} ParserInput;
+
+/* Ring accessors. parser_ring_idx maps a depth (0 == current) to a physical
+ * slot; parser_cur borrows the current cell. */
+static inline u8 parser_ring_idx(const ParserInput* in, u32 d) {
+ return (u8)((in->cur + d) % 3u);
+}
+static inline CFeCell* parser_cur(ParserInput* in) {
+ return &in->cells[in->cur];
+}
+static inline const CFeCell* parser_cur_const(const ParserInput* in) {
+ return &in->cells[in->cur];
+}
+
+/* ============================================================
* Parser context
* ============================================================ */
@@ -247,12 +278,7 @@ typedef struct Parser {
u8 default_visibility; /* SymVis */
u8 auto_var_init; /* KitAutoVarInit: implicit init for uninit locals */
- Tok cur;
- Tok next;
- int has_next;
-
- Tok pending;
- int has_pending;
+ ParserInput input;
Sym kw_sym[KW_COUNT];
KwTab kw_map; /* keyword/alias Sym -> CKw; built once, see ident_kw_inline */
@@ -406,6 +432,13 @@ typedef struct Parser {
u32 static_relocs_cap;
} Parser;
+/* Borrowed pointer to the current token cell (depth 0). Valid until the next
+ * advance or replay-source switch. */
+static inline CFeCell* p_cur(Parser* p) { return parser_cur(&p->input); }
+static inline const CFeCell* p_cur_const(const Parser* p) {
+ return parser_cur_const(&p->input);
+}
+
/* ============================================================
* DeclSpecs and TypeSpecAccum
* ============================================================ */
@@ -443,6 +476,13 @@ typedef struct TypeSpecAccum {
* ============================================================ */
_Noreturn void perr(Parser* p, const char* fmt, ...);
+
+void parser_advance(Parser* p);
+void parser_fill_to(Parser* p, u32 depth); /* cold path: fills through depth */
+/* Borrowed pointer to the cell at lookahead `depth` (0 == current); LL(2)
+ * headroom. Valid until the next advance or replay-source switch. */
+const CFeCell* parser_peek(Parser* p, u32 depth);
+
void advance(Parser* p);
Tok peek1(Parser* p);
void expect_punct(Parser* p, u32 punct, const char* what);
@@ -650,4 +690,7 @@ FrameSlot make_local_aligned(Parser* p, Sym name, const Type* type, SrcLoc loc,
Sym mint_static_local_sym(Parser* p, Sym orig);
void record_braced_block(Parser* p);
void replay_rewind(Parser* p);
+/* Switch the input source to the parser's replay buffer (replay[0..]); resets
+ * the ring. Caller sets replay/replay_cap/replay_len first. */
+void parser_replay_begin(Parser* p);
u32 count_recorded_top_level_items(const Tok* vec, u32 len);
diff --git a/lang/c/parse/parse_stmt.c b/lang/c/parse/parse_stmt.c
@@ -16,7 +16,7 @@ static SrcLoc tok_loc_stmt(Parser* p, const Tok* t) {
}
static int accept_kw_stmt(Parser* p, CKw k) {
- if (!is_kw(p, &p->cur, k)) return 0;
+ if (!is_kw(p, p_cur(p), k)) return 0;
advance(p);
return 1;
}
@@ -143,7 +143,7 @@ static void parse_for_stmt(Parser* p) {
}
c_cg_label_place(p, L_top);
- if (!is_punct(&p->cur, ';')) {
+ if (!is_punct(p_cur(p), ';')) {
parse_expr(p);
to_rvalue(p);
if (!c_type_is_scalar(c_cg_top_type(p))) {
@@ -157,7 +157,7 @@ static void parse_for_stmt(Parser* p) {
CGLabel L_body = c_cg_label_new(p);
c_cg_jump(p, L_body);
c_cg_label_place(p, L_step);
- if (!is_punct(&p->cur, ')')) {
+ if (!is_punct(p_cur(p), ')')) {
parse_expr(p);
c_cg_drop(p);
}
@@ -230,7 +230,7 @@ static void parse_do_stmt(Parser* p) {
p->cur_break = saved_break;
p->cur_continue = saved_continue;
c_cg_label_place(p, L_cond);
- if (!is_kw(p, &p->cur, KW_WHILE)) perr(p, "expected 'while' after do-body");
+ if (!is_kw(p, p_cur(p), KW_WHILE)) perr(p, "expected 'while' after do-body");
advance(p); /* while */
expect_punct(p, '(', "'('");
parse_expr(p);
@@ -320,16 +320,16 @@ static void parse_goto_stmt(Parser* p) {
Sym name;
SrcLoc loc;
GotoLabel* gl;
- if (is_punct(&p->cur, '*')) {
+ if (is_punct(p_cur(p), '*')) {
parse_computed_goto(p);
return;
}
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected label name after 'goto'");
}
- name = tok_ident(&p->cur);
- loc = tok_loc_stmt(p, &p->cur);
+ name = tok_ident(p_cur(p));
+ loc = tok_loc_stmt(p, p_cur(p));
advance(p);
expect_punct(p, ';', "';' after goto");
gl = label_get_or_create(p, name, loc);
@@ -344,8 +344,8 @@ static void parse_goto_stmt(Parser* p) {
}
static void parse_label_stmt(Parser* p) {
- Sym name = tok_ident(&p->cur);
- SrcLoc loc = tok_loc_stmt(p, &p->cur);
+ Sym name = tok_ident(p_cur(p));
+ SrcLoc loc = tok_loc_stmt(p, p_cur(p));
GotoLabel* gl;
advance(p); /* IDENT */
advance(p); /* ':' */
@@ -364,7 +364,7 @@ static void parse_case_stmt(Parser* p) {
i64 v;
CGLabel L;
CaseEntry* ce;
- SrcLoc loc = tok_loc_stmt(p, &p->cur);
+ SrcLoc loc = tok_loc_stmt(p, p_cur(p));
if (!p->cur_switch) perr(p, "'case' label not in switch statement");
v = eval_const_int(p, loc);
for (ce = p->cur_switch->cases; ce; ce = ce->next) {
@@ -533,19 +533,19 @@ static void parse_switch_stmt(Parser* p) {
}
void parse_static_assert(Parser* p) {
- SrcLoc loc = tok_loc_stmt(p, &p->cur);
+ SrcLoc loc = tok_loc_stmt(p, p_cur(p));
i64 v;
if (!accept_kw_stmt(p, KW_STATIC_ASSERT)) {
perr(p, "expected _Static_assert");
}
expect_punct(p, '(', "'(' after _Static_assert");
- v = eval_const_int(p, tok_loc_stmt(p, &p->cur));
+ v = eval_const_int(p, tok_loc_stmt(p, p_cur(p)));
expect_punct(p, ',', "',' separating _Static_assert args");
- if (p->cur.kind != TOK_STR) {
+ if (p_cur(p)->kind != TOK_STR) {
perr(p, "expected string literal as _Static_assert message");
}
{
- Tok msg = p->cur;
+ Tok msg = *p_cur(p);
advance(p);
expect_punct(p, ')', "')' after _Static_assert");
expect_punct(p, ';', "';' after _Static_assert");
@@ -587,12 +587,12 @@ static void asm_out_value_push(Parser* p, const AsmOutLValue* lv) {
static Sym parse_asm_operand_name(Parser* p) {
Sym name = 0;
- if (!is_punct(&p->cur, '[')) return 0;
+ if (!is_punct(p_cur(p), '[')) return 0;
advance(p);
- if (p->cur.kind != TOK_IDENT) {
+ if (p_cur(p)->kind != TOK_IDENT) {
perr(p, "expected identifier inside '[name]' on asm operand");
}
- name = tok_ident(&p->cur);
+ name = tok_ident(p_cur(p));
advance(p);
expect_punct(p, ']', "']' after asm operand name");
return name;
@@ -603,11 +603,11 @@ static const char* parse_asm_str(Parser* p, const char* what) {
size_t nlen = 0;
Sym s;
Tok t;
- if (p->cur.kind != TOK_STR) {
+ if (p_cur(p)->kind != TOK_STR) {
perr(p, "expected string literal in %.*s",
KIT_SLICE_ARG(kit_slice_cstr(what)));
}
- t = p->cur;
+ t = *p_cur(p);
advance(p);
bytes = decode_string_literal(p, &t, &nlen);
if (nlen > 0) nlen -= 1;
@@ -620,7 +620,7 @@ static const char* parse_asm_str(Parser* p, const char* what) {
/* GNU local register variables: when an asm operand is exactly a bare reference
* to a `register T x __asm__("reg")` local, return that register name (else 0).
- * Called with p->cur positioned at the first token of the operand expression,
+ * Called with the current token positioned at the first token of the operand expression,
* so it only peeks — it must not consume. The operand has to be a lone
* identifier (the canonical idiom); anything more complex is not a
* hard-register operand under GCC's rules either. The name is carried opaquely
@@ -630,10 +630,10 @@ static const char* parse_asm_str(Parser* p, const char* what) {
static Sym asm_operand_pinned_reg(Parser* p, FrameSlot* slot_out) {
Tok nxt;
SymEntry* e;
- if (p->cur.kind != TOK_IDENT) return 0;
+ if (p_cur(p)->kind != TOK_IDENT) return 0;
nxt = peek1(p);
if (!is_punct(&nxt, ')')) return 0;
- e = scope_lookup(p, tok_ident(&p->cur));
+ e = scope_lookup(p, tok_ident(p_cur(p)));
if (!e || e->kind != SEK_LOCAL) return 0;
if (e->reg_asm_name && slot_out) *slot_out = e->v.slot;
return e->reg_asm_name;
@@ -648,7 +648,7 @@ static void parse_asm_stmt(Parser* p) {
u32 nout = 0, nin = 0, nclob = 0;
u32 cap_out = 0, cap_in = 0, cap_clob = 0;
int saw_goto = 0;
- SrcLoc loc = tok_loc_stmt(p, &p->cur);
+ SrcLoc loc = tok_loc_stmt(p, p_cur(p));
for (;;) {
if (accept_kw_stmt(p, KW_VOLATILE))
@@ -661,7 +661,7 @@ static void parse_asm_stmt(Parser* p) {
tmpl = parse_asm_str(p, "asm template");
if (accept_punct(p, ':')) {
- if (!is_punct(&p->cur, ':') && !is_punct(&p->cur, ')')) {
+ if (!is_punct(p_cur(p), ':') && !is_punct(p_cur(p), ')')) {
cap_out = 4;
outs =
(AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, cap_out);
@@ -732,7 +732,7 @@ static void parse_asm_stmt(Parser* p) {
}
if (accept_punct(p, ':')) {
- if (!is_punct(&p->cur, ':') && !is_punct(&p->cur, ')')) {
+ if (!is_punct(p_cur(p), ':') && !is_punct(p_cur(p), ')')) {
cap_in = 4;
ins =
(AsmConstraint*)arena_array(p->pool->arena, AsmConstraint, cap_in);
@@ -762,7 +762,7 @@ static void parse_asm_stmt(Parser* p) {
}
if (accept_punct(p, ':')) {
- if (!is_punct(&p->cur, ':') && !is_punct(&p->cur, ')')) {
+ if (!is_punct(p_cur(p), ':') && !is_punct(p_cur(p), ')')) {
cap_clob = 4;
clobbers = (Sym*)arena_array(p->pool->arena, Sym, cap_clob);
for (;;) {
@@ -783,9 +783,9 @@ static void parse_asm_stmt(Parser* p) {
}
if (accept_punct(p, ':')) {
- if (!is_punct(&p->cur, ')')) {
+ if (!is_punct(p_cur(p), ')')) {
for (;;) {
- if (p->cur.kind != TOK_IDENT) {
+ if (p_cur(p)->kind != TOK_IDENT) {
perr(p, "expected label identifier in asm-goto label list");
}
advance(p);
@@ -854,18 +854,18 @@ static void parse_asm_stmt(Parser* p) {
void parse_compound_stmt(Parser* p) {
expect_punct(p, '{', "'{'");
scope_push(p);
- while (!is_punct(&p->cur, '}') && p->cur.kind != TOK_EOF) {
- if (p->cur.kind == TOK_NEWLINE || is_pp_hash(&p->cur)) {
+ while (!is_punct(p_cur(p), '}') && p_cur(p)->kind != TOK_EOF) {
+ if (p_cur(p)->kind == TOK_NEWLINE || is_pp_hash(p_cur(p))) {
advance(p);
continue;
}
- if (is_kw(p, &p->cur, KW_STATIC_ASSERT)) {
+ if (is_kw(p, p_cur(p), KW_STATIC_ASSERT)) {
parse_static_assert(p);
continue;
}
{
DeclSpecs specs;
- Tok save_tok = p->cur;
+ Tok save_tok = *p_cur(p);
(void)save_tok;
if (parse_decl_specs(p, &specs)) {
parse_local_decl(p, &specs);
@@ -883,79 +883,79 @@ void parse_compound_stmt(Parser* p) {
}
void parse_stmt(Parser* p) {
- c_cg_set_loc(p, tok_loc_stmt(p, &p->cur));
- if (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE) {
+ c_cg_set_loc(p, tok_loc_stmt(p, p_cur(p)));
+ if (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE) {
Tok n = peek1(p);
if (is_punct(&n, ':')) {
parse_label_stmt(p);
return;
}
}
- if (is_punct(&p->cur, '{')) {
+ if (is_punct(p_cur(p), '{')) {
parse_compound_stmt(p);
return;
}
- if (is_punct(&p->cur, ';')) {
+ if (is_punct(p_cur(p), ';')) {
advance(p);
return;
}
- if (is_kw(p, &p->cur, KW_IF)) {
+ if (is_kw(p, p_cur(p), KW_IF)) {
advance(p);
parse_if_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_WHILE)) {
+ if (is_kw(p, p_cur(p), KW_WHILE)) {
advance(p);
parse_while_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_FOR)) {
+ if (is_kw(p, p_cur(p), KW_FOR)) {
advance(p);
parse_for_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_DO)) {
+ if (is_kw(p, p_cur(p), KW_DO)) {
advance(p);
parse_do_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_RETURN)) {
+ if (is_kw(p, p_cur(p), KW_RETURN)) {
advance(p);
parse_return_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_BREAK)) {
+ if (is_kw(p, p_cur(p), KW_BREAK)) {
advance(p);
parse_break_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_CONTINUE)) {
+ if (is_kw(p, p_cur(p), KW_CONTINUE)) {
advance(p);
parse_continue_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_GOTO)) {
+ if (is_kw(p, p_cur(p), KW_GOTO)) {
advance(p);
parse_goto_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_SWITCH)) {
+ if (is_kw(p, p_cur(p), KW_SWITCH)) {
advance(p);
parse_switch_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_CASE)) {
+ if (is_kw(p, p_cur(p), KW_CASE)) {
advance(p);
parse_case_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_DEFAULT)) {
+ if (is_kw(p, p_cur(p), KW_DEFAULT)) {
advance(p);
parse_default_stmt(p);
return;
}
- if (is_kw(p, &p->cur, KW_ASM) || is_kw(p, &p->cur, KW_BUILTIN_ASM)) {
+ if (is_kw(p, p_cur(p), KW_ASM) || is_kw(p, p_cur(p), KW_BUILTIN_ASM)) {
advance(p);
parse_asm_stmt(p);
return;
diff --git a/lang/c/parse/parse_type.c b/lang/c/parse/parse_type.c
@@ -76,7 +76,7 @@ static void attr_canon_range(const char* s, size_t len, const char** out_p,
size_t* out_len);
static int accept_kw(Parser* p, CKw k) {
- if (is_kw(p, &p->cur, k)) {
+ if (is_kw(p, p_cur(p), k)) {
advance(p);
return 1;
}
@@ -111,18 +111,20 @@ static const Type* attrs_apply_type_mode(Parser* p, const Type* base,
}
int starts_attr(const Parser* p) {
- return p->cur.kind == TOK_IDENT && tok_ident(&p->cur) == p->sym_attribute;
+ return p_cur_const(p)->kind == TOK_IDENT &&
+ tok_ident(p_cur_const(p)) == p->sym_attribute;
}
static int starts_asm_label(const Parser* p) {
- return is_kw(p, &p->cur, KW_ASM) || is_kw(p, &p->cur, KW_BUILTIN_ASM);
+ return is_kw(p, p_cur_const(p), KW_ASM) ||
+ is_kw(p, p_cur_const(p), KW_BUILTIN_ASM);
}
static Sym parse_asm_label(Parser* p) {
Sym label = 0;
advance(p); /* asm / __asm / __asm__ */
expect_punct(p, '(', "'(' after asm label");
- if (p->cur.kind != TOK_STR) {
+ if (p_cur(p)->kind != TOK_STR) {
perr(p, "expected string literal in asm label");
}
/* Capture the label string for the declarator currently being parsed. For a
@@ -130,7 +132,7 @@ static Sym parse_asm_label(Parser* p) {
* variable binds to. Other asm labels (symbol renames) are still effectively
* ignored by callers that do not consume DeclaratorInfo.asm_label. */
{
- Tok t = p->cur;
+ Tok t = *p_cur(p);
size_t nlen = 0;
u8* bytes = decode_string_literal(p, &t, &nlen);
u32 ilen = (nlen > 0) ? (u32)(nlen - 1) : 0;
@@ -141,7 +143,7 @@ static Sym parse_asm_label(Parser* p) {
}
do {
advance(p);
- } while (p->cur.kind == TOK_STR);
+ } while (p_cur(p)->kind == TOK_STR);
expect_punct(p, ')', "')' after asm label");
return label;
}
@@ -216,16 +218,16 @@ static AttrKind classify_attr(Parser* p, Sym name, AttrArgShape* shape_out) {
static void skip_balanced_parens(Parser* p) {
int depth;
- if (!is_punct(&p->cur, '(')) perr(p, "internal: skip_balanced_parens");
+ if (!is_punct(p_cur(p), '(')) perr(p, "internal: skip_balanced_parens");
depth = 1;
advance(p);
while (depth > 0) {
- if (p->cur.kind == TOK_EOF) {
+ if (p_cur(p)->kind == TOK_EOF) {
perr(p, "unexpected EOF inside attribute arguments");
}
- if (is_punct(&p->cur, '('))
+ if (is_punct(p_cur(p), '('))
++depth;
- else if (is_punct(&p->cur, ')')) {
+ else if (is_punct(p_cur(p), ')')) {
--depth;
if (depth == 0) {
advance(p);
@@ -238,7 +240,7 @@ static void skip_balanced_parens(Parser* p) {
static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
const char* attr_diag_name) {
- if (!is_punct(&p->cur, '(')) {
+ if (!is_punct(p_cur(p), '(')) {
if (shape == AS_NONE || shape == AS_OPTIONAL || shape == AS_INT_OPT ||
shape == AS_OPAQUE) {
return;
@@ -263,7 +265,7 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
case AS_INT_OPT: {
SrcLoc loc;
advance(p); /* '(' */
- if (is_punct(&p->cur, ')')) {
+ if (is_punct(p_cur(p), ')')) {
if (shape == AS_INT) {
perr(p, "attribute '%.*s' expects an integer argument",
KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
@@ -271,7 +273,7 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
advance(p);
return;
}
- loc = tok_loc(p, &p->cur);
+ loc = tok_loc(p, p_cur(p));
a->v.i = eval_const_int(p, loc);
if (a->kind == ATTR_ALIGNED && a->v.i > 0 &&
(((u64)a->v.i & ((u64)a->v.i - 1u)) != 0)) {
@@ -283,12 +285,12 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
}
case AS_STRING: {
advance(p); /* '(' */
- if (p->cur.kind != TOK_STR) {
+ if (p_cur(p)->kind != TOK_STR) {
perr(p, "attribute '%.*s' expects a string literal",
KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
}
{
- Tok t = p->cur;
+ Tok t = *p_cur(p);
size_t nlen = 0;
u8* bytes = decode_string_literal(p, &t, &nlen);
u32 ilen = (nlen > 0) ? (u32)(nlen - 1) : 0;
@@ -304,11 +306,11 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
}
case AS_IDENT: {
advance(p); /* '(' */
- if (p->cur.kind != TOK_IDENT) {
+ if (p_cur(p)->kind != TOK_IDENT) {
perr(p, "attribute '%.*s' expects an identifier",
KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
}
- a->v.sym = tok_ident(&p->cur);
+ a->v.sym = tok_ident(p_cur(p));
a->nargs = 1;
advance(p);
expect_punct(p, ')', "')' after attribute identifier argument");
@@ -318,15 +320,15 @@ static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
SrcLoc mloc, nloc;
i64 mv, nv;
advance(p); /* '(' */
- if (p->cur.kind != TOK_IDENT) {
+ if (p_cur(p)->kind != TOK_IDENT) {
perr(p, "attribute 'format' expects (archetype, m, n)");
}
advance(p);
expect_punct(p, ',', "',' after format archetype");
- mloc = tok_loc(p, &p->cur);
+ mloc = tok_loc(p, p_cur(p));
mv = eval_const_int(p, mloc);
expect_punct(p, ',', "',' after format string-index");
- nloc = tok_loc(p, &p->cur);
+ nloc = tok_loc(p, p_cur(p));
nv = eval_const_int(p, nloc);
if (mv < 0 || mv > 0xFFFF || nv < 0 || nv > 0xFFFF) {
perr(p, "attribute 'format' indices out of range");
@@ -349,7 +351,7 @@ Attr* parse_attribute_spec_list(Parser* p) {
Attr* head = NULL;
Attr* tail = NULL;
while (starts_attr(p)) {
- SrcLoc kw_loc = tok_loc(p, &p->cur);
+ SrcLoc kw_loc = tok_loc(p, p_cur(p));
advance(p); /* __attribute__ */
expect_punct(p, '(', "'(' after __attribute__");
expect_punct(p, '(', "'((' after __attribute__");
@@ -363,15 +365,15 @@ Attr* parse_attribute_spec_list(Parser* p) {
size_t canon_len;
while (accept_punct(p, ',')) { /* skip */
}
- if (is_punct(&p->cur, ')')) break;
- if (p->cur.kind != TOK_IDENT) {
+ if (is_punct(p_cur(p), ')')) break;
+ if (p_cur(p)->kind != TOK_IDENT) {
perr(p, "expected attribute name");
}
- aname = tok_ident(&p->cur);
+ aname = tok_ident(p_cur(p));
a = arena_new(p->pool->arena, Attr);
if (!a) perr(p, "out of memory in parse_attribute_spec_list");
memset(a, 0, sizeof *a);
- a->loc = tok_loc(p, &p->cur);
+ a->loc = tok_loc(p, p_cur(p));
a->name = aname;
a->kind = (u16)classify_attr(p, aname, &shape);
advance(p);
@@ -608,9 +610,9 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) {
out->vla_byte_slot = FRAME_SLOT_NONE;
out->vla_bounds = NULL;
out->attrs = NULL;
- loc = tok_loc(p, &p->cur);
+ loc = tok_loc(p, p_cur(p));
for (;;) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
/* Classify the token's keyword identity exactly once per iteration; the
* decl-spec dispatch below compares against this instead of re-deciding
* keyword-ness per candidate (was ~26 is_kw probes/token). */
@@ -779,11 +781,11 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) {
u32 a = 0;
advance(p); /* `_Alignas` */
expect_punct(p, '(', "'(' after _Alignas");
- if (starts_type_name(p, &p->cur)) {
+ if (starts_type_name(p, p_cur(p))) {
const Type* tn = parse_type_name(p);
a = c_abi_alignof(p->abi, p->pool, tn);
} else {
- i64 v = eval_const_int(p, tok_loc(p, &p->cur));
+ i64 v = eval_const_int(p, tok_loc(p, p_cur(p)));
if (v < 0) perr(p, "_Alignas requires a non-negative alignment");
a = (u32)v;
}
@@ -955,12 +957,12 @@ static void parse_member_decls(Parser* p, TypeRecordBuilder* b) {
MemberNameSeen* names = NULL;
u32 field_count = 0;
int saw_flexible = 0;
- while (!is_punct(&p->cur, '}') && p->cur.kind != TOK_EOF) {
+ while (!is_punct(p_cur(p), '}') && p_cur(p)->kind != TOK_EOF) {
DeclSpecs specs;
if (!parse_decl_specs(p, &specs)) {
perr(p, "expected member declaration");
}
- if (is_punct(&p->cur, ';')) {
+ if (is_punct(p_cur(p), ';')) {
if (specs.type &&
(specs.type->kind == TY_STRUCT || specs.type->kind == TY_UNION)) {
Field f;
@@ -977,11 +979,11 @@ static void parse_member_decls(Parser* p, TypeRecordBuilder* b) {
}
for (;;) {
Sym mname = 0;
- SrcLoc mloc = tok_loc(p, &p->cur);
+ SrcLoc mloc = tok_loc(p, p_cur(p));
const Type* mty;
Field f;
memset(&f, 0, sizeof f);
- if (is_punct(&p->cur, ':')) {
+ if (is_punct(p_cur(p), ':')) {
advance(p);
if (!type_is_int(specs.type)) perr(p, "bit-field has non-integer type");
i64 w = eval_const_int(p, mloc);
@@ -1046,13 +1048,13 @@ const Type* parse_struct_or_union(Parser* p, TypeKind kind,
TagDeclKind tdk = (kind == TY_STRUCT) ? TAG_STRUCT : TAG_UNION;
Attr* rec_attrs = NULL;
parse_attrs_into(p, &rec_attrs);
- tag_loc = tok_loc(p, &p->cur);
- if (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE) {
- tag_name = tok_ident(&p->cur);
+ tag_loc = tok_loc(p, p_cur(p));
+ if (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE) {
+ tag_name = tok_ident(p_cur(p));
advance(p);
}
- int has_body = is_punct(&p->cur, '{');
+ int has_body = is_punct(p_cur(p), '{');
if (!has_body && tag_name == 0) {
perr(p, "expected tag name or '{' after struct/union");
}
@@ -1141,10 +1143,10 @@ const Type* parse_enum(Parser* p, Attr** anon_attrs_out) {
SrcLoc tag_loc;
Attr* rec_attrs = NULL;
parse_attrs_into(p, &rec_attrs);
- tag_loc = tok_loc(p, &p->cur);
- if (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE) {
- tag_name = tok_ident(&p->cur);
+ tag_loc = tok_loc(p, p_cur(p));
+ if (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE) {
+ tag_name = tok_ident(p_cur(p));
advance(p);
}
/* C23 §6.7.2.2: an optional fixed underlying type — `enum [tag] : T` —
@@ -1157,7 +1159,7 @@ const Type* parse_enum(Parser* p, Attr** anon_attrs_out) {
underlying = parse_type_name(p);
has_fixed_type = 1;
}
- int has_body = is_punct(&p->cur, '{');
+ int has_body = is_punct(p_cur(p), '{');
if (!has_body && tag_name == 0) {
perr(p, "expected tag name or '{' after enum");
}
@@ -1197,13 +1199,13 @@ const Type* parse_enum(Parser* p, Attr** anon_attrs_out) {
u32 nconsts = 0, consts_cap = 0;
for (;;) {
Sym name;
- SrcLoc nloc = tok_loc(p, &p->cur);
+ SrcLoc nloc = tok_loc(p, p_cur(p));
SymEntry* e;
- if (p->cur.kind != TOK_IDENT ||
- ident_kw_inline(p, tok_ident(&p->cur)) != KW_NONE) {
+ if (p_cur(p)->kind != TOK_IDENT ||
+ ident_kw_inline(p, tok_ident(p_cur(p))) != KW_NONE) {
perr(p, "expected enumerator name");
}
- name = tok_ident(&p->cur);
+ name = tok_ident(p_cur(p));
advance(p);
i64 val = next_val;
if (accept_punct(p, '=')) {
@@ -1228,7 +1230,7 @@ const Type* parse_enum(Parser* p, Attr** anon_attrs_out) {
nconsts++;
}
if (!accept_punct(p, ',')) break;
- if (is_punct(&p->cur, '}')) break;
+ if (is_punct(p_cur(p), '}')) break;
}
expect_punct(p, '}', "'}' after enumerator list");
((Type*)et)->enm.consts = consts;
@@ -1379,7 +1381,7 @@ static void parse_param_array_bound(Parser* p, DeclSuffix* out) {
return;
}
while (depth > 0) {
- Tok t = p->cur;
+ Tok t = *p_cur(p);
if (t.kind == TOK_EOF) {
perr(p, "unexpected EOF in parameter array bound");
}
@@ -1441,7 +1443,7 @@ int parse_decl_suffix(Parser* p, DeclSuffix* out) {
return 1;
}
{
- Tok t = p->cur;
+ Tok t = *p_cur(p);
/* A VLA is a block-scope-only feature (§6.7.6.2¶4): at file scope every
* declared array bound must be an integer constant expression. Route all
* file-scope bounds through eval_const_int below, so a non-constant bound
@@ -1463,7 +1465,7 @@ int parse_decl_suffix(Parser* p, DeclSuffix* out) {
}
}
if (is_const_start) {
- SrcLoc cloc = tok_loc(p, &p->cur);
+ SrcLoc cloc = tok_loc(p, p_cur(p));
i64 v = eval_const_int(p, cloc);
if (v < 0) perr(p, "negative array size");
out->count = (u32)v;
@@ -1591,7 +1593,7 @@ const Type* parse_declarator_full_info(Parser* p, const Type* base,
DeclSuffix inner_suffs[8];
int n_inner_suffs = 0;
- if (is_punct(&p->cur, '(')) {
+ if (is_punct(p_cur(p), '(')) {
Tok n = peek1(p);
int is_inner = 0;
if (is_punct(&n, '*')) {
@@ -1632,12 +1634,12 @@ const Type* parse_declarator_full_info(Parser* p, const Type* base,
}
inner_quals[nptrs_inner++] = q;
}
- if (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE) {
- name = tok_ident(&p->cur);
- nloc = tok_loc(p, &p->cur);
+ if (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE) {
+ name = tok_ident(p_cur(p));
+ nloc = tok_loc(p, p_cur(p));
advance(p);
- } else if (is_punct(&p->cur, '(')) {
+ } else if (is_punct(p_cur(p), '(')) {
Tok nn = peek1(p);
if (!is_punct(&nn, '*')) {
if (!allow_abstract) perr(p, "expected declarator name");
@@ -1672,10 +1674,10 @@ const Type* parse_declarator_full_info(Parser* p, const Type* base,
}
nested_quals[nptrs_nested++] = q;
}
- if (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE) {
- name = tok_ident(&p->cur);
- nloc = tok_loc(p, &p->cur);
+ if (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE) {
+ name = tok_ident(p_cur(p));
+ nloc = tok_loc(p, p_cur(p));
advance(p);
} else if (!allow_abstract) {
perr(p, "expected declarator name");
@@ -1697,10 +1699,10 @@ const Type* parse_declarator_full_info(Parser* p, const Type* base,
}
if (!has_inner_parens) {
- if (p->cur.kind == TOK_IDENT &&
- ident_kw_inline(p, tok_ident(&p->cur)) == KW_NONE) {
- name = tok_ident(&p->cur);
- nloc = tok_loc(p, &p->cur);
+ if (p_cur(p)->kind == TOK_IDENT &&
+ ident_kw_inline(p, tok_ident(p_cur(p))) == KW_NONE) {
+ name = tok_ident(p_cur(p));
+ nloc = tok_loc(p, p_cur(p));
advance(p);
} else if (!allow_abstract) {
perr(p, "expected declarator name");
@@ -1719,7 +1721,7 @@ const Type* parse_declarator_full_info(Parser* p, const Type* base,
parse_attrs_and_asm_into(p, attrs_out, &local_attrs, &asm_label);
}
base = attrs_apply_type_mode(p, base, attrs_out ? *attrs_out : local_attrs);
- if (nsuffs == 8 && (is_punct(&p->cur, '[') || is_punct(&p->cur, '('))) {
+ if (nsuffs == 8 && (is_punct(p_cur(p), '[') || is_punct(p_cur(p), '('))) {
perr(p, "too many declarator suffixes (raise the cap if needed)");
}
if (n_inner_suffs > 0 && inner_suffs[0].kind == DS_FUNC) {
@@ -1775,9 +1777,9 @@ const Type* complete_incomplete_array(Parser* p, const Type* ty) {
const Type* elem;
if (!ty || ty->kind != TY_ARRAY || !ty->arr.incomplete) return ty;
elem = ty->arr.elem;
- if (p->cur.kind == TOK_STR &&
- string_literal_initializes_array(p, elem, &p->cur)) {
- Tok t = p->cur;
+ if (p_cur(p)->kind == TOK_STR &&
+ string_literal_initializes_array(p, elem, p_cur(p))) {
+ Tok t = *p_cur(p);
size_t n = 0;
u8* bytes = decode_string_literal(p, &t, &n);
u32 elem_size = c_abi_sizeof(p->abi, p->pool, elem);
@@ -1786,7 +1788,7 @@ const Type* complete_incomplete_array(Parser* p, const Type* ty) {
return type_array(p->pool, elem, elem_size ? (u32)(n / elem_size) : 0,
/*incomplete=*/0);
}
- if (is_punct(&p->cur, '{')) {
+ if (is_punct(p_cur(p), '{')) {
u32 cnt;
record_braced_block(p);
cnt = count_recorded_top_level_items(p->replay, p->replay_len);