Skip to content

Commit 1b270b1

Browse files
committed
add __VA_ARGS__ and __VA_OPT__
1 parent fe42da3 commit 1b270b1

File tree

1 file changed

+130
-60
lines changed

1 file changed

+130
-60
lines changed

nattlua/c_declarations/preprocessor.lua

Lines changed: 130 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -203,60 +203,6 @@ do
203203
return args
204204
end
205205

206-
function META:CaptureArgsOld()
207-
self:ExpectTokenValue("(")
208-
local args = {}
209-
210-
for _ = self:GetPosition(), self:GetLength() do
211-
if self:IsTokenValue(")") then break end
212-
213-
local tokens = {}
214-
215-
for _ = self:GetPosition(), self:GetLength() do
216-
if self:IsTokenValue(",") then break end
217-
218-
if self:IsTokenValue(")") then break end
219-
220-
local tk = self:ConsumeToken()
221-
local def = self:GetDefinition(tk.value)
222-
223-
if def then
224-
if def.args then
225-
local start = self:GetPosition()
226-
self:ExpectTokenType("letter") -- consume the identifier
227-
local args = self:CaptureArgs() -- capture all tokens separated by commas
228-
local stop = self:GetPosition()
229-
230-
for i = stop - 1, start, -1 do
231-
self:RemoveToken(i)
232-
end
233-
234-
self.current_token_index = start
235-
self:AddTokens(def.tokens)
236-
237-
for i, tokens in ipairs(args) do
238-
table.insert(tokens, 1, def.args[i].value)
239-
end
240-
else
241-
for i, v in ipairs(def.tokens) do
242-
table.insert(tokens, v)
243-
end
244-
end
245-
else
246-
table.insert(tokens, tk)
247-
end
248-
end
249-
250-
table.insert(args, tokens)
251-
252-
if self:IsTokenValue(",") then self:ExpectTokenValue(",") end
253-
end
254-
255-
table.print(args, 2)
256-
self:ExpectTokenValue(")")
257-
return args
258-
end
259-
260206
function META:PrintState()
261207
print("\n" .. tostring_tokens(self.tokens, self:GetPosition()))
262208
end
@@ -318,17 +264,136 @@ do
318264
end
319265

320266
self.current_token_index = start
321-
self:AddTokens(def.tokens)
322-
assert(#args == #def.args, "Argument count mismatch")
323267

324-
for i, tokens in ipairs(args) do
325-
self:PushDefine(def.args[i].value, nil, tokens)
268+
if tk.value == "__VA_OPT__" then
269+
local va = self:GetDefinition("__VA_ARGS__")
270+
271+
if not va or #va.tokens == 0 or va.tokens[1].value == "" then
272+
273+
else
274+
self:AddTokens(def.tokens)
275+
end
276+
else
277+
self:AddTokens(def.tokens)
278+
end
279+
280+
local has_var_arg = def.args[1] and def.args[#def.args].value == "..."
281+
282+
if has_var_arg then
283+
if #args < #def.args - 1 then error("Argument count mismatch") end
284+
else
285+
assert(#args == #def.args, "Argument count mismatch")
286+
end
287+
288+
if #args == 0 then
289+
if def.args[#def.args].value == "..." then
290+
self:PushDefine(
291+
"__VA_ARGS__",
292+
nil,
293+
{
294+
{
295+
value = "",
296+
type = "symbol",
297+
whitespace = {
298+
{value = " ", type = "space"},
299+
},
300+
},
301+
}
302+
)
303+
self:PushDefine(
304+
"__VA_OPT__",
305+
{
306+
{
307+
value = "arg",
308+
type = "letter",
309+
whitespace = {
310+
{value = " ", type = "space"},
311+
},
312+
},
313+
},
314+
{
315+
{
316+
value = ",",
317+
type = "symbol",
318+
whitespace = {
319+
{value = " ", type = "space"},
320+
},
321+
},
322+
}
323+
)
324+
end
325+
else
326+
for i, tokens in ipairs(args) do
327+
if def.args[i].value == "..." then
328+
local remaining = {}
329+
330+
for j = i, #args do
331+
for _, token in ipairs(args[j]) do
332+
if j ~= i then
333+
table.insert(
334+
remaining,
335+
{
336+
value = ",",
337+
type = "symbol",
338+
whitespace = {
339+
{value = " ", type = "space"},
340+
},
341+
}
342+
)
343+
end
344+
345+
table.insert(remaining, token)
346+
end
347+
end
348+
349+
self:PushDefine("__VA_ARGS__", nil, remaining)
350+
self:PushDefine(
351+
"__VA_OPT__",
352+
{
353+
{
354+
value = "arg",
355+
type = "letter",
356+
whitespace = {
357+
{value = " ", type = "space"},
358+
},
359+
},
360+
},
361+
{
362+
{
363+
value = ",",
364+
type = "symbol",
365+
whitespace = {
366+
{value = " ", type = "space"},
367+
},
368+
},
369+
}
370+
)
371+
372+
break
373+
else
374+
self:PushDefine(def.args[i].value, nil, tokens)
375+
end
376+
end
326377
end
327378

328379
self:Parse()
329380

330-
for i, tokens in ipairs(args) do
331-
self:PushUndefine(def.args[i].value)
381+
if #args == 0 then
382+
if def.args[#def.args].value == "..." then
383+
self:PushUndefine("__VA_ARGS__")
384+
self:PushUndefine("__VA_OPT__")
385+
end
386+
else
387+
for i, tokens in ipairs(args) do
388+
if def.args[i].value == "..." then
389+
self:PushUndefine("__VA_ARGS__")
390+
self:PushUndefine("__VA_OPT__")
391+
392+
break
393+
else
394+
self:PushUndefine(def.args[i].value)
395+
end
396+
end
332397
end
333398
else
334399
self:RemoveToken(self:GetPosition()) -- remove the token we replace
@@ -413,6 +478,8 @@ local function assert_find(code, find)
413478
error("Could not find " .. find .. " in " .. code)
414479
end
415480

481+
assert_find("#define F(...) >__VA_ARGS__<\nF(0)", "> 0 <")
482+
assert_find("#define F(...) >__VA_ARGS__<\nF()", "> <")
416483
assert_find([[
417484
#define X(x) x
418485
#define Y X(1)
@@ -530,3 +597,6 @@ assert_find(
530597
)
531598
assert_find("#define STRINGIFY(a) #a \nSTRINGIFY(1);", "\"1\"")
532599
assert_find("#define STRINGIFY(a) #a \nSTRINGIFY((a,b,c));", "\"(a,b,c)\"")
600+
assert_find("#define F(...) >__VA_ARGS__<\nF(1,2,3)", "> 1 , 2 , 3 <")
601+
assert_find("#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)\nF(1)", "f ( 0 , 1 )")
602+
assert_find("#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)\nF()", "f ( 0 )")

0 commit comments

Comments
 (0)