Skip to content

Commit ffe7517

Browse files
committed
Dual code now only accepts a single assignment statement on the line, as it should.
1 parent 54b2b14 commit ffe7517

File tree

2 files changed

+103
-39
lines changed

2 files changed

+103
-39
lines changed

RunTest.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
@ECHO OFF
22
IF NOT EXIST local MD local
33
lua preprocess-cl.lua --debug --saveinfo=local/info.lua test.lua2p
4+
REM lua preprocess-cl.lua --debug --saveinfo=local/info.lua test.lua2p --linenumbers

preprocess.lua

Lines changed: 102 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,11 @@ local escapePattern
185185
local F
186186
local getFileContents, fileExists
187187
local getNextUsableToken
188+
local insertTokenRepresentations
188189
local isAny
190+
local isToken
189191
local loadLuaString, loadLuaFile
190-
local maybeOutputLineNumber
192+
local outputLineNumber, maybeOutputLineNumber
191193
local pack, unpack
192194
local parseStringlike
193195
local printf, printTokens
@@ -515,6 +517,12 @@ function concatTokens(tokens, lastLn, addLineNumbers)
515517
return table.concat(parts)
516518
end
517519

520+
function insertTokenRepresentations(parts, tokens, i1, i2)
521+
for i = i1, i2 do
522+
table.insert(parts, tokens[i].representation)
523+
end
524+
end
525+
518526
function getFileContents(path, isTextFile)
519527
assertarg(1, path, "string")
520528
assertarg(2, isTextFile, "boolean","nil")
@@ -667,16 +675,29 @@ function escapePattern(s)
667675
return (s:gsub("[-+*^?$.%%()[%]]", "%%%0"))
668676
end
669677

678+
function outputLineNumber(parts, ln)
679+
table.insert(parts, "--[[@")
680+
table.insert(parts, ln)
681+
table.insert(parts, "]]")
682+
end
683+
function maybeOutputLineNumber(parts, tok, lastLn)
684+
if tok.line == lastLn or USELESS_TOKENS[tok.type] then return lastLn end
685+
686+
outputLineNumber(parts, tok.line)
687+
return tok.line
688+
end
689+
--[=[
670690
function maybeOutputLineNumber(parts, tok, lastLn, fromMetaToOutput)
671691
if tok.line == lastLn or USELESS_TOKENS[tok.type] then return lastLn end
672692
673-
-- if fromMetaToOutput then
674-
-- table.insert(parts, '__LUA"--[[@'..tok.line..']]"\n')
675-
-- else
693+
if fromMetaToOutput then
694+
table.insert(parts, '__LUA"--[[@'..tok.line..']]"\n')
695+
else
676696
table.insert(parts, "--[[@"..tok.line.."]]")
677-
-- end
697+
end
678698
return tok.line
679699
end
700+
]=]
680701

681702
function isAny(v, ...)
682703
for i = 1, select("#", ...) do
@@ -767,16 +788,29 @@ else
767788
end
768789
end
769790

