Skip to content

Commit 607a19b

Browse files
committed
Implement macro parameter substitution in statement contexts
This enables function-like macros with statement bodies that reference macro parameters. Examples now supported: - ASSIGN_MACRO(variable, val) → variable = variable + val + 10 - COMPOUND_ASSIGN(variable, val) → variable += val + 10 - SET_VAR(var, value) → var = value Implementation uses find_macro_param_src_idx() with careful lexer state management to safely substitute parameter values in statement parsing contexts, matching existing expression context functionality. Close #142
1 parent e04a60d commit 607a19b

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/parser.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,6 +2671,36 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
26712671
if (!lex_peek(T_identifier, token))
26722672
error("Unexpected token");
26732673

2674+
/* handle macro parameter substitution for statements */
2675+
int macro_param_idx = find_macro_param_src_idx(token, parent);
2676+
if (macro_param_idx && parent->macro) {
2677+
/* save current state */
2678+
int saved_size = SOURCE->size;
2679+
char saved_char = next_char;
2680+
int saved_token = next_token;
2681+
2682+
/* jump to parameter value */
2683+
SOURCE->size = macro_param_idx;
2684+
next_char = SOURCE->elements[SOURCE->size];
2685+
next_token = lex_token();
2686+
2687+
/* extract the parameter value as identifier token */
2688+
if (lex_peek(T_identifier, token)) {
2689+
lex_expect(T_identifier);
2690+
} else {
2691+
/* parameter is not a simple identifier, restore state and continue
2692+
*/
2693+
SOURCE->size = saved_size;
2694+
next_char = saved_char;
2695+
next_token = saved_token;
2696+
}
2697+
2698+
/* restore source position */
2699+
SOURCE->size = saved_size;
2700+
next_char = saved_char;
2701+
next_token = saved_token;
2702+
}
2703+
26742704
/* is it a variable declaration? */
26752705
int find_type_flag = lex_accept(T_struct) ? 2 : 1;
26762706
type = find_type(token, find_type_flag);

tests/driver.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,49 @@ int main()
928928
}
929929
EOF
930930

931+
# macro parameter substitution works in expression contexts
932+
try_ 15 << EOF
933+
#define ADD_PARAMS(a, b) ((a) + (b))
934+
int main()
935+
{
936+
int x = 5, y = 10;
937+
return ADD_PARAMS(x, y);
938+
}
939+
EOF
940+
941+
# macro with assignment operators
942+
try_ 18 << EOF
943+
#define ASSIGN_MACRO(variable, val) \
944+
variable = variable + val + 10
945+
int main()
946+
{
947+
int x = 5;
948+
ASSIGN_MACRO(x, 3);
949+
return x;
950+
}
951+
EOF
952+
953+
try_ 27 << EOF
954+
#define COMPOUND_ASSIGN(variable, val) \
955+
variable += val + 10
956+
int main()
957+
{
958+
int y = 10;
959+
COMPOUND_ASSIGN(y, 7);
960+
return y;
961+
}
962+
EOF
963+
964+
try_ 42 << EOF
965+
#define SET_VAR(var, value) var = value
966+
int main()
967+
{
968+
int z = 0;
969+
SET_VAR(z, 42);
970+
return z;
971+
}
972+
EOF
973+
931974
try_output 0 "Wrapper: Hello World!" << EOF
932975
#define WRAPPER(...) \
933976
do { \

0 commit comments

Comments
 (0)