Skip to content

Commit e6e5c19

Browse files
committed
Handling hexadecimal fractions & binary exponents. Added missing token "::".
Updated detection of malformed numbers. Fixed internal error "error object is a nil value" in Lua 5.3.
1 parent f6f2203 commit e6e5c19

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

preprocess.lua

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ local PUNCTUATION = {
126126
"==", "~=", "<=", ">=", "<", ">", "=",
127127
"(", ")", "{", "}", "[", "]",
128128
";", ":", ",", ".", "..", "...",
129+
-- Lua 5.2
130+
"::",
129131
-- Lua 5.3
130132
"//", "&", "|", "~", ">>", "<<",
131133
} for i, v in ipairs(PUNCTUATION) do PUNCTUATION[v], PUNCTUATION[i] = true, nil end
@@ -231,7 +233,7 @@ function errorOnLine(path, ln, agent, s, ...)
231233
path, ln, s:format(...)
232234
)
233235
end
234-
onError(err, 2)
236+
onError(s, 2)
235237
end
236238
function errorInFile(contents, path, ptr, agent, s, ...)
237239
s = s:format(...)
@@ -258,7 +260,7 @@ function errorInFile(contents, path, ptr, agent, s, ...)
258260
path, ln, s, lastLine, ("-"):rep(col-1)
259261
)
260262
end
261-
onError(err, 2)
263+
onError(s, 2)
262264

263265
return s
264266
end
@@ -310,6 +312,15 @@ function parseStringlike(s, ptr)
310312
return tok, ptr
311313
end
312314

315+
local NUM_HEX_FRAC_EXP = ("^( 0x ([%dA-Fa-f]*) %.([%dA-Fa-f]+) [Pp]([-+]?[%dA-Fa-f]+) )"):gsub(" +", "")
316+
local NUM_HEX_FRAC = ("^( 0x ([%dA-Fa-f]*) %.([%dA-Fa-f]+) )"):gsub(" +", "")
317+
local NUM_HEX_EXP = ("^( 0x ([%dA-Fa-f]+) [Pp]([-+]?[%dA-Fa-f]+) )"):gsub(" +", "")
318+
local NUM_HEX = ("^( 0x [%dA-Fa-f]+ )"):gsub(" +", "")
319+
local NUM_DEC_FRAC_EXP = ("^( %d* %.%d+ [Ee][-+]?%d+ )"):gsub(" +", "")
320+
local NUM_DEC_FRAC = ("^( %d* %.%d+ )"):gsub(" +", "")
321+
local NUM_DEC_EXP = ("^( %d+ [Ee][-+]?%d+ )"):gsub(" +", "")
322+
local NUM_DEC = ("^( %d+ )"):gsub(" +", "")
323+
313324
-- tokens = tokenize( lua, filePath, allowBacktickStrings [, allowPreprocessorTokens=false ] )
314325
function tokenize(s, path, allowBacktickStrings, allowMetaTokens)
315326
local tokens = {}
@@ -333,17 +344,43 @@ function tokenize(s, path, allowBacktickStrings, allowMetaTokens)
333344

334345
-- Number.
335346
elseif s:find("^%.?%d", ptr) then
336-
local i1, i2, numStr = s:find("^(%d*%.%d+[Ee]%-?%d+)", ptr)
337-
if not i1 then i1, i2, numStr = s:find("^(%d+[Ee]%-?%d+)", ptr) end
338-
if not i1 then i1, i2, numStr = s:find("^(0x[%dA-Fa-f]+)", ptr) end
339-
if not i1 then i1, i2, numStr = s:find("^(%d*%.%d+)", ptr) end
340-
if not i1 then i1, i2, numStr = s:find("^(%d+)", ptr) end
341-
342-
if not i1 then
347+
local lua52Hex, i1, i2, numStr = true, s:find(NUM_HEX_FRAC_EXP, ptr)
348+
if not i1 then lua52Hex, i1, i2, numStr = true, s:find(NUM_HEX_FRAC, ptr) end
349+
if not i1 then lua52Hex, i1, i2, numStr = true, s:find(NUM_HEX_EXP, ptr) end
350+
if not i1 then lua52Hex, i1, i2, numStr = false, s:find(NUM_HEX, ptr) end
351+
if not i1 then lua52Hex, i1, i2, numStr = false, s:find(NUM_DEC_FRAC_EXP, ptr) end
352+
if not i1 then lua52Hex, i1, i2, numStr = false, s:find(NUM_DEC_FRAC, ptr) end
353+
if not i1 then lua52Hex, i1, i2, numStr = false, s:find(NUM_DEC_EXP, ptr) end
354+
if not i1 then lua52Hex, i1, i2, numStr = false, s:find(NUM_DEC, ptr) end
355+
356+
if not numStr then
343357
return nil, errorInFile(s, path, ptr, "Tokenizer", "Malformed number.")
344358
end
359+
if s:find("^[%w_]", i2+1) then
360+
-- This is actually only an error in Lua 5.1. Maybe we should issue a warning instead of an error here?
361+
return nil, errorInFile(s, path, i2+1, "Tokenizer", "Malformed number.")
362+
end
345363

