diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua index fee587c9d..b6adce38b 100644 --- a/polymer/eduke32/source/lunatic/lunacon.lua +++ b/polymer/eduke32/source/lunatic/lunacon.lua @@ -462,21 +462,33 @@ function warnprintf(fmt, ...) -- local end local function parse_number(pos, numstr) + -- is a full number string, potentially prefixed with a minus sign. local num = tonumber((numstr:gsub("h$", ""))) +-- local onum = num + local hex = numstr:match("0[xX]([^h]*)h?") -- get hex digits, if any -- num==nil for Rio Lua, which doesn't handle large hex literals. if (num==nil or not (num >= -0x80000000 and num <= 0xffffffff)) then - perrprintf(pos, "number %s out of the range of a 32-bit integer", numstr) - -- Be careful not to write bound checks like - -- "if (iHIGHBOUND) then error('...') end": - num = NaN - elseif (num >= 0x80000000 and numstr:sub(1,2):lower()~="0x") then - if (g_warn["number-conversion"]) then + -- number is UINT32_MAX or NaN + if (hex and #hex>8 and hex:sub(1,#hex-8):match("^[fF]$")) then + -- Too many hex digits, but they're all Fs. + pwarnprintf(pos, "number %s truncated to 32 bits", numstr) + num = bit.band(num, 0xffffffff) + else + perrprintf(pos, "number %s out of the range of a 32-bit integer", numstr) + -- Be careful not to write bound checks like + -- "if (iHIGHBOUND) then error('...') end": + num = NaN + end + elseif (num >= 0x80000000) then + if (not hex and g_warn["number-conversion"]) then pwarnprintf(pos, "number %s converted to a negative one", numstr) end - num = num-(0xffffffff+1) + num = bit.band(num, 0xffffffff) end +-- printf("numstr:%s, num=%d (0x%s) '%s', resnum=%d (0x%s)", +-- numstr, onum, bit.tohex(onum), hex, num, bit.tohex(num)) return num end @@ -2869,7 +2881,7 @@ local Grammar = Pat{ t_number = POS() * lpeg.C( tok.maybe_minus * ((Pat("0x") + "0X") * Range("09", "af", "AF")^1 * Pat("h")^-1 - + Range("09")^1) + + Range("09")^1) ) / parse_number, t_identifier_all = lpeg.C(t_broken_identifier + t_good_identifier), @@ -2935,7 +2947,7 @@ local Grammar = Pat{ + Keyw("whilevarn") * sp1 * tok.rvar * sp1 * tok.define / on.while_begin * sp1 * Var("single_stmt") * (lpeg.Cc(nil) / on.while_end), - stmt_common = Keyw("{") * sp1 * "}" / "do end" -- space separation of commands in CON is for a reason! + stmt_common = Keyw("{") * sp1 * "}" / "" -- space separation of commands in CON is for a reason! + Keyw("{") * sp1 * lpeg.Ct(stmt_list) * sp1 * "}" + con_inner_command + Var("switch_stmt") + lpeg.Ct(Var("while_stmt")), diff --git a/polymer/eduke32/source/lunatic/test/nlcf_break.con b/polymer/eduke32/source/lunatic/test/nlcf_break.con index 4f0f50c49..204d4d970 100644 --- a/polymer/eduke32/source/lunatic/test/nlcf_break.con +++ b/polymer/eduke32/source/lunatic/test/nlcf_break.con @@ -1,3 +1,5 @@ +// NOTE: This file is misnamed, "break" is local control flow, of course. + state teststate_break ifvare 1 1 { @@ -20,3 +22,23 @@ onevent EVENT_INIT redefinequote 114 STILL LIVE OUTER echo 114 endevent + +// Test number parsing +gamevar MINUS_ONE -1 0 +gamevar INT32_MIN 0x80000000 0 +gamevar INT32_MIN_ -0x80000000 0 +gamevar INT32_MINh 0x80000000h 0 +gamevar INT32_MIN_h -0x80000000h 0 + +gamevar INT32_MIN_P1 0x80000001 0 +gamevar INT32_MIN_P1h 0x80000001h 0 +//gamevar INT32_MAX_ -0x80000001 0 // error + +gamevar INT32_MAX 0x7fffffff 0 +gamevar INT32_MAXh 0x7fffffffh 0 + +// 9 digits? truncate it, but only because there's an F there. +gamevar SOMEHEX 0xFFEFC0001 0 + +// This one throws an error: +//gamevar BADHEX 0xBFEFC0001 0