' ============================================================ ' 轻量行格式化:仅补空格,不删不改,复合运算符不拆分 ' ============================================================ #ifndef __TRIM_MACROS__ # define __TRIM_MACROS__ # define TrimAny(s) Trim(s, any Chr(32) +Chr(9)) # define LTrimAny(s) LTrim(s, any Chr(32) +Chr(9)) # define RTrimAny(s) RTrim(s, any Chr(32) +Chr(9)) #endif Dim shared keywordList(...) As zSTRING * 12 = { _ "eqv", "xor", "andalso", "orelse", "to", _ "return", "print", "let", "data", _ "and", "or", "not", "imp", "step", _ "if", "then", "else", "do", "while", "until", "case" } private Function IsKeyword(word As STRING) As BOOLEAN Dim lowWord As STRING = lcase(word) For i As INTEGER = lbound(keywordList) To ubound(keywordList) If RtrimAny(lcase(keywordList(i))) = lowWord Then Return True Next Return False End Function private Function GetPrevWord(Byval lineText As STRING, Byval curPos As INTEGER) As STRING Dim j As INTEGER = curPos - 1 If j < 0 Then Return "" If lineText[j] = 32 Then j -= 1 '如果-左边是空格,则左移一格读取关键字 Dim wordBuf As STRING = "" While j >= 0 Select Case lineText[j] Case 32, 9 '跳过前面的空格后,后面遇到空格就是结束符 ' Exit While Case 48 To 57, 65 To 90, 95, 97 To 122 wordBuf = chr(lineText[j]) + wordBuf Case Else Exit While End Select j -= 1 Wend Return wordBuf End Function private Function EndsWithSpace(s As STRING) As BOOLEAN If len(s) = 0 Then Return False Dim c As STRING = right(s, 1) Return (c = " " ORelse c = chr(9)) End Function Function AddSpacesAroundOperators(Byval LineText As STRING) As STRING If len(trimany(LineText)) = 0 Then Return LineText Dim indentLen As INTEGER = 0 While indentLen < len(LineText) ANDALSO (LineText[indentLen] = 32 OR LineText[indentLen] = 9) indentLen += 1 Wend Dim indent As STRING = left(LineText, indentLen) Dim sLine As STRING = mid(LineText, indentLen + 1) If left(trimany(sLine), 1) = "#" OR left(trimany(sLine), 1) = "'" Then Return LineText Dim result As STRING = "" Dim As BOOLEAN inString = False, inComment = False Dim As INTEGER i = 0, n = len(sLine) While i < n Dim c As UBYTE = sLine[i] Dim curCh As STRING = chr(c) ' 字符串/注释 原样输出 If c = 34 Then result += curCh i += 1 If i < n ANDALSO sLine[i] = 34 Then ' 连续两个 "" → 转义,原样输出第二个 " result += chr(34) i += 1 ' inString 保持 True,不翻转 Else ' 单个 " → 翻转字符串状态 inString = NOT inString End If Continue While End If If c = 39 AND NOT inString Then inComment = True If inComment OR inString Then result += curCh i += 1 Continue While end if select case c ' 点号 Case asc(".") If EndsWithSpace(result) Then result = rtrimany(result) End If ' 清除缓存末尾空格、制表符 while i + 1 < n and (sLine[i + 1] = 32 OR sLine[i + 1] = 9) i += 1 wend ' 括号 Case asc("("), asc("{") ' 关键字后紧跟(,前面补空格(如 if( → if () If IsKeyword(GetPrevWord(sLine, i)) AndAlso Not EndsWithSpace(result) Then result += " " End If result += curCh i += 1 ' 去掉括号后所有空格/Tab,实现 ( xxx → (xxx While i < n AndAlso (sLine[i] = 32 OR sLine[i] = 9) i += 1 Wend Continue While case asc("[") If EndsWithSpace(result) Then result = rtrimany(result) End If Case asc(")"), asc("]"), asc("}") ' 吃掉)前面所有空格,实现 a ) → a) While Len(result) > 0 AndAlso EndsWithSpace(result) result = RTrimAny(result) Wend result += curCh ' 括号后非运算符/标点则补空格(保持原有运算符逻辑不冲突) If i + 1 < n Then Dim nextC As UBYTE = sLine[i+1] Select Case nextC Case 32,9,44,59,58,41,40,46,61,62,60,43,45,42,47,92,94,38 ' 后接空格、标点、运算符,不额外加空格 Case Else result += " " End Select End If i += 1 Continue While ' 标点 , : ; 仅后面补空格 Case asc(","), asc(":"), asc(";") Dim lastC As UByte = Asc(Right(result,1)) If EndsWithSpace(result) Then result = rtrimany(result) End If result += curCh 'while i + 1 < n andalso not (sLine[i + 1] = 32 orelse sLine[i + 1] = 9) Dim j As Integer = i + 1 While j < n AndAlso (sLine[j] = 32 OrElse sLine[j] = 9) j += 1 Wend ' j 停在第一个非空白字符位置 If j < n Then result += " " End If i = j Continue While ' 判断<>,>=,<=,>,<,+,-,*,/,\,^,& case 60, 61, 62, 38, 42, 43, 45, 47, 92, 94, 66, 72, 79 ' 先根据后面的字符判断是否复合运算符 If i + 1 < n Then Dim twoChar As STRING = ucase(curCh & chr(sLine[i + 1])) ' 比较/逻辑复合运算符 >= <= <> =>, 赋值复合运算符 += -= *= /= \= &= ^= Select Case twochar '先判断 >= <= <> =>,二元 Case chr(62, 61), chr(60, 61), chr(60, 62), chr(61, 62) If NOT EndsWithSpace(result) Then result += " " result += twoChar If i + 2 < n AND NOT (sLine[i + 2] = 32 OR sLine[i + 2] = 9) Then result += " " i += 2 Continue While '再判断复合运算符,增加+=>的判断 Case chr(38, 61), chr(43, 61), chr(45, 61), chr(42, 61), _ chr(47, 61), chr(92, 61), chr(94, 61) If NOT EndsWithSpace(result) Then result += " " result += twoChar If i + 2 < n AND NOT (sLine[i + 2] = 32 OR sLine[i + 2] = 9) Then If chr(sLine[i + 2]) = ">" Then '=>赋值语法判断 result += ">" & " " i += 3 Continue While Else result += " " End If End If i += 2 Continue While Case Else exit select end select End If select case c '&判断,字符串连接和进制字符串前缀 '16,8,2进制符的判断:如果变量名以H,O,B头,那么以&连接时,后面必须跟空格,但可以紧跟"字符面量" '判断后面是空格原样输出,后面不是空格且不是H,B,O加一个空格,后面是HBO则&之后无空格 Case asc("&") ' chr(38)=& '1、先跳过&后方全部空白,找到真实下一个有效字符 Dim p As Integer = i + 1 While p < n AndAlso (sLine[p] = 32 OrElse sLine[p] = 9) p += 1 Wend If p < n Then Dim nextChar As String = ucase(chr(sLine[p])) If InStr("BHO", nextChar) Then ' 进制前缀,清理 & 与字母、字母与数字之间所有空格 result += "&" & nextChar p += 1 ' 读取数字段,跳过所有空格,只收集合法进制字符 Dim numPart As String = "" While p < n Dim cur As Integer = sLine[p] Select Case cur Case 32, 9 ' 空格tab直接跳过,不存入 p += 1 Case 48 To 57, 65 To 70, 97 To 102 ' 合法进制字符 numPart &= UCase(Chr(cur)) p += 1 Case Else ' 非进制字符终止读取 Exit While End Select Wend result &= numPart i = p Continue While Else ' 普通字符串连接,沿用原有空格逻辑不变 If Not EndsWithSpace(result) Then result += " " result += curCh & " " i += 1 Continue While End If End If Case asc("=") ' 前方无空格 → 补一个 If NOT EndsWithSpace(result) Then result += " " End If ' 输出等号 result += "=" ' 后方无空格 → 补一个(跳过判断,直接补,保证必加) Dim j As Integer = i + 1 ' 跳过连续空格、Tab While j < n AndAlso (sLine[j] = 32 OrElse sLine[j] = 9) j += 1 Wend ' 后面还有非空白字符,补单个空格 If j < n Then result += " " End If i = j Continue While ' * 解引用 / 乘法 Case asc("*") Dim prevWord As STRING = lcase(GetPrevWord(sLine, i)) Dim j As INTEGER = i - 1 While j >= 0 AND (sLine[j] = 32 OR sLine[j] = 9) j -= 1 Wend Dim isMultiply As BOOLEAN = false 'If prevWord <> "" ANDALSO j >= 0 Then If j >= 0 Then Select Case sLine[j] Case 41, 48 To 57, 93 ' 为)数字和]判断为乘法 isMultiply = true Case 65 To 90, 97 To 122, 95 ' 字母或下划线 If NOT IsKeyword(prevWord) Then isMultiply = true Case Else End Select End If If isMultiply Then If NOT EndsWithSpace(result) Then result += " " result += "*" If i + 1 < n AND NOT (sLine[i + 1] = 32) Then result += " " Else result += "*" End If i += 1 Continue While ' ====================== 减号 - 一元/二元 ====================== Case asc("-") Dim j As INTEGER = i + 1 ' 内联跳过空格 While j < n AND (sLine[j] = 32) j += 1 Wend ' 处理 -> 指针运算符 If j < n AND chr(sLine[j]) = ">" Then result += "->" i = j + 1 Continue While End If ' ============================================== ' ✅【修复】正确的一元负号判断逻辑 ' ============================================== Dim isUnary As BOOLEAN = False Dim k As INTEGER = i - 1 While k >= 0 AND (sLine[k] = 32 OR sLine[k] = 9) k -= 1 Wend ' If k < 0 Then ' 1. 行首 → 一元负号 isUnary = True Else Dim prevC As INTEGER = sLine[k] Select Case prevC ' 2. 前面是运算符 → 一元负号 Case asc("="), asc("+"), asc("-"), asc("*"), asc("/"), asc("\"), _ asc("^"), asc("&"), asc("("), asc(","), asc(":"), asc("<"), asc(">") isUnary = True Case 48 To 57, 41 '3. 前面是数字)是二元减法 isUnary = false Case 65 To 90, 97 To 122, 95 ' 3.1 前面是字母和_ → 二元减法 Dim prevWord As STRING = GetPrevWord(sLine, i) print prevword If IsKeyword(prevWord) Then isUnary = True ' 关键字后面 → 一元 Else isUnary = False End If Case Else ' 4. 其他情况,检查是不是关键字 isUnary = false End Select End If ' 输出处理 If isUnary Then result += "-" ' 一元负号:不加空格 Else ' 二元减法:前后加空格 If NOT EndsWithSpace(result) Then result += " " result += "-" If i + 1 < n AND NOT sLine[i + 1] = 32 Then result += " " End If i += 1 Continue While case else If NOT EndsWithSpace(result) Then result += " " result += curCh If i + 1 < n AND NOT (sLine[i + 1] = 32) Then result += " " i += 1 Continue While end select End Select ' 普通字符 result += curCh i += 1 Wend Return indent + result End Function