Skip to content

Commit 00409ac

Browse files
committed
!() and !!() work in table macros.
1 parent be7cf95 commit 00409ac

File tree

2 files changed

+124
-89
lines changed

2 files changed

+124
-89
lines changed

preprocess.lua

Lines changed: 94 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,50 @@ local function insertTokensAsStringLiteral(tokens, tokensToConcat, locationTok)
19871987
return lua
19881988
end
19891989

1990+
local function processPreprocessorBlockInMacro(tokens, fileBuffers, tokenStack, argNonPpTokens, locationTok, isFirstPart)
1991+
local ppEntryTok = tableRemove(tokenStack) -- '!' or '!!'
1992+
assert(isToken(ppEntryTok, "pp_entry"))
1993+
1994+
if not isFirstPart then
1995+
tableInsert(tokens, newTokenAt({type="punctuation", value="..", representation=".."}, locationTok))
1996+
end
1997+
if argNonPpTokens[1] then
1998+
insertTokensAsStringLiteral(tokens, argNonPpTokens, locationTok)
1999+
tableInsert(tokens, newTokenAt({type="punctuation", value="..", representation=".."}, ppEntryTok))
2000+
end
2001+
2002+
local ident = (ppEntryTok.value == "!") and "__TOLUA" or "__ASSERTLUA"
2003+
tableInsert(tokens, newTokenAt({type="identifier", value=ident, representation=ident}, ppEntryTok))
2004+
tableInsert(tokens, tableRemove(tokenStack)) -- '('
2005+
local exprStartTokIndex = #tokens
2006+
2007+
local parensDepth = 1
2008+
2009+
while true do
2010+
local tok = tableRemove(tokenStack) -- anything
2011+
if not tok then
2012+
errorAtToken(fileBuffers, ppEntryTok, nil, "Parser", "Missing end of preprocessor block.")
2013+
end
2014+
tableInsert(tokens, tok)
2015+
2016+
if isToken(tok, "punctuation", "(") then
2017+
parensDepth = parensDepth + 1
2018+
elseif isToken(tok, "punctuation", ")") then
2019+
parensDepth = parensDepth - 1
2020+
if parensDepth == 0 then break end
2021+
elseif tok.type:find"^pp_" then
2022+
errorAtToken(fileBuffers, tok, nil, "Parser", "Preprocessor token inside metaprogram (starting %s).", getRelativeLocationText(ppEntryTok, tok))
2023+
end
2024+
end
2025+
2026+
local chunk, err = loadLuaString("return ".._concatTokens(tokens, nil, false, exprStartTokIndex, nil), "@")
2027+
if not chunk then
2028+
errorAtToken(fileBuffers, tokens[exprStartTokIndex+1], nil, "Macro", "Syntax error: Invalid expression in preprocessor block.")
2029+
-- err = err:gsub("^:%d+: ", "")
2030+
-- errorAtToken(fileBuffers, tokens[exprStartTokIndex+1], nil, "Macro", "Syntax error: Invalid expression in preprocessor block. (%s)", err)
2031+
end
2032+
end
2033+
19902034
local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats)
19912035
--
19922036
-- Expand expressions:
@@ -2053,59 +2097,75 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20532097
-- (Similar code as `@insert identifier()` below.)
20542098
--
20552099

2056-
-- Add '!!(ident'.
2100+
-- Add '!!(ident('.
20572101
tableInsert(tokens, newTokenAt({type="pp_entry", value="!!", representation="!!", double=true}, ppKeywordTok))
20582102
tableInsert(tokens, newTokenAt({type="punctuation", value="(", representation="(" }, ppKeywordTok))
20592103
tableInsert(tokens, identTok)
2104+
tableInsert(tokens, newTokenAt({type="punctuation", value="(", representation="(" }, identTok))
20602105

20612106
-- Collect tokens for the table arg.
20622107
-- We're looking for the closing '}'.
2063-
local tableStartTok = tokNext
2064-
local argTokens = {tableStartTok}
2065-
local bracketDepth = 1
2108+
local argNonPpStartTok = tokNext -- Used for location info.
2109+
local argNonPpTokens = {argNonPpStartTok}
2110+
local bracketDepth = 1
2111+
local isFirstPart = true
20662112

