diff options
| author | 2022-08-06 05:42:19 +0200 | |
|---|---|---|
| committer | 2022-08-06 05:43:06 +0200 | |
| commit | 762c6c17c9effd360a6e00a440964cb176cf96e7 (patch) | |
| tree | 83f460ec36865dbb77808e22054f164a20bc26b1 /bootstrap/parse.c | |
| parent | 3083cf126cf3989b257546aa3b1b69608aac7923 (diff) | |
macro body arg
Diffstat (limited to 'bootstrap/parse.c')
| -rw-r--r-- | bootstrap/parse.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 4372cdc..2b0f08e 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -1642,6 +1642,7 @@ parseexpandmacro(struct parser *P, const struct macro *macro) { struct expan expan = {0}; struct expanarg *expanargs; struct macrocase c; + bool bodyarg = 0; expan.span = lexpeek(P).span; lexexpect(P, '('); @@ -1685,11 +1686,42 @@ parseexpandmacro(struct parser *P, const struct macro *macro) { } } + if (lexmatch(P, &tok, '{')) { + int pabal = 0, + bkbal = 0, + bcbal = 1; + struct span espan = tok.span; + vec_t(struct tok) toks = {0}; + struct toktree ttoks; + vec_push(&toks, (struct tok){'{'}); + bodyarg = 1; + + while (bcbal > 0) { + tok = lex(P); + switch (tok.t) { + case '[': ++bkbal; break; + case ']': --bkbal; break; + case '{': ++bcbal; break; + case '}': --bcbal; break; + case '(': ++pabal; break; + case ')': --pabal; break; + case TKeof: + fatal(P, espan, "unterminated macro `%s' invokation", macro->name); + } + vec_push(&toks, tok); + } + + vec_slice_cpy(&ttoks, &toks); + vec_push(&args, ttoks); + } + for (int i = 0; i < macro->cs.n; ++i) { c = macro->cs.d[i]; - if (!c.variadic && args.length == c.params.n) { + if (c.bodyarg && bodyarg && args.length == c.params.n) { + goto ok; + } else if (!c.variadic && args.length == c.params.n && !bodyarg) { goto ok; - } else if (c.variadic && args.length >= c.params.n - 1) { + } else if (c.variadic && args.length >= c.params.n - 1 && !bodyarg) { int n = args.length - (c.params.n - 1); if (n == 0) { vec_push(&args, (struct toktree){0}); @@ -1939,8 +1971,14 @@ parsemacrocase(struct parser *P) { lexexpect(P, ')'); break; } else { + if (lexmatch(P, &tok, '&')) + c.bodyarg = 1; vec_push(¶ms, lexexpects(P, TKident, "parameter name").str); - if (!lexmatch(P, &tok, ',')) { + if (c.bodyarg) { + lexmatch(P, &tok, ','); + lexexpect(P, ')'); + break; + } else if (!lexmatch(P, &tok, ',')) { lexexpect(P, ')'); break; } |