From 33adf4a8d6bec271e170698ff0da5cb488440ece Mon Sep 17 00:00:00 2001 From: v_vz <86975939+Mp3Alt@users.noreply.github.com> Date: Mon, 13 Apr 2026 00:07:22 -0500 Subject: [PATCH 1/2] Major bug fixes in luamin.js Fixes Tokenizers strict expectations with numbers. Fixes ";" stripping ambiguously. Fixes unary spacing. "-49" -> "- 49" and "#table" -> "# table" Removes trailing ";". "" --- src/luamin.js | 59 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/luamin.js b/src/luamin.js index 8e694bb..27af150 100644 --- a/src/luamin.js +++ b/src/luamin.js @@ -424,14 +424,32 @@ function CreateLuaTokenStream(text) { } else if(Digits.includes(c1) || (c1 == '.' && Digits.includes(look()))) { // Number - if (c1 == '0' && look().toLowerCase() == 'x') { - p++ + let isHex = false; + let isBin = false; + let pOffset = 0; + + // Peek forward to check for 'x' or 'b' after '0' and any '_' + if (c1 === '0') { + let peekChar = look(pOffset); + while (peekChar === '_') { + pOffset++; + peekChar = look(pOffset); + } + if (peekChar.toLowerCase() === 'x') { + isHex = true; + p += pOffset + 1; // Consume up to 'x' + } else if (peekChar.toLowerCase() === 'b') { + isBin = true; + p += pOffset + 1; // Consume up to 'b' + } + } + + if (isHex) { // Hex number while (HexDigits.includes(look()) || look() === '_') { p++ } - } else if (c1 == '0' && look().toLowerCase() == 'b') { - p++ + } else if (isBin) { // Binary number while (look() === '0' || look() === '1' || look() === '_') { p++ @@ -442,21 +460,21 @@ function CreateLuaTokenStream(text) { p++ } - if (look() == '.') { + if (look() === '.') { // With decimal point p++ - while (Digits.includes(look())) { + while (Digits.includes(look()) || look() === '_') { p++ } } - if (look() == 'e' || look() == 'E') { + if (look() === 'e' || look() === 'E') { // With exponent p++ - if (look() == '-' || look() == '+') { + if (look() === '-' || look() === '+') { p++ } - while (Digits.includes(look())) { + while (Digits.includes(look()) || look() === '_') { p++ } } @@ -2600,9 +2618,14 @@ function FormatAst(ast, indentation) { padToken(expr.Token_Op) //} } else if(expr.Type == "UnopExpr") { - //padToken(expr.Token_Op) formatExpr(expr.Rhs) - padToken(expr.Rhs.GetFirstToken()) + // Only add a space if the operator is a word like 'not' + if (expr.Token_Op.Source === 'not') { + padToken(expr.Rhs.GetFirstToken()) + } else { + // Otherwise, squish them together for '-' and '#' + trimToken(expr.Rhs.GetFirstToken()) + } } else if(expr.Type == "NumberLiteral" || expr.Type == "StringLiteral" || expr.Type == "NilLiteral" || expr.Type == "BooleanLiteral" || expr.Type == "VargLiteral" || expr.Type == 'HashLiteral') @@ -3008,7 +3031,12 @@ function StripAst(ast) { let firstCh = (typeof tokenB.Source == 'string' ? tokenB.Source : tokenB.Source.toString()).substr(0,1) if ((lastCh == "-" && firstCh == "-") || (AllIdentChars.includes(lastCh) && AllIdentChars.includes(firstCh)) || (shit && lastCh == ')' && firstCh == '(')) { - tokenB.LeadingWhite = shit ? ';' : ' ' + // Only force a semicolon if it's the specific ')( ' edge case + if (shit && lastCh == ')' && firstCh == '(') { + tokenB.LeadingWhite = ';'; + } else { + tokenB.LeadingWhite = ' '; + } } else { tokenB.LeadingWhite = "" } @@ -3177,10 +3205,9 @@ function StripAst(ast) { } if (stat.SemicolonList[i-1]) { - let lastS = lastChStat.GetLastToken().Source - let firstS = chStat.GetFirstToken().Source - if (bannedCombos[lastS] === null || bannedCombos[lastS] === undefined || !bannedCombos[lastS].includes(firstS)) { - stat.SemicolonList[i-1] = null + let firstS = chStat.GetFirstToken().Source; + if (firstS !== '(' && firstS !== '[') { + stat.SemicolonList[i-1] = null; } } From 606c253a6dec23e1347dda50bfa3f6974e26f40f Mon Sep 17 00:00:00 2001 From: v_vz <86975939+Mp3Alt@users.noreply.github.com> Date: Mon, 13 Apr 2026 00:46:15 -0500 Subject: [PATCH 2/2] Refactor number parsing Added "if (!radix || radix === 10) { return Number(str.toString()); }" to parseFloat to handle function notation. Revert 0_x, 0_b number fix, as it broke other numbers in specific cases. --- src/luamin.js | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/luamin.js b/src/luamin.js index 27af150..e00e32f 100644 --- a/src/luamin.js +++ b/src/luamin.js @@ -34,6 +34,9 @@ const assert = function(a,b) { function parseFloat(str, radix) { if (!str) return 0; + if (!radix || radix === 10) { + return Number(str.toString()); + } var parts = str.toString().split("."); if (parts.length > 1) { return parseInt(parts[0], radix) + parseInt(parts[1], radix) / Math.pow(radix, parts[1].length); @@ -424,32 +427,14 @@ function CreateLuaTokenStream(text) { } else if(Digits.includes(c1) || (c1 == '.' && Digits.includes(look()))) { // Number - let isHex = false; - let isBin = false; - let pOffset = 0; - - // Peek forward to check for 'x' or 'b' after '0' and any '_' - if (c1 === '0') { - let peekChar = look(pOffset); - while (peekChar === '_') { - pOffset++; - peekChar = look(pOffset); - } - if (peekChar.toLowerCase() === 'x') { - isHex = true; - p += pOffset + 1; // Consume up to 'x' - } else if (peekChar.toLowerCase() === 'b') { - isBin = true; - p += pOffset + 1; // Consume up to 'b' - } - } - - if (isHex) { + if (c1 == '0' && look().toLowerCase() == 'x') { + p++ // Hex number while (HexDigits.includes(look()) || look() === '_') { p++ } - } else if (isBin) { + } else if (c1 == '0' && look().toLowerCase() == 'b') { + p++ // Binary number while (look() === '0' || look() === '1' || look() === '_') { p++ @@ -460,21 +445,21 @@ function CreateLuaTokenStream(text) { p++ } - if (look() === '.') { + if (look() == '.') { // With decimal point p++ - while (Digits.includes(look()) || look() === '_') { + while (Digits.includes(look())) { p++ } } - if (look() === 'e' || look() === 'E') { + if (look() == 'e' || look() == 'E') { // With exponent p++ - if (look() === '-' || look() === '+') { + if (look() == '-' || look() == '+') { p++ } - while (Digits.includes(look()) || look() === '_') { + while (Digits.includes(look())) { p++ } }