20672113
while true do
2068-
tok = tokenStack[#tokenStack]
2114+
local len = #tokenStack
2115+
tok = tokenStack[len]
20692116

20702117
if not tok then
2071-
errorAtToken(fileBuffers, tableStartTok, nil, "Macro", "Syntax error: Could not find end of table constructor before EOF.")
2118+
errorAtToken(fileBuffers, argNonPpStartTok, nil, "Macro", "Syntax error: Could not find end of table constructor before EOF.")
2119+
2120+
-- Preprocessor block in macro.
2121+
elseif tok.type == "pp_entry" and isTokenAndNotNil(tokenStack[len-1], "punctuation", "(") then
2122+
processPreprocessorBlockInMacro(tokens, fileBuffers, tokenStack, argNonPpTokens, argNonPpStartTok, isFirstPart)
20722123

2124+
argNonPpStartTok = tokenStack[#tokenStack] -- Could be nil, but that should be fine I think.
2125+
argNonPpTokens = argNonPpTokens[1] and {} or argNonPpTokens
2126+
isFirstPart = false
2127+
2128+
-- Other preprocessor code in macro.
20732129
elseif tok.type:find"^pp_" then
20742130
errorAtToken(fileBuffers, tok, nil, "Macro", "Unsupported preprocessor code in macro. (Macro starts %s)", getRelativeLocationText(ppKeywordTok, tok))
20752131

2132+
-- End of table and argument.
20762133
elseif bracketDepth == 1 and isToken(tok, "punctuation", "}") then
2077-
tableInsert(argTokens, tableRemove(tokenStack)) -- '}'
2134+
tableInsert(argNonPpTokens, tableRemove(tokenStack)) -- '}'
20782135
break
20792136

2137+
-- Normal token.
20802138
else
20812139
if isToken(tok, "punctuation", "{") then
20822140
bracketDepth = bracketDepth + 1
20832141
elseif isToken(tok, "punctuation", "}") then
20842142
bracketDepth = bracketDepth - 1
20852143
end
2086-
tableInsert(argTokens, tableRemove(tokenStack)) -- anything
2144+
tableInsert(argNonPpTokens, tableRemove(tokenStack)) -- anything
20872145
end
20882146
end
20892147

2090-
local argStr = _concatTokens(argTokens, nil, false, nil, nil)
2148+
-- Add last part of argument value.
2149+
if argNonPpTokens[1] then
2150+
if not isFirstPart then
2151+
tableInsert(tokens, newTokenAt({type="punctuation", value="..", representation=".."}, argNonPpStartTok))
2152+
end
2153+
local argStr = insertTokensAsStringLiteral(tokens, argNonPpTokens, argNonPpStartTok)
2154+
2155+
if isFirstPart then
2156+
local chunk, err = loadLuaString("return ("..argStr..")", "@")
20912157

2092-
local chunk, err = loadLuaString("return "..argStr, "@")
2093-
if not chunk then
2094-
errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid table constructor expression.")
2095-
-- err = err:gsub("^:%d+: ", "")
2096-
-- errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid table constructor expression. (%s)", err)
2158+
if not chunk then
2159+
errorAtToken(fileBuffers, argNonPpStartTok, nil, "Macro", "Syntax error: Invalid table constructor expression.")
2160+
-- err = err:gsub("^:%d+: ", "")
2161+
-- errorAtToken(fileBuffers, argNonPpStartTok, nil, "Macro", "Syntax error: Invalid table constructor expression. (%s)", err)
2162+
end
2163+
end
20972164
end
20982165

2099-
-- Add argument value.
2100-
tableInsert(tokens, newTokenAt({
2101-
type = "string",
2102-
value = argStr,
2103-
representation = F("%q", argStr):gsub("\n", "n"),
2104-
long = false,
2105-
}, tableStartTok))
2106-
2107-
-- Add ')'.
2108-
tableInsert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, ppKeywordTok))
2166+
-- Add '))'.
2167+
tableInsert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, tokens[#tokens]))
2168+
tableInsert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, tokens[#tokens]))
21092169

21102170
-- @insert identifier ( argument1, ... )
21112171
else
@@ -2138,10 +2198,10 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
21382198

21392199
-- Collect tokens for this arg.
21402200
-- We're looking for the next comma at depth 0 or closing ')'.
2141-
local argNonPpStartTok = tokenStack[#tokenStack]
2201+
local argNonPpStartTok = tokenStack[#tokenStack] -- Used for location info.
21422202
local argNonPpTokens = {}
21432203
local depthStack = {}
2144-
local insertedPpEntry = false
2204+
local isFirstPart = true
21452205
popUseless(tokenStack) -- Trim leading useless tokens.
21462206

21472207
while true do
@@ -2153,51 +2213,11 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
21532213

21542214
-- Preprocessor block in macro.
21552215
elseif tok.type == "pp_entry" and isTokenAndNotNil(tokenStack[len-1], "punctuation", "(") then
2156-
local ppEntryTok = tok
2157-
tableRemove(tokenStack) -- '!' or '!!'
2158-
2159-
if insertedPpEntry then
2160-
tableInsert(tokens, newTokenAt({type="punctuation", value="..", representation=".."}, argNonPpStartTok))
2161-
end
2162-
if argNonPpTokens[1] then
2163-
insertTokensAsStringLiteral(tokens, argNonPpTokens, argNonPpStartTok)
2164-
argNonPpTokens = {}
2165-
tableInsert(tokens, newTokenAt({type="punctuation", value="..", representation=".."}, ppEntryTok))
2166-
end
2167-
2168-
local ident = (ppEntryTok.value == "!") and "__TOLUA" or "__ASSERTLUA"
2169-
tableInsert(tokens, newTokenAt({type="identifier", value=ident, representation=ident}, ppEntryTok))
2170-
tableInsert(tokens, tableRemove(tokenStack)) -- '('
2171-
local exprStartTokIndex = #tokens
2216+
processPreprocessorBlockInMacro(tokens, fileBuffers, tokenStack, argNonPpTokens, argNonPpStartTok, isFirstPart)
21722217

2173-
local parensDepth = 1
2174-
2175-
while true do
2176-
tok = tableRemove(tokenStack) -- anything
2177-
if not tok then
2178-
errorAtToken(fileBuffers, ppEntryTok, nil, "Parser", "Missing end of preprocessor block.")
2179-
end
2180-
tableInsert(tokens, tok)
2181-
2182-
if isToken(tok, "punctuation", "(") then
2183-
parensDepth = parensDepth + 1
2184-
elseif isToken(tok, "punctuation", ")") then
2185-
parensDepth = parensDepth - 1
2186-
if parensDepth == 0 then break end
2187-
elseif tok.type:find"^pp_" then
2188-
errorAtToken(fileBuffers, tok, nil, "Parser", "Preprocessor token inside metaprogram (starting %s).", getRelativeLocationText(ppEntryTok, tok))
2189-
end
2190-
end
2191-
2192-
local chunk, err = loadLuaString("return ".._concatTokens(tokens, nil, false, exprStartTokIndex, nil), "@")
2193-
if not chunk then
2194-
errorAtToken(fileBuffers, tokens[exprStartTokIndex+1], nil, "Macro", "Syntax error: Invalid expression in preprocessor block.")
2195-
-- err = err:gsub("^:%d+: ", "")
2196-
-- errorAtToken(fileBuffers, tokens[exprStartTokIndex+1], nil, "Macro", "Syntax error: Invalid expression in preprocessor block. (%s)", err)
2197-
end
2198-
2199-
insertedPpEntry = true
22002218
argNonPpStartTok = tokenStack[#tokenStack] -- Could be nil, but that should be fine I think.
2219+
argNonPpTokens = argNonPpTokens[1] and {} or argNonPpTokens
2220+
isFirstPart = false
22012221

22022222
-- Other preprocessor code in macro.
22032223
elseif tok.type:find"^pp_" then
@@ -2248,12 +2268,12 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
22482268
popUseless(argNonPpTokens) -- Trim trailing useless tokens.
22492269

22502270
if argNonPpTokens[1] then
2251-
if insertedPpEntry then
2271+
if not isFirstPart then
22522272
tableInsert(tokens, newTokenAt({type="punctuation", value="..", representation=".."}, argNonPpStartTok))
22532273
end
22542274
local argStr = insertTokensAsStringLiteral(tokens, argNonPpTokens, argNonPpStartTok)
22552275

2256-
if not insertedPpEntry then
2276+
if isFirstPart then
22572277
local chunk, err = loadLuaString("return ("..argStr..")", "@")
22582278

22592279
if not chunk then
@@ -2263,7 +2283,8 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
22632283
end
22642284
end
22652285

2266-
elseif not insertedPpEntry then
2286+
elseif isFirstPart then
2287+
-- There were no useful tokens for the argument!
22672288
errorAtToken(fileBuffers, argNonPpStartTok, nil, "Macro", "Syntax error: Expected argument #%d.", argNum)
22682289
end
22692290

@@ -2279,7 +2300,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
22792300

22802301
-- Add '))'.
22812302
tableInsert(tokens, tableRemove(tokenStack)) -- ')'
2282-
tableInsert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, ppKeywordTok))
2303+
tableInsert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, tokens[#tokens]))
22832304
end
22842305

22852306
else

tests/quickTest.lua2p

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,36 @@ local f = @@PASS_THROUGH(function(a, b)
130130
end)
131131

132132
local x = @@PASS_THROUGH( @@"tests/quickTest.txt" )
133-
local y = @@PASS_THROUGH( 1 + !!( "3" ) * 8 )
134-
local z = @@PASS_THROUGH( 1 + !( 3 ) * 8 )
135-
136-
local a = @@PASS_THROUGH( !(2) )
137-
local b = @@PASS_THROUGH( !(2) + 3 )
138-
local c = @@PASS_THROUGH( 1 + !(2) )
139-
local d = @@PASS_THROUGH( 1 + !(2) + 3 )
140-
141-
local m = @@PASS_THROUGH( !!("1")!!("+")!!("2") )
142-
143-
-- local no = @@PASS_THROUGH( @@654 ) -- Error!
144-
-- local no = @@PASS_THROUGH( @@aaaaa ) -- Error!
145-
-- local no = @@PASS_THROUGH( !() ) -- Error!
146-
-- local no = @@PASS_THROUGH( !!() ) -- Error!
147-
-- local no = @@PASS_THROUGH( !!( 1 ) ) -- Error!
148-
-- local no = @@PASS_THROUGH( !!( !(3) ) ) -- Error!
133+
134+
local x1 = @@PASS_THROUGH( 1 + !!( "3" ) * 8 )
135+
local x2 = @@PASS_THROUGH{ 1 + !!( "3" ) * 8 }
136+
local y1 = @@PASS_THROUGH( 1 + !( 3 ) * 8 )
137+
local y2 = @@PASS_THROUGH{ 1 + !( 3 ) * 8 }
138+
139+
local a1 = @@PASS_THROUGH( !(2) )
140+
local a2 = @@PASS_THROUGH{ !(2) }
141+
local b1 = @@PASS_THROUGH( !(2) + 3 )
142+
local b2 = @@PASS_THROUGH{ !(2) + 3 }
143+
local c1 = @@PASS_THROUGH( 1 + !(2) )
144+
local c2 = @@PASS_THROUGH{ 1 + !(2) }
145+
local d1 = @@PASS_THROUGH( 1 + !(2) + 3 )
146+
local d2 = @@PASS_THROUGH{ 1 + !(2) + 3 }
147+
148+
local m1 = @@PASS_THROUGH( !!("1")!!("+")!!("2") )
149+
local m2 = @@PASS_THROUGH{ !!("1")!!("+")!!("2") }
150+
151+
-- local no = @@PASS_THROUGH( @@654 ) -- Error: Bad token after @insert.
152+
-- local no = @@PASS_THROUGH{ @@654 } -- Error: Bad token after @insert.
153+
-- local no = @@PASS_THROUGH( @@foo ) -- Error: Bad token after macro name.
154+
-- local no = @@PASS_THROUGH{ @@foo } -- Error: Bad token after macro name.
155+
-- local no = @@PASS_THROUGH( !() ) -- Error: Invalid expression.
156+
-- local no = @@PASS_THROUGH{ !() } -- Error: Invalid expression.
157+
-- local no = @@PASS_THROUGH( !!() ) -- Error: Invalid expression.
158+
-- local no = @@PASS_THROUGH{ !!() } -- Error: Invalid expression.
159+
-- local no = @@PASS_THROUGH( !!( 1 ) ) -- Error: Value is not Lua code.
160+
-- local no = @@PASS_THROUGH{ !!( 1 ) } -- Error: Value is not Lua code.
161+
-- local no = @@PASS_THROUGH( !!( !(3) ) ) -- Error: Nested code block.
162+
-- local no = @@PASS_THROUGH{ !!( !(3) ) } -- Error: Nested code block.
149163

150164

151165

0 commit comments

Comments
 (0)