Skip to content

Commit 1bc940c

Browse files
committed
@insert func"" and @insert func{} work.
1 parent 0177856 commit 1bc940c

File tree

4 files changed

+208
-88
lines changed

4 files changed

+208
-88
lines changed

preprocess.lua

Lines changed: 176 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,9 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
16041604
table.insert(tokens, newTokenAt({type="number", value=ppKeywordTok.line, representation=F("%d",ppKeywordTok.line)}, ppKeywordTok))
16051605

16061606
-- @insert "name"
1607-
-- @insert identifier( argument1, ... )
1607+
-- @insert identifier ( argument1, ... )
1608+
-- @insert identifier " ... "
1609+
-- @insert identifier { ... }
16081610
elseif ppKeywordTok.value == "insert" then
16091611
local tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack-1, nil, -1)
16101612
if not (isTokenAndNotNil(tokNext, "string") or isTokenAndNotNil(tokNext, "identifier")) then
@@ -1671,114 +1673,203 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
16711673
stats.lineCount = stats.lineCount + (lastTok and lastTok.line + countString(lastTok.representation, "\n", true) or 0)
16721674
stats.lineCountCode = stats.lineCountCode + getLineCountWithCode(toInsertTokens)
16731675

1674-
-- @insert identifier( argument1, ... )
1676+
-- @insert identifier ( argument1, ... )
1677+
-- @insert identifier " ... "
1678+
-- @insert identifier { ... }
16751679
elseif tokNext.type == "identifier" then
16761680
local identTok = tokNext
1677-
16781681
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
1679-
if not isTokenAndNotNil(tokNext, "punctuation", "(") then
1680-
errorAtToken(fileBuffers, identTok, identTok.position+#identTok.representation, "Macro", "Syntax error: Expected '(' after name.")
1681-
elseif isLastToken(tokenStack, "whitespace") and tokenStack[#tokenStack].value:find"\n" then -- Apply the same 'ambiguous syntax' rule as Lua.
1682-
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Ambiguous syntax near '(' - part of macro, or new statement?")
1683-
end
16841682

1685-
local parensStartTok = tokNext
1686-
popTokens(tokenStack, iNext) -- "("
1683+
-- @insert identifier " ... "
1684+
if isTokenAndNotNil(tokNext, "string") then
1685+
local stringTok = tokNext
1686+
popTokens(tokenStack, iNext)
1687+
1688+
-- Add "!!(ident".
1689+
table.insert(tokens, newTokenAt({type="pp_entry", value="!!", representation="!!", double=true}, ppKeywordTok))
1690+
table.insert(tokens, newTokenAt({type="punctuation", value="(", representation="(" }, ppKeywordTok))
1691+
table.insert(tokens, identTok)
1692+
1693+
stringTok.value = stringTok.representation
1694+
stringTok.representation = F("%q", stringTok.value):gsub("\n", "n")
1695+
table.insert(tokens, stringTok)
1696+
1697+
-- Add ")".
1698+
table.insert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, ppKeywordTok))
1699+
1700+
-- @insert identifier { ... }
1701+
elseif isTokenAndNotNil(tokNext, "punctuation", "{") then
1702+
popTokens(tokenStack, iNext) -- "{"
1703+
1704+
-- Add "!!(ident".
1705+
table.insert(tokens, newTokenAt({type="pp_entry", value="!!", representation="!!", double=true}, ppKeywordTok))
1706+
table.insert(tokens, newTokenAt({type="punctuation", value="(", representation="(" }, ppKeywordTok))
1707+
table.insert(tokens, identTok)
1708+
1709+
-- Collect tokens for the table arg.
1710+
local tableStartTok = tokNext
1711+
local argTokens = {tableStartTok}
1712+
local bracketDepth = 1
1713+
1714+
while true do
1715+
if not tokenStack[1] then
1716+
errorAtToken(fileBuffers, tableStartTok, nil, "Macro", "Syntax error: Could not find end of table constructor before EOF.")
1717+
1718+
-- @Copypaste from above. @Cleanup
1719+
elseif isLastToken(tokenStack, "pp_keyword", "file") then
1720+
local ppKwTokInner = table.remove(tokenStack) -- "@file"
1721+
table.insert(argTokens, newTokenAt({type="string", value=ppKwTokInner.file, representation=F("%q",ppKwTokInner.file)}, ppKwTokInner))
1722+
elseif isLastToken(tokenStack, "pp_keyword", "line") then
1723+
local ppKwTokInner = table.remove(tokenStack) -- "@line"
1724+
table.insert(argTokens, newTokenAt({type="number", value=ppKwTokInner.line, representation=F("%d",ppKwTokInner.line)}, ppKwTokInner))
1725+
1726+
elseif tokenStack[#tokenStack].type:find"^pp_" then
1727+
errorAtToken(fileBuffers, tokenStack[#tokenStack], nil, "Macro", "Preprocessor code not supported in macros.")
1728+
1729+
elseif bracketDepth == 1 and isLastToken(tokenStack, "punctuation", "}") then
1730+
table.insert(argTokens, table.remove(tokenStack))
1731+
break
16871732

1688-
-- Add "!!(ident(".
1689-
table.insert(tokens, newTokenAt({type="pp_entry", value="!!", representation="!!", double=true}, ppKeywordTok))
1690-
table.insert(tokens, newTokenAt({type="punctuation", value="(", representation="(" }, ppKeywordTok))
1691-
table.insert(tokens, identTok)
1692-
table.insert(tokens, parensStartTok)
1733+
else
1734+
if isLastToken(tokenStack, "punctuation", "{") then
1735+
bracketDepth = bracketDepth + 1
1736+
elseif isLastToken(tokenStack, "punctuation", "}") then
1737+
bracketDepth = bracketDepth - 1
1738+
end
1739+
table.insert(argTokens, table.remove(tokenStack))
1740+
end
1741+
end
16931742

1694-
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
1695-
if isTokenAndNotNil(tokNext, "punctuation", ")") then
1696-
popUseless(tokenStack)
1743+
local parts = {}
1744+
for i, argTok in ipairs(argTokens) do
1745+
parts[i] = argTok.representation
1746+
end
1747+
local argStr = table.concat(parts)
16971748

1698-
else
1699-
local lastArgSeparatorTok = nil
1749+
local chunk, err = loadLuaString("return "..argStr, "@")
1750+
if not chunk then
1751+
errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid table constructor expression.")
1752+
-- err = err:gsub("^:%d+: ", "")
1753+
-- errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid table constructor expression. (%s)", err)
1754+
end
17001755

1701-
for argNum = 1, 1/0 do
1702-
local argStartTok = tokenStack[#tokenStack]
1703-
local argTokens = {}
1704-
local parensDepth = 0
1705-
popUseless(tokenStack)
1756+
-- Add argument value.
1757+
table.insert(tokens, newTokenAt({
1758+
type = "string",
1759+
value = argStr,
1760+
representation = F("%q", argStr):gsub("\n", "n"),
1761+
long = false,
1762+
}, tableStartTok))
17061763

1707-
-- Collect tokens for this arg.
1708-
while true do
1709-
if not tokenStack[1] then
1710-
errorAtToken(fileBuffers, parensStartTok, nil, "Macro", "Syntax error: Could not find end of argument list before EOF.")
1764+
-- Add ")".
1765+
table.insert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, ppKeywordTok))
17111766

1712-
-- @Copypaste from above. @Cleanup
1713-
elseif isLastToken(tokenStack, "pp_keyword", "file") then
1714-
local ppKwTokInner = table.remove(tokenStack) -- "@file"
1715-
table.insert(argTokens, newTokenAt({type="string", value=ppKwTokInner.file, representation=F("%q",ppKwTokInner.file)}, ppKwTokInner))
1716-
elseif isLastToken(tokenStack, "pp_keyword", "line") then
1717-
local ppKwTokInner = table.remove(tokenStack) -- "@line"
1718-
table.insert(argTokens, newTokenAt({type="number", value=ppKwTokInner.line, representation=F("%d",ppKwTokInner.line)}, ppKwTokInner))
1767+
-- @insert identifier ( argument1, ... )
1768+
else
1769+
if not isTokenAndNotNil(tokNext, "punctuation", "(") then
1770+
errorAtToken(fileBuffers, identTok, identTok.position+#identTok.representation, "Macro", "Syntax error: Expected '(' after name.")
1771+
elseif isLastToken(tokenStack, "whitespace") and tokenStack[#tokenStack].value:find"\n" then -- Apply the same 'ambiguous syntax' rule as Lua.
1772+
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Ambiguous syntax near '(' - part of macro, or new statement?")
1773+
end
17191774

1720-
elseif tokenStack[#tokenStack].type:find"^pp_" then
1721-
errorAtToken(fileBuffers, tokenStack[#tokenStack], nil, "Macro", "Preprocessor code not supported in macros.")
1775+
local parensStartTok = tokNext
1776+
popTokens(tokenStack, iNext) -- "("
17221777

1723-
elseif parensDepth == 0 and isLastToken(tokenStack, "punctuation", ",") then
1724-
break
1778+
-- Add "!!(ident(".
1779+
table.insert(tokens, newTokenAt({type="pp_entry", value="!!", representation="!!", double=true}, ppKeywordTok))
1780+
table.insert(tokens, newTokenAt({type="punctuation", value="(", representation="(" }, ppKeywordTok))
1781+
table.insert(tokens, identTok)
1782+
table.insert(tokens, parensStartTok)
17251783

1726-
elseif parensDepth == 0 and isLastToken(tokenStack, "punctuation", ")") then
1727-
break
1784+
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
1785+
if isTokenAndNotNil(tokNext, "punctuation", ")") then
1786+
popUseless(tokenStack)
17281787

1729-
else
1730-
if isLastToken(tokenStack, "punctuation", "(") then
1731-
parensDepth = parensDepth + 1
1732-
elseif isLastToken(tokenStack, "punctuation", ")") then
1733-
parensDepth = parensDepth - 1
1788+
else
1789+
local lastArgSeparatorTok = nil
1790+
1791+
for argNum = 1, 1/0 do
1792+
local argStartTok = tokenStack[#tokenStack]
1793+
local argTokens = {}
1794+
local parensDepth = 0
1795+
popUseless(tokenStack)
1796+
1797+
-- Collect tokens for this arg.
1798+
while true do
1799+
if not tokenStack[1] then
1800+
errorAtToken(fileBuffers, parensStartTok, nil, "Macro", "Syntax error: Could not find end of argument list before EOF.")
1801+
1802+
-- @Copypaste from above. @Cleanup
1803+
elseif isLastToken(tokenStack, "pp_keyword", "file") then
1804+
local ppKwTokInner = table.remove(tokenStack) -- "@file"
1805+
table.insert(argTokens, newTokenAt({type="string", value=ppKwTokInner.file, representation=F("%q",ppKwTokInner.file)}, ppKwTokInner))
1806+
elseif isLastToken(tokenStack, "pp_keyword", "line") then
1807+
local ppKwTokInner = table.remove(tokenStack) -- "@line"
1808+
table.insert(argTokens, newTokenAt({type="number", value=ppKwTokInner.line, representation=F("%d",ppKwTokInner.line)}, ppKwTokInner))
1809+
1810+
elseif tokenStack[#tokenStack].type:find"^pp_" then
1811+
errorAtToken(fileBuffers, tokenStack[#tokenStack], nil, "Macro", "Preprocessor code not supported in macros.")
1812+
1813+
elseif parensDepth == 0 and isLastToken(tokenStack, "punctuation", ",") then
1814+
break
1815+
1816+
elseif parensDepth == 0 and isLastToken(tokenStack, "punctuation", ")") then
1817+
break
1818+
1819+
else
1820+
if isLastToken(tokenStack, "punctuation", "(") then
1821+
parensDepth = parensDepth + 1
1822+
elseif isLastToken(tokenStack, "punctuation", ")") then
1823+
parensDepth = parensDepth - 1
1824+
end
1825+
table.insert(argTokens, table.remove(tokenStack))
17341826
end
1735-
table.insert(argTokens, table.remove(tokenStack))
17361827
end
1737-
end
17381828

1739-
popUseless(argTokens)
1740-
if not argTokens[1] then
1741-
errorAtToken(fileBuffers, argStartTok, nil, "Macro", "Syntax error: Expected argument #%d.", argNum)
1742-
end
1829+
popUseless(argTokens)
1830+
if not argTokens[1] then
1831+
errorAtToken(fileBuffers, argStartTok, nil, "Macro", "Syntax error: Expected argument #%d.", argNum)
1832+
end
17431833

1744-
local parts = {}
1745-
for i, argTok in ipairs(argTokens) do
1746-
parts[i] = argTok.representation
1747-
end
1748-
local argStr = table.concat(parts)
1834+
local parts = {}
1835+
for i, argTok in ipairs(argTokens) do
1836+
parts[i] = argTok.representation
1837+
end
1838+
local argStr = table.concat(parts)
17491839

1750-
local chunk, err = loadLuaString("return "..argStr, "@")
1751-
if not chunk then
1752-
errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid expression for argument #%d.", argNum)
1753-
-- err = err:gsub("^:%d+: ", "")
1754-
-- errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid expression for argument #%d. (%s)", argNum, err)
1755-
end
1840+
local chunk, err = loadLuaString("return "..argStr, "@")
1841+
if not chunk then
1842+
errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid expression for argument #%d.", argNum)
1843+
-- err = err:gsub("^:%d+: ", "")
1844+
-- errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid expression for argument #%d. (%s)", argNum, err)
1845+
end
17561846

1757-
-- Add argument separator.
1758-
if lastArgSeparatorTok then
1759-
table.insert(tokens, lastArgSeparatorTok)
1760-
end
1847+
-- Add argument separator.
1848+
if lastArgSeparatorTok then
1849+
table.insert(tokens, lastArgSeparatorTok)
1850+
end
17611851

1762-
-- Add argument value.
1763-
table.insert(tokens, newTokenAt({
1764-
type = "string",
1765-
value = argStr,
1766-
representation = F("%q", argStr):gsub("\n", "n"),
1767-
long = false,
1768-
}, argStartTok))
1852+
-- Add argument value.
1853+
table.insert(tokens, newTokenAt({
1854+
type = "string",
1855+
value = argStr,
1856+
representation = F("%q", argStr):gsub("\n", "n"),
1857+
long = false,
1858+
}, argStartTok))
17691859

1770-
if isLastToken(tokenStack, "punctuation", ")") then
1771-
break
1772-
end
1860+
if isLastToken(tokenStack, "punctuation", ")") then
1861+
break
1862+
end
17731863

1774-
lastArgSeparatorTok = table.remove(tokenStack) -- ","
1775-
assert(isToken(lastArgSeparatorTok, "punctuation", ","))
1776-
end--for argNum
1777-
end
1864+
lastArgSeparatorTok = table.remove(tokenStack) -- ","
1865+
assert(isToken(lastArgSeparatorTok, "punctuation", ","))
1866+
end--for argNum
1867+
end
17781868

1779-
-- Add "))".
1780-
table.insert(tokens, table.remove(tokenStack)) -- ")"
1781-
table.insert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, ppKeywordTok))
1869+
-- Add "))".
1870+
table.insert(tokens, table.remove(tokenStack)) -- ")"
1871+
table.insert(tokens, newTokenAt({type="punctuation", value=")", representation=")"}, ppKeywordTok))
1872+
end
17821873

17831874
else
17841875
assert(false)

tests/quickTest.lua2p

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ local ok = 1==1
106106
-- @insert ASSERT ( , ok ) -- Syntax error!
107107
-- @insert ASSERT ( --[[]] , ok ) -- Syntax error!
108108

109+
!local function PASS_THROUGH(lua) return lua end
110+
local s = @insert PASS_THROUGH "foo"
111+
local t = @insert PASS_THROUGH { 496, b=true }
112+
109113

110114

111115
-- Misc.

tests/quickTest.output.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,13 @@ print("Blargh!")
6161

6262
print(string.format('We are at %s:%d!', "misc/quickTest.lua2p", 87))
6363

64-
65-
6664
local ok = 1==1
6765

6866
if not (ok) then error("Oh "..tonumber("7",10).." noes!") end
6967

68+
local s = "foo"
69+
local t = { 496, b=true }
70+
7071

7172

7273
print("dataFromCommandLine: Hello, world!")

tests/runTests.lua

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,31 @@ doTest("Preprocessor keywords", function()
214214
})
215215
assertCodeOutput(luaOut, [[v = "bar"]])
216216

217-
-- @Incomplete: Test macros: @insert foo()
217+
local luaOut = assert(pp.processString{ code=[[
218+
!function join(ident1, ident2) return ident1..ident2 end
219+
v = @insert join(foo, bar)
220+
]]})
221+
assertCodeOutput(luaOut, [[v = foobar]])
222+
223+
local luaOut = assert(pp.processString{ code=[[
224+
!function echo(v) return v end
225+
s = @insert echo""
226+
]]})
227+
assertCodeOutput(luaOut, [[s = ""]])
228+
229+
local luaOut = assert(pp.processString{ code=[[
230+
!function echo(v) return v end
231+
t = @insert echo{}
232+
]]})
233+
assertCodeOutput(luaOut, [[t = {}]])
234+
235+
-- Invalid: Ambiguous syntax.
236+
local luaOut = pp.processString{ code=[[
237+
!function void() return "" end
238+
v = @insert void
239+
()
240+
]]}
241+
assert(not luaOut)
218242
end)
219243

220244

0 commit comments

Comments
 (0)