770-
-- token, index = getNextUsableToken( tokens, startIndex [, maxIndex=#tokens ] )
771-
function getNextUsableToken(tokens, i, iEnd)
772-
for i = i, math.min((iEnd or math.huge), #tokens) do
791+
-- token, index = getNextUsableToken( tokens, startIndex [, indexLimit, direction=1 ] )
792+
function getNextUsableToken(tokens, i, iLimit, dir)
793+
dir = dir or 1
794+
795+
iLimit
796+
= dir < 0
797+
and math.max((iLimit or 1), 1)
798+
or math.min((iLimit or math.huge), #tokens)
799+
800+
for i = i, iLimit, dir do
773801
if not USELESS_TOKENS[tokens[i].type] then
774802
return tokens[i], i
775803
end
776804
end
805+
777806
return nil
778807
end
779808

809+
-- bool = isToken( token, tokenType [, tokenValue=any ] )
810+
function isToken(tok, tokType, v)
811+
return tok.type == tokType and (v == nil or tok.value == v)
812+
end
813+
780814
--==============================================================
781815
--= Preprocessor Functions =====================================
782816
--==============================================================
@@ -820,6 +854,11 @@ metaFuncs.serialize = serialize
820854
-- escapedString = escapePattern( string )
821855
metaFuncs.escapePattern = escapePattern
822856

857+
-- isToken()
858+
-- Check if a token is of a specific type, optionally also check it's value.
859+
-- bool = isToken( token, tokenType [, tokenValue=any ] )
860+
metaFuncs.isToken = isToken
861+
823862
-- run()
824863
-- Execute a Lua file. Similar to dofile().
825864
-- returnValue1, ... = run( path )
@@ -926,13 +965,6 @@ function metaFuncs.eachToken(tokens, ignoreUselessTokens)
926965
end
927966
end
928967

929-
-- isToken()
930-
-- Check if a token is of a specific type, optionally also check it's value.
931-
-- bool = isToken( token, tokenType [, tokenValue=any ] )
932-
function metaFuncs.isToken(tok, tokType, v)
933-
return tok.type == tokType and (v == nil or tok.value == v)
934-
end
935-
936968
-- newToken()
937969
-- Create a new token. Different token types take different arguments.
938970
-- token = newToken( tokenType, ... )
@@ -1151,7 +1183,7 @@ local function _processFileOrString(params, isFile)
11511183
--==============================================================
11521184

11531185
for _, tok in ipairs(tokens) do
1154-
if tok.type == "pp_entry" then
1186+
if isToken(tok, "pp_entry") then
11551187
hasPreprocessorCode = true
11561188
break
11571189
end
@@ -1181,36 +1213,35 @@ local function _processFileOrString(params, isFile)
11811213
tokensToProcess = {}
11821214
end
11831215

1184-
local function outputFinalDualValueStatement(metaLineStartIndex)
1216+
local function outputFinalDualValueStatement(metaLineIndexStart, metaLineIndexEnd)
11851217
-- We expect the statement to look like any of these:
11861218
-- !!local x = ...
11871219
-- !!x = ...
11881220

1189-
-- Note: Something like the following produces a valid program, but won't work as expected:
1190-
-- !!local x = 1; local y = 2;
1191-
-- Only x will be outputted. @Robustness: Don't allow this.
1192-
1193-
local tok, i = getNextUsableToken(tokens, metaLineStartIndex, tokenIndex-1)
1221+
-- Check whether local or not.
1222+
local tok, i = getNextUsableToken(tokens, metaLineIndexStart, metaLineIndexEnd)
11941223
if not tok then
11951224
errorInFile(
1196-
luaUnprocessed, pathIn, tokens[metaLineStartIndex].position, "Parser",
1225+
luaUnprocessed, pathIn, tokens[metaLineIndexStart].position, "Parser",
11971226
"Unexpected end of preprocessor line."
11981227
)
11991228
end
12001229

1201-
local isLocal = (tok.type == "keyword" and tok.value == "local")
1230+
local isLocal = isToken(tok, "keyword", "local")
12021231

12031232
if isLocal then
1204-
tok, i = getNextUsableToken(tokens, i+1, tokenIndex-1)
1233+
tok, i = getNextUsableToken(tokens, i+1, metaLineIndexEnd)
12051234
if not tok then
12061235
errorInFile(
1207-
luaUnprocessed, pathIn, tokens[metaLineStartIndex].position, "Parser",
1236+
luaUnprocessed, pathIn, tokens[metaLineIndexStart].position, "Parser",
12081237
"Unexpected end of preprocessor line."
12091238
)
12101239
end
12111240
end
12121241

1213-
if tok.type ~= "identifier" then
1242+
-- Check for identifier.
1243+
-- @Incomplete: Support multiple assignments. :MultipleAssignments
1244+
if not isToken(tok, "identifier") then
12141245
errorInFile(
12151246
luaUnprocessed, pathIn, tok.position, "Parser",
12161247
"Expected an identifier."
@@ -1219,28 +1250,65 @@ local function _processFileOrString(params, isFile)
12191250

12201251
local ident = tok.value
12211252

1222-
tok, i = getNextUsableToken(tokens, i+1, tokenIndex-1)
1253+
-- Check for "=".
1254+
tok, i = getNextUsableToken(tokens, i+1, metaLineIndexEnd)
12231255
if not tok then
12241256
errorInFile(
1225-
luaUnprocessed, pathIn, tokens[metaLineStartIndex].position, "Parser",
1257+
luaUnprocessed, pathIn, tokens[metaLineIndexStart].position, "Parser",
12261258
"Unexpected end of preprocessor line."
12271259
)
1228-
elseif not (tok.type == "punctuation" and tok.value == "=") then
1260+
elseif isToken(tok, "punctuation", ",") then
1261+
-- :MultipleAssignments
1262+
errorInFile(
1263+
luaUnprocessed, pathIn, tok.position, "Parser",
1264+
"Preprocessor line must be a single assignment. (Multiple assignments are not supported.)"
1265+
)
1266+
elseif not isToken(tok, "punctuation", "=") then
12291267
errorInFile(
12301268
luaUnprocessed, pathIn, tok.position, "Parser",
12311269
"Preprocessor line must be an assignment."
12321270
)
12331271
end
12341272

1235-
if not getNextUsableToken(tokens, i+1, tokenIndex-1) then
1273+
local indexAfterEqualSign = i+1
1274+
1275+
if not getNextUsableToken(tokens, indexAfterEqualSign, metaLineIndexEnd) then
12361276
errorInFile(
12371277
luaUnprocessed, pathIn, tok.position, "Parser",
12381278
"Unexpected end of preprocessor line."
12391279
)
12401280
end
12411281

1282+
-- Check if the rest of the line is an expression.
1283+
if true then
1284+
local lastUsableToken, lastUsableIndex = getNextUsableToken(tokens, metaLineIndexEnd+1, 1, -1)
1285+
local parts = {}
1286+
1287+
table.insert(parts, "return (")
1288+
if isToken(lastUsableToken, "punctuation", ";") then
1289+
insertTokenRepresentations(parts, tokens, indexAfterEqualSign, lastUsableIndex-1)
1290+
else
1291+
insertTokenRepresentations(parts, tokens, indexAfterEqualSign, metaLineIndexEnd)
1292+
end
1293+
table.insert(parts, "\n)")
1294+
1295+
if not loadstring(table.concat(parts)) then
1296+
errorInFile(
1297+
luaUnprocessed, pathIn, tokens[metaLineIndexStart].position, "Parser",
1298+
"Dual code line must be a single assignment statement."
1299+
)
1300+
end
1301+
end
1302+
1303+
-- Output.
12421304
table.insert(metaParts, '__LUA"')
1305+
1306+
if params.addLineNumbers then
1307+
outputLineNumber(metaParts, tokens[metaLineIndexStart].line)
1308+
end
1309+
12431310
if isLocal then table.insert(metaParts, 'local ') end
1311+
12441312
table.insert(metaParts, ident)
12451313
table.insert(metaParts, ' = "__VAL(')
12461314
table.insert(metaParts, ident)
@@ -1251,7 +1319,7 @@ local function _processFileOrString(params, isFile)
12511319

12521320
-- Note: Can be multiple lines if extended.
12531321
local function processMetaLine(isDual, metaStartLine)
1254-
local metaLineStartIndex = tokenIndex
1322+
local metaLineIndexStart = tokenIndex
12551323
local bracketBalance = 0
12561324

12571325
while true do
@@ -1273,7 +1341,7 @@ local function _processFileOrString(params, isFile)
12731341
end
12741342

12751343
if isDual then
1276-
outputFinalDualValueStatement(metaLineStartIndex)
1344+
outputFinalDualValueStatement(metaLineIndexStart, tokenIndex-1)
12771345
end
12781346

12791347
break
@@ -1323,12 +1391,7 @@ local function _processFileOrString(params, isFile)
13231391
-- !( function sum(a, b) return a+b; end )
13241392
-- local text = !("Hello, mr. "..getName())
13251393
-- _G.!!("myRandomGlobal"..math.random(5)) = 99
1326-
if
1327-
tokType == "pp_entry"
1328-
and tokens[tokenIndex+1]
1329-
and tokens[tokenIndex+1].type == "punctuation"
1330-
and tokens[tokenIndex+1].value == "("
1331-
then
1394+
if tokType == "pp_entry" and tokens[tokenIndex+1] and isToken(tokens[tokenIndex+1], "punctuation", "(") then
13321395
local startToken = tok
13331396
local startPos = tok.position
13341397
local startLine = tok.line

0 commit comments

Comments
 (0)