@@ -748,18 +748,20 @@ end
748748
749749
750750
751- function _concatTokens (tokens , lastLn , addLineNumbers )
751+ -- luaString = _concatTokens( tokens, lastLn=nil, addLineNumbers, fromIndex=1, toIndex=#tokens )
752+ function _concatTokens (tokens , lastLn , addLineNumbers , i1 , i2 )
752753 local parts = {}
753754
754755 if addLineNumbers then
755- for _ , tok in ipairs (tokens ) do
756- lastLn = maybeOutputLineNumber (parts , tok , lastLn )
756+ for i = (i1 or 1 ), (i2 or # tokens ) do
757+ local tok = tokens [i ]
758+ lastLn = maybeOutputLineNumber (parts , tok , lastLn )
757759 tableInsert (parts , tok .representation )
758760 end
759761
760762 else
761- for i , tok in ipairs ( tokens ) do
762- parts [i ] = tok .representation
763+ for i = ( i1 or 1 ), ( i2 or # tokens ) do
764+ tableInsert ( parts , tokens [i ].representation )
763765 end
764766 end
765767
@@ -1726,7 +1728,7 @@ end
17261728-- Concatinate tokens by their representations.
17271729-- luaString = concatTokens( tokens )
17281730function metaFuncs .concatTokens (tokens )
1729- return _concatTokens (tokens )
1731+ return _concatTokens (tokens , nil , false , nil , nil )
17301732end
17311733
17321734-- Extra stuff used by the command line program:
@@ -1736,9 +1738,18 @@ metaFuncs.tryToFormatError = tryToFormatError
17361738
17371739for k , v in pairs (metaFuncs ) do metaEnv [k ] = v end
17381740
1739- metaEnv .__LUA = metaEnv .outputLua
1740- metaEnv .__VAL = metaEnv .outputValue
1741- metaEnv .__TOLUA = function (v ) return (assert (toLua (v ))) end
1741+ metaEnv .__LUA = metaEnv .outputLua
1742+ metaEnv .__VAL = metaEnv .outputValue
1743+
1744+ function metaEnv .__TOLUA (v )
1745+ return (assert (toLua (v )))
1746+ end
1747+ function metaEnv .__ASSERTLUA (lua )
1748+ if type (lua ) ~= " string" then
1749+ error (" Value is not Lua code." , 2 )
1750+ end
1751+ return lua
1752+ end
17421753
17431754
17441755
@@ -1962,6 +1973,20 @@ local function doLateExpansionsResources(tokensToExpand, fileBuffers, params, st
19621973 return tokens
19631974end
19641975
1976+ -- luaString = insertTokensAsStringLiteral( tokens, tokensToConcat, locationToken )
1977+ local function insertTokensAsStringLiteral (tokens , tokensToConcat , locationTok )
1978+ local lua = _concatTokens (tokensToConcat , nil , false , nil , nil )
1979+
1980+ tableInsert (tokens , newTokenAt ({
1981+ type = " string" ,
1982+ value = lua ,
1983+ representation = F (" %q" , lua ):gsub (" \n " , " n" ),
1984+ long = false ,
1985+ }, locationTok ))
1986+
1987+ return lua
1988+ end
1989+
19651990local function doLateExpansionsMacros (tokensToExpand , fileBuffers , params , stats )
19661991 --
19671992 -- Expand expressions:
@@ -2008,7 +2033,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20082033 local stringTok = tokNext
20092034 popTokens (tokenStack , iNext ) -- the string
20102035
2011- -- Add " !!(ident" .
2036+ -- Add ' !!(ident' .
20122037 tableInsert (tokens , newTokenAt ({type = " pp_entry" , value = " !!" , representation = " !!" , double = true }, ppKeywordTok ))
20132038 tableInsert (tokens , newTokenAt ({type = " punctuation" , value = " (" , representation = " (" }, ppKeywordTok ))
20142039 tableInsert (tokens , identTok )
@@ -2017,7 +2042,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20172042 stringTok .representation = F (" %q" , stringTok .value ):gsub (" \n " , " n" )
20182043 tableInsert (tokens , stringTok )
20192044
2020- -- Add ")" .
2045+ -- Add ')' .
20212046 tableInsert (tokens , newTokenAt ({type = " punctuation" , value = " )" , representation = " )" }, ppKeywordTok ))
20222047
20232048 -- @insert identifier { ... }
@@ -2028,7 +2053,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20282053 -- (Similar code as `@insert identifier()` below.)
20292054 --
20302055
2031- -- Add " !!(ident" .
2056+ -- Add ' !!(ident' .
20322057 tableInsert (tokens , newTokenAt ({type = " pp_entry" , value = " !!" , representation = " !!" , double = true }, ppKeywordTok ))
20332058 tableInsert (tokens , newTokenAt ({type = " punctuation" , value = " (" , representation = " (" }, ppKeywordTok ))
20342059 tableInsert (tokens , identTok )
@@ -2046,7 +2071,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20462071 errorAtToken (fileBuffers , tableStartTok , nil , " Macro" , " Syntax error: Could not find end of table constructor before EOF." )
20472072
20482073 elseif tok .type :find " ^pp_" then
2049- errorAtToken (fileBuffers , tok , nil , " Macro" , " Non-simple preprocessor code not supported in macros . (Macro starts %s)" , getRelativeLocationText (ppKeywordTok , tok ))
2074+ errorAtToken (fileBuffers , tok , nil , " Macro" , " Unsupported preprocessor code in macro . (Macro starts %s)" , getRelativeLocationText (ppKeywordTok , tok ))
20502075
20512076 elseif bracketDepth == 1 and isToken (tok , " punctuation" , " }" ) then
20522077 tableInsert (argTokens , tableRemove (tokenStack )) -- '}'
@@ -2062,11 +2087,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20622087 end
20632088 end
20642089
2065- local parts = {}
2066- for i , argTok in ipairs (argTokens ) do
2067- parts [i ] = argTok .representation
2068- end
2069- local argStr = table.concat (parts )
2090+ local argStr = _concatTokens (argTokens , nil , false , nil , nil )
20702091
20712092 local chunk , err = loadLuaString (" return " .. argStr , " @" )
20722093 if not chunk then
@@ -2083,7 +2104,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20832104 long = false ,
20842105 }, tableStartTok ))
20852106
2086- -- Add ")" .
2107+ -- Add ')' .
20872108 tableInsert (tokens , newTokenAt ({type = " punctuation" , value = " )" , representation = " )" }, ppKeywordTok ))
20882109
20892110 -- @insert identifier ( argument1, ... )
@@ -2096,7 +2117,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
20962117 local parensStartTok = tokNext
20972118 popTokens (tokenStack , iNext ) -- '('
20982119
2099- -- Add " !!(ident(" .
2120+ -- Add ' !!(ident(' .
21002121 tableInsert (tokens , newTokenAt ({type = " pp_entry" , value = " !!" , representation = " !!" , double = true }, ppKeywordTok ))
21012122 tableInsert (tokens , newTokenAt ({type = " punctuation" , value = " (" , representation = " (" }, ppKeywordTok ))
21022123 tableInsert (tokens , identTok )
@@ -2110,25 +2131,83 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
21102131 local lastArgSeparatorTok = nil
21112132
21122133 for argNum = 1 , 1 / 0 do
2113- local argStartTok = tokenStack [ # tokenStack ]
2114- local argTokens = {}
2115- local depthStack = {}
2116- popUseless ( tokenStack )
2134+ -- Add argument separator.
2135+ if lastArgSeparatorTok then
2136+ tableInsert ( tokens , lastArgSeparatorTok )
2137+ end
21172138
21182139 -- Collect tokens for this arg.
21192140 -- We're looking for the next comma at depth 0 or closing ')'.
2141+ local argNonPpStartTok = tokenStack [# tokenStack ]
2142+ local argNonPpTokens = {}
2143+ local depthStack = {}
2144+ local insertedPpEntry = false
2145+ popUseless (tokenStack ) -- Trim leading useless tokens.
2146+
21202147 while true do
2121- tok = tokenStack [# tokenStack ]
2148+ local len = # tokenStack
2149+ tok = tokenStack [len ]
21222150
21232151 if not tok then
21242152 errorAtToken (fileBuffers , parensStartTok , nil , " Macro" , " Syntax error: Could not find end of argument list before EOF." )
21252153
2154+ -- Preprocessor block in macro.
2155+ 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
2172+
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
2200+ argNonPpStartTok = tokenStack [# tokenStack ] -- Could be nil, but that should be fine I think.
2201+
2202+ -- Other preprocessor code in macro.
21262203 elseif tok .type :find " ^pp_" then
2127- errorAtToken (fileBuffers , tok , nil , " Macro" , " Non-simple preprocessor code not supported in macros . (Macro starts %s)" , getRelativeLocationText (ppKeywordTok , tok ))
2204+ errorAtToken (fileBuffers , tok , nil , " Macro" , " Unsupported preprocessor code in macro . (Macro starts %s)" , getRelativeLocationText (ppKeywordTok , tok ))
21282205
2206+ -- End of argument.
21292207 elseif not depthStack [1 ] and (isToken (tok , " punctuation" , " ," ) or isToken (tok , " punctuation" , " )" )) then
21302208 break
21312209
2210+ -- Normal token.
21322211 else
21332212 if isToken (tok , " punctuation" , " (" ) then
21342213 tableInsert (depthStack , {startToken = tok , [1 ]= " punctuation" , [2 ]= " )" })
@@ -2161,41 +2240,34 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
21612240 tableRemove (depthStack )
21622241 end
21632242
2164- tableInsert (argTokens , tableRemove (tokenStack )) -- anything
2243+ tableInsert (argNonPpTokens , tableRemove (tokenStack )) -- anything
21652244 end
21662245 end
21672246
2168- popUseless (argTokens )
2169- if not argTokens [1 ] then
2170- errorAtToken (fileBuffers , argStartTok , nil , " Macro" , " Syntax error: Expected argument #%d." , argNum )
2171- end
2247+ -- Add last part of argument value.
2248+ popUseless (argNonPpTokens ) -- Trim trailing useless tokens.
21722249
2173- local parts = {}
2174- for i , argTok in ipairs ( argTokens ) do
2175- parts [ i ] = argTok . representation
2176- end
2177- local argStr = table.concat ( parts )
2250+ if argNonPpTokens [ 1 ] then
2251+ if insertedPpEntry then
2252+ tableInsert ( tokens , newTokenAt ({ type = " punctuation " , value = " .. " , representation = " .. " }, argNonPpStartTok ))
2253+ end
2254+ local argStr = insertTokensAsStringLiteral ( tokens , argNonPpTokens , argNonPpStartTok )
21782255
2179- local chunk , err = loadLuaString (" return (" .. argStr .. " )" , " @" )
2180- if not chunk then
2181- errorAtToken (fileBuffers , argTokens [1 ], nil , " Macro" , " Syntax error: Invalid expression for argument #%d." , argNum )
2182- -- err = err:gsub("^:%d+: ", "")
2183- -- errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid expression for argument #%d. (%s)", argNum, err)
2184- end
2256+ if not insertedPpEntry then
2257+ local chunk , err = loadLuaString (" return (" .. argStr .. " )" , " @" )
21852258
2186- -- Add argument separator.
2187- if lastArgSeparatorTok then
2188- tableInsert (tokens , lastArgSeparatorTok )
2189- end
2259+ if not chunk then
2260+ errorAtToken (fileBuffers , argNonPpStartTok , nil , " Macro" , " Syntax error: Invalid expression for argument #%d." , argNum )
2261+ -- err = err:gsub("^:%d+: ", "")
2262+ -- errorAtToken(fileBuffers, argNonPpStartTok, nil, "Macro", "Syntax error: Invalid expression for argument #%d. (%s)", argNum, err)
2263+ end
2264+ end
21902265
2191- -- Add argument value.
2192- tableInsert (tokens , newTokenAt ({
2193- type = " string" ,
2194- value = argStr ,
2195- representation = F (" %q" , argStr ):gsub (" \n " , " n" ),
2196- long = false ,
2197- }, argStartTok ))
2266+ elseif not insertedPpEntry then
2267+ errorAtToken (fileBuffers , argNonPpStartTok , nil , " Macro" , " Syntax error: Expected argument #%d." , argNum )
2268+ end
21982269
2270+ -- Do next argument or finish arguments.
21992271 if isLastToken (tokenStack , " punctuation" , " )" ) then
22002272 break
22012273 end
@@ -2205,7 +2277,7 @@ local function doLateExpansionsMacros(tokensToExpand, fileBuffers, params, stats
22052277 end -- for argNum
22062278 end
22072279
2208- -- Add "))" .
2280+ -- Add '))' .
22092281 tableInsert (tokens , tableRemove (tokenStack )) -- ')'
22102282 tableInsert (tokens , newTokenAt ({type = " punctuation" , value = " )" , representation = " )" }, ppKeywordTok ))
22112283 end
@@ -2306,7 +2378,7 @@ local function _processFileOrString(params, isFile)
23062378 local function flushTokensToProcess ()
23072379 if not tokensToProcess [1 ] then return end
23082380
2309- local lua = _concatTokens (tokensToProcess , ln , params .addLineNumbers )
2381+ local lua = _concatTokens (tokensToProcess , ln , params .addLineNumbers , nil , nil )
23102382 local luaMeta
23112383
23122384 if isDebug then
@@ -2580,7 +2652,7 @@ local function _processFileOrString(params, isFile)
25802652 tokenIndex = tokenIndex + 1
25812653 end
25822654
2583- local metaBlock = _concatTokens (tokensInBlock , nil , params .addLineNumbers )
2655+ local metaBlock = _concatTokens (tokensInBlock , nil , params .addLineNumbers , nil , nil )
25842656
25852657 if loadLuaString (" return(" .. metaBlock .. " )" ) then
25862658 tableInsert (metaParts , (doOutputLua and " __LUA((" or " __VAL((" ))
0 commit comments