Skip to content

Commit 12f6a62

Browse files
06wjAndrewRayCode
authored andcommitted
Fix bug for macro expansion in binary expression evaluation
1 parent db5a474 commit 12f6a62

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

src/preprocessor/preprocessor.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,37 @@ true
163163
`);
164164
});
165165

166+
test('evaluates binary expression with simple macro', () => {
167+
const program = `
168+
#define A 1
169+
#if A + 1 == 2
170+
true
171+
#endif
172+
`;
173+
174+
const ast = parse(program);
175+
preprocessAst(ast);
176+
expect(generate(ast)).toBe(`
177+
true
178+
`);
179+
});
180+
181+
test('evaluates binary expression with nested macro', () => {
182+
const program = `
183+
#define A 1
184+
#define B A + 1
185+
#if B == 2
186+
true
187+
#endif
188+
`;
189+
190+
const ast = parse(program);
191+
preprocessAst(ast);
192+
expect(generate(ast)).toBe(`
193+
true
194+
`);
195+
});
196+
166197
test('define inside if/else is properly expanded when the if branch is chosen', () => {
167198
const program = `
168199
#define MACRO

src/preprocessor/preprocessor.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,25 @@ const evaluteExpression = (node: PreprocessorAstNode, macros: Macros) =>
337337
// TODO: Handle non-base-10 numbers. Should these be parsed in the peg grammar?
338338
int_constant: (node) => parseInt(node.token, 10),
339339
unary_defined: (node) => node.identifier.identifier in macros,
340-
identifier: (node) => node.identifier,
340+
identifier: (node) => {
341+
// If the identifier is a pure number (e.g. "123"), parse it as an integer.
342+
if (/^\d+$/.test(node.identifier)) {
343+
return parseInt(node.identifier, 10);
344+
}
345+
346+
// If the identifier contains no letters (e.g. "1+2", "(1+2)*3"), try to evaluate it as a JS expression.
347+
if (!/[a-zA-Z]/.test(node.identifier)) {
348+
try {
349+
return eval(node.identifier);
350+
} catch (e) {
351+
// If evaluation fails, fall through to error below.
352+
}
353+
}
354+
// If it's not a number or evaluatable expression, throw an error (likely an unknown macro or invalid expression).
355+
throw new Error(
356+
`Preprocessing error: Unknown identifier or unsupported expression "${node.identifier}"`
357+
);
358+
},
341359
group: (node, visit) => visit(node.expression),
342360
binary: ({ left, right, operator: { literal } }, visit) => {
343361
switch (literal) {

0 commit comments

Comments
 (0)