Skip to content

Commit 227a522

Browse files
committed
Fix expansion order of nested macros
1 parent 58cef8e commit 227a522

2 files changed

Lines changed: 19 additions & 11 deletions

File tree

rezparser/preprocessor.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ def print_func(arg):
7575
pass
7676
self.print_func = print_func
7777

78-
# Sequence of tokens that were produced by a macro expansion and not yet consumed.
78+
# Sequence ("reverse stack") of tokens that were produced by a macro expansion and not yet consumed.
7979
# Can also contain the string "expansion_end" to mark the end of a macro expansion, these markers are only used internally to track macro expansion depth and are otherwise ignored.
80-
self.expansion_queue = []
80+
self.expansion_stack = []
8181

82-
# Current macro expansion depth. Is increased when a macro is expanded, and decreased when the corresponding "expansion_end" marker is hit. If this number grows too high, the preprocessor errors out.
83-
self.expansion_depth = 0
82+
# Sequence (stack) of the names of all macros that are currently being expanded. Names are pushed when they are expanded, and popped whenever an "expansion_end" marker is hit. If this stack grows too large, the preprocessor errors out.
83+
self.macro_stack = []
8484

8585
# Sequence (stack) of strings representing the state of all conditional blocks enclosing the current block. Valid values are:
8686
# * "waiting": An inactive block in a chain where no active block has been found yet.
@@ -131,7 +131,7 @@ def _eval_expression(self, tokens):
131131
def _token_internal(self, *, expand=True):
132132
while True:
133133
try:
134-
tok = self.expansion_queue.pop(0)
134+
tok = self.expansion_stack.pop(0)
135135
except IndexError:
136136
tok = self.lexers[-1].token()
137137

@@ -141,16 +141,15 @@ def _token_internal(self, *, expand=True):
141141
else:
142142
return tok
143143
elif tok == "expansion_end":
144-
self.expansion_depth -= 1
144+
self.macro_stack.pop()
145145
continue
146146
elif tok.type == "IDENTIFIER" and self.if_state == "active" and expand:
147147
name = tok.value.casefold()
148148
try:
149-
self.expansion_depth += 1
150-
if self.expansion_depth > 100:
151-
raise PreprocessError("Maximum macro expansion depth exceeded (> 100)")
152-
self.expansion_queue += self.macros[name]
153-
self.expansion_queue.append("expansion_end")
149+
if len(self.macro_stack) > 100:
150+
raise PreprocessError(f"Maximum macro expansion depth exceeded (> 100), macro stack: {self.macro_stack}")
151+
self.expansion_stack[0:0] = self.macros[name] + ["expansion_end"]
152+
self.macro_stack.append(name)
154153
except KeyError:
155154
return tok
156155
else:

test/DGTest.r

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ enum {
6565
#printf("8 >> 2 = %d, 8 >> -2 = %d\r", 8 >> 2, 8 >> -2)
6666
#printf("Date: %s; Time: %s; Version: %s\r", $$Date, $$Time, $$Version)
6767

68+
#define abc "abc"
69+
#define def "def"
70+
#define abcdef abc def
71+
#define ghi "ghi"
72+
#define abcdefghi abcdef ghi
73+
#define xyz "xyz"
74+
#define xyzabcdefghi xyz abcdefghi
75+
#printf("%s\r", xyzabcdefghi)
76+
6877
type '_FOO' {
6978
start: integer = start;
7079
integer = end;

0 commit comments

Comments
 (0)