346364
local n = tonumber(numStr)
365+
366+
-- Support hexadecimal floats in Lua 5.1.
367+
if not n and lua52Hex then
368+
local _, intStr, fracStr, expStr = numStr:match(NUM_HEX_FRAC_EXP)
369+
if not intStr then _, intStr, fracStr = numStr:match(NUM_HEX_FRAC) ; expStr = "0" end
370+
if not intStr then _, intStr, expStr = numStr:match(NUM_HEX_EXP) ; fracStr = "" end
371+
assert(intStr, numStr)
372+
373+
n = tonumber(intStr, 16) or 0 -- intStr may be "".
374+
375+
local fracValue = 1
376+
for i = 1, #fracStr do
377+
fracValue = fracValue/16
378+
n = n+tonumber(fracStr:sub(i, i), 16)*fracValue
379+
end
380+
381+
n = n*2^expStr:gsub("^+", "")
382+
end
383+
347384
if not n then
348385
return nil, errorInFile(s, path, ptr, "Tokenizer", "Invalid number.")
349386
end
@@ -492,7 +529,7 @@ function tokenize(s, path, allowBacktickStrings, allowMetaTokens)
492529
local repr = s:sub(ptr, ptr+2)
493530
tok = {type="punctuation", representation=repr, value=repr}
494531
ptr = ptr+#repr
495-
elseif s:find("^%.%.", ptr) or s:find("^[=~<>]=", ptr) or s:find("^//", ptr) or s:find("^<<", ptr) or s:find("^>>", ptr) then
532+
elseif s:find("^%.%.", ptr) or s:find("^[=~<>]=", ptr) or s:find("^::", ptr) or s:find("^//", ptr) or s:find("^<<", ptr) or s:find("^>>", ptr) then
496533
local repr = s:sub(ptr, ptr+1)
497534
tok = {type="punctuation", representation=repr, value=repr}
498535
ptr = ptr+#repr
@@ -1100,17 +1137,18 @@ function metaFuncs.newToken(tokType, ...)
11001137
numberFormat = numberFormat or "auto"
11011138

11021139
-- Some of these are technically multiple other tokens. We could trigger an error but ehhh...
1140+
-- @Incomplete: Hexadecimal floats.
11031141
local numStr
11041142
= n ~= n and "0/0"
11051143
or n == math.huge and "math.huge"
1106-
or n == -math.huge and "-math.huge"
1144+
or n == -math.huge and " -math.huge" -- The space prevents an accidental comment if a "-" is right before.
11071145
or numberFormat == "auto" and tostring(n)
11081146
or numberFormat == "integer" and F("%d", n)
11091147
or numberFormat == "float" and F("%f", n):gsub("(%d)0+$", "%1")
11101148
or numberFormat == "scientific" and F("%e", n):gsub("(%d)0+e", "%1e"):gsub("0+(%d+)$", "%1")
11111149
or numberFormat == "SCIENTIFIC" and F("%E", n):gsub("(%d)0+E", "%1E"):gsub("0+(%d+)$", "%1")
1112-
or numberFormat == "hexadecimal" and F("0x%x", n)
1113-
or numberFormat == "HEXADECIMAL" and F("0x%X", n)
1150+
or numberFormat == "hexadecimal" and (n == math.floor(n) and F("0x%x", n) or error("Hexadecimal floats not supported yet."))
1151+
or numberFormat == "HEXADECIMAL" and (n == math.floor(n) and F("0x%X", n) or error("Hexadecimal floats not supported yet."))
11141152
or error(F("Invalid number format '%s'.", numberFormat))
11151153

11161154
return {type="number", representation=numStr, value=n}

0 commit comments

Comments
 (0)