Port of The Aether mod for versions of Minecraft after 1.14
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
14 KiB

  1. KEEP = 0 # keep original capitalization
  2. UPPER = 1 # convert to upper case
  3. LOWER = 2 # convert to lower case
  4. REMOVE = 3 # remove it
  5. ADD = 4 # add it
  6. TRUNC = 8 # for UNDERSCORES, if there is more than 1 underscore, remove the extras. for ZERO_XXXX, if there are unneccessary zeros, remove them.
  7. ADD_IF_NEEDED = 16 # for DOUBLE_TYPE_SUFFIX, if REMOVE is also specified and ZERO_FPART is REMOVE, re-add the suffix and remove the trailing decimal point.
  8. # ===== OPTIONS =====
  9. HEX_PREFIX = LOWER
  10. BINARY_PREFIX = LOWER
  11. OCTAL_PREFIX = REMOVE
  12. HEX_LITERAL = UPPER
  13. ZERO_IPART = ADD | TRUNC
  14. ZERO_FPART = ADD | TRUNC
  15. IPART_UNDERSCORES = KEEP
  16. FPART_UNDERSCORES = KEEP
  17. DOUBLE_TYPE_SUFFIX = REMOVE
  18. FLOAT_TYPE_SUFFIX = UPPER
  19. LONG_TYPE_SUFFIX = UPPER
  20. EXPONENT_INDICATOR = UPPER
  21. HEX_EXPONENT_INDICATOR = LOWER
  22. EXPONENT_SIGN = KEEP
  23. #####################
  24. assert HEX_PREFIX in (KEEP, UPPER, LOWER, REMOVE), f"Invalid value for HEX_PREFIX: {HEX_PREFIX}"
  25. assert BINARY_PREFIX in (KEEP, UPPER, LOWER, REMOVE), f"Invalid value for BINARY_PREFIX: {BINARY_PREFIX}"
  26. assert OCTAL_PREFIX in (KEEP, REMOVE), f"Invalid value for OCTAL_PREFIX: {OCTAL_PREFIX}"
  27. assert HEX_LITERAL in (KEEP, UPPER, LOWER), f"Invalid value for HEX_LITERAL: {HEX_LITERAL}"
  28. assert ZERO_IPART in (KEEP, ADD, REMOVE, TRUNC, ADD | TRUNC), f"Invalid value for ZERO_IPART: {ZERO_IPART}"
  29. assert ZERO_FPART in (KEEP, ADD, REMOVE, TRUNC, ADD | TRUNC), f"Invalid value for ZERO_FPART: {ZERO_FPART}"
  30. assert IPART_UNDERSCORES in (KEEP, ADD, REMOVE, TRUNC), f"Invalid value for IPART_UNDERSCORES: {IPART_UNDERSCORES}"
  31. assert FPART_UNDERSCORES in (KEEP, ADD, REMOVE, TRUNC), f"Invalid value for FPART_UNDERSCORES: {FPART_UNDERSCORES}"
  32. assert DOUBLE_TYPE_SUFFIX in (KEEP, ADD, REMOVE, UPPER, LOWER, REMOVE | ADD_IF_NEEDED) or DOUBLE_TYPE_SUFFIX.bit_length() == 3 and DOUBLE_TYPE_SUFFIX & (UPPER | LOWER) in (UPPER, LOWER), f"Invalid value for DOUBLE_TYPE_SUFFIX: {DOUBLE_TYPE_SUFFIX}"
  33. assert FLOAT_TYPE_SUFFIX in (KEEP, UPPER, LOWER), f"Invalid value for FLOAT_TYPE_SUFFIX: {FLOAT_TYPE_SUFFIX}"
  34. assert LONG_TYPE_SUFFIX in (KEEP, UPPER, LOWER), f"Invalid value for LONG_TYPE_SUFFIX: {LONG_TYPE_SUFFIX}"
  35. assert EXPONENT_INDICATOR in (KEEP, UPPER, LOWER), f"Invalid value for EXPONENT_INDICATOR: {EXPONENT_INDICATOR}"
  36. assert HEX_EXPONENT_INDICATOR in (KEEP, UPPER, LOWER), f"Invalid value for HEX_EXPONENT_INDICATOR: {HEX_EXPONENT_INDICATOR}"
  37. assert EXPONENT_SIGN in (KEEP, ADD, REMOVE), f"Invalid value for EXPONENT_SIGN: {EXPONENT_SIGN}"
  38. from glob import glob
  39. import re
  40. import os, os.path as path
  41. os.chdir(path.dirname(path.abspath(__file__)))
  42. DIGITS = r'(?:\d+(?:_+\d+)*)'
  43. HEX_DIGITS = r'(?:[a-fA-F0-9]+(?:_+[a-fA-F0-9]+)*)'
  44. BIN_DIGITS = r'(?:[01]+(?:_+[01]+)*)'
  45. OCT_DIGITS = r'(?:[0-7]+(?:_+[0-7]+)*)'
  46. ID_CHAR = r'[a-zA-Z_0-9$]'
  47. # INT_REGEX = re.compile(r'(?<!{ID_CHAR})([1-9]\d*(?:_+\d+)*|0([xX]{HEX_DIGITS}|[bB][01]+(?:_+[01]+)*|_*[0-7]+(?:_+[0-7]+)*))(?!{ID_CHAR})'.format_map(globals()))
  48. # LONG_REGEX = re.compile(r'(?<!{ID_CHAR})([1-9]\d*(?:_+\d+)*|0([xX]{HEX_DIGITS}|[bB][01]+(?:_+[01]+)*|_*[0-7]+(?:_+[0-7]+)*))[lL](?!{ID_CHAR})'.format_map(globals()))
  49. # FLOAT_REGEX = re.compile(r'(?<!{ID_CHAR})((\.{DIGITS}|{DIGITS}(\.{DIGITS}?)?)([eE][-+]?{DIGITS})?|0[xX](\.{HEX_DIGITS}|{HEX_DIGITS}(\.{HEX_DIGITS}?)?)[pP][-+]?{DIGITS})[fF](?!{ID_CHAR})'.format_map(globals()))
  50. # DOUBLE_REGEX = re.compile(r'(?<!{ID_CHAR})((\.{DIGITS}|{DIGITS}(\.{DIGITS}?|(?=[eEdD])))([eE][-+]?{DIGITS})?|0[xX](\.{HEX_DIGITS}|{HEX_DIGITS}(\.{HEX_DIGITS}?)?)[pP][-+]?{DIGITS})[dD]?(?!{ID_CHAR})'.format_map(globals()))
  51. EXPONENT = r'(?:[eE][-+]?{DIGITS})'.format_map(globals())
  52. HEX_EXPONENT = r'(?:[pP][-+]?{DIGITS})'.format_map(globals())
  53. NUMBER_OR_STR_REGEX = re.compile(r'''(?x)
  54. (["']) (\\ . | [^\\])*? \1
  55. |
  56. (?<!{ID_CHAR})
  57. ( \.{DIGITS}{EXPONENT}?[fFdD]?
  58. | {DIGITS} ( \.{DIGITS}?{EXPONENT}?[fFdD]?
  59. | {EXPONENT}[fFdD]?
  60. | [lLfFdD]?
  61. )
  62. | 0[xX] ( \.{HEX_DIGITS}{HEX_EXPONENT}[fFdD]?
  63. | {HEX_DIGITS} ( \.{HEX_DIGITS}?{HEX_EXPONENT}[fFdD]?
  64. | {HEX_EXPONENT}[fFdD]?
  65. | [lL]?
  66. )
  67. )
  68. | 0[bB] {BIN_DIGITS}[lL]?
  69. )
  70. (?!{ID_CHAR})
  71. '''.format_map(globals()))
  72. HEX_REGEX = re.compile(r'(?P<prefix>0[xX])(?P<ipart>{HEX_DIGITS})?((?P<decimal>\.)(?P<fpart>{HEX_DIGITS})?)?((?P<xind>[pP])(?P<xpart>[-+]?{DIGITS}))?(?P<suffix>[lLfFdD]?)'.format_map(globals()))
  73. DECIMAL_REGEX = re.compile(r'(?P<ipart>{DIGITS})?((?P<decimal>\.)(?P<fpart>{DIGITS})?)?((?P<xind>[eE])(?P<xpart>[-+]?{DIGITS}))?(?P<suffix>[lLfFdD]?)'.format_map(globals()))
  74. OCTAL_REGEX = re.compile(r'(?P<prefix>0)(?P<ipart>{OCT_DIGITS})(?P<suffix>[lL]?)'.format_map(globals()))
  75. BINARY_REGEX = re.compile(r'(?P<prefix>0[bB])(?P<ipart>{BIN_DIGITS})(?P<suffix>[lL]?)'.format_map(globals()))
  76. UNDERSCORE_REGEX = re.compile(r'_+')
  77. PREFIX_ZEROS = re.compile(r'^0+')
  78. POSTFIX_ZEROS = re.compile(r'0+$')
  79. ZEROS = re.compile(r'^0+$')
  80. # HEX_PREFIX_REGEX = re.compile(r'0[xX]')
  81. # P_REGEX = re.compile(r'[pP]')
  82. # NON_OCTAL_CHAR_REGEX = re.compile(r'[89.eEpPxXbBfFdD]')
  83. # BINARY_REGEX = re.compile(r'0[bB]')
  84. # for num in '1.2', '3', '165_200', '14E-20', '1E10', '7e+2', '0x3A', '0x3AL', '0x3A.p4', '0x3A.Fp-2F', '0x3D_2AF.42P+20':
  85. # assert NUMBER_REGEX.fullmatch(num), num
  86. # def isfloat(s: str, /) -> bool:
  87. # if HEX_REGEX.match(s) and not P_REGEX.search(s):
  88. # return False
  89. # return s[-1] in 'fF'
  90. # def isdouble(s: str, /) -> bool:
  91. # if HEX_REGEX.match(s) and not P_REGEX.search(s):
  92. # return False
  93. # if '.' in s:
  94. # return s[-1] not in 'fF'
  95. # return s[-1] in 'dD'
  96. # def islong(s: str, /) -> bool:
  97. # return s[-1] in 'lL'
  98. # def isoctal(s: str, /) -> bool:
  99. # return not NON_OCTAL_CHAR_REGEX.search(s)
  100. replace_count = 0
  101. def refactor(s: str) -> str:
  102. if s[0] in ('"', "'"):
  103. return s
  104. global replace_count
  105. if (m := HEX_REGEX.fullmatch(s)):
  106. result = reformat(
  107. prefix=m['prefix'],
  108. ipart=m['ipart'],
  109. decimal=m['decimal'],
  110. fpart=m['fpart'],
  111. xind=m['xind'],
  112. xpart=m['xpart'],
  113. suffix=m['suffix']
  114. )
  115. elif (m := OCTAL_REGEX.fullmatch(s)):
  116. result = reformat(
  117. prefix=m['prefix'],
  118. ipart=m['ipart'],
  119. suffix=m['suffix']
  120. )
  121. elif (m := BINARY_REGEX.fullmatch(s)):
  122. result = reformat(
  123. prefix=m['prefix'],
  124. ipart=m['ipart'],
  125. suffix=m['suffix']
  126. )
  127. elif (m := DECIMAL_REGEX.fullmatch(s)):
  128. result = reformat(
  129. ipart=m['ipart'],
  130. decimal=m['decimal'],
  131. fpart=m['fpart'],
  132. xind=m['xind'],
  133. xpart=m['xpart'],
  134. suffix=m['suffix']
  135. )
  136. else:
  137. assert False, f"Could not refactor {s!r}"
  138. if result != s:
  139. replace_count += 1
  140. return result
  141. LEFT = -1
  142. RIGHT = 1
  143. def create_fix_underscores(underscores: int, direction: LEFT|RIGHT=0):
  144. if underscores == ADD:
  145. if direction == LEFT:
  146. def fix_underscores(s: str) -> str:
  147. if not s: return ""
  148. for i in range(len(s) - 4, 0, -4):
  149. s = s[0:i] + '_' + s[i+1:]
  150. return s
  151. elif direction == RIGHT:
  152. def fix_underscores(s: str) -> str:
  153. if not s: return ""
  154. for i in range(3, len(s), 4):
  155. s = s[0:i] + '_' + s[i+1:]
  156. return s
  157. else:
  158. assert False, f"Invalid value for direction: {direction}"
  159. else:
  160. if underscores == KEEP:
  161. underscore_replacement = R"\0"
  162. elif underscores == REMOVE:
  163. underscore_replacement = ""
  164. elif underscores == TRUNC:
  165. underscore_replacement = "_"
  166. else:
  167. assert False, f"Invalid value for UNDERSCORES: {underscores}"
  168. def fix_underscores(s: str) -> str:
  169. if not s: return ""
  170. return UNDERSCORE_REGEX.sub(underscore_replacement, s)
  171. return fix_underscores
  172. fix_ipart_underscores = create_fix_underscores(IPART_UNDERSCORES, direction=LEFT)
  173. fix_fpart_underscores = create_fix_underscores(FPART_UNDERSCORES, direction=RIGHT)
  174. def reformat(*, prefix: str="", ipart: str="", decimal: str="", fpart: str="", xind: str="", xpart: str="", suffix: str="") -> str:
  175. prefix = prefix or ""
  176. ipart = fix_ipart_underscores(ipart)
  177. decimal = decimal or ""
  178. fpart = fix_fpart_underscores(fpart)
  179. xind = xind or ""
  180. xpart = xpart or ""
  181. suffix = suffix or ""
  182. assert ipart or fpart, "both ipart and xpart were empty"
  183. if fpart: assert decimal, "decimal was empty when fpart was not empty"
  184. if xind: assert xpart, "xpart was empty when xind was not empty"
  185. else: assert not xpart, "xind was empty when xpart was not empty"
  186. isdecimal = bool(decimal or fpart or xind or suffix and suffix in "fFdD")
  187. if isdecimal and not suffix and DOUBLE_TYPE_SUFFIX & ADD:
  188. if DOUBLE_TYPE_SUFFIX & LOWER:
  189. assert not DOUBLE_TYPE_SUFFIX & UPPER
  190. suffix = "d"
  191. else:
  192. suffix = "D"
  193. elif suffix:
  194. if suffix in "dD" and (DOUBLE_TYPE_SUFFIX == REMOVE or DOUBLE_TYPE_SUFFIX == REMOVE | ADD_IF_NEEDED and (ZERO_FPART != REMOVE or not ZEROS.fullmatch(fpart) or ZERO_IPART != REMOVE or not ZEROS.fullmatch(ipart))):
  195. suffix = ""
  196. elif suffix == "d" and DOUBLE_TYPE_SUFFIX.bit_length() <= 3 and DOUBLE_TYPE_SUFFIX & UPPER:
  197. suffix = "D"
  198. elif suffix == "D" and DOUBLE_TYPE_SUFFIX.bit_length() <= 3 and DOUBLE_TYPE_SUFFIX & LOWER:
  199. suffix = "d"
  200. elif suffix == "f" and FLOAT_TYPE_SUFFIX == UPPER:
  201. suffix = "F"
  202. elif suffix == "F" and FLOAT_TYPE_SUFFIX == LOWER:
  203. suffix = "f"
  204. elif suffix == "l" and LONG_TYPE_SUFFIX == UPPER:
  205. suffix = "L"
  206. elif suffix == "L" and LONG_TYPE_SUFFIX == LOWER:
  207. suffix = "l"
  208. if prefix:
  209. assert prefix[0] == "0" and len(prefix) <= 2
  210. if len(prefix) == 1: # octal literal
  211. if OCTAL_PREFIX == REMOVE:
  212. assert isdecimal == False
  213. return refactor(f"{int(ipart, base=8)}{suffix}")
  214. else:
  215. assert OCTAL_PREFIX == KEEP, OCTAL_PREFIX
  216. elif prefix[1] in "xX": # hex literal
  217. if HEX_PREFIX == REMOVE:
  218. if isdecimal:
  219. return refactor(f"{float.fromhex(f'0x{ipart}{decimal}{fpart}{xind}{xpart}')}{suffix}")
  220. else:
  221. return refactor(f"{int(ipart, base=16)}{suffix}")
  222. elif HEX_PREFIX == UPPER:
  223. prefix = prefix.upper()
  224. elif HEX_PREFIX == LOWER:
  225. prefix = prefix.lower()
  226. else:
  227. assert HEX_PREFIX == KEEP, HEX_PREFIX
  228. if HEX_LITERAL == UPPER:
  229. ipart = ipart.upper()
  230. fpart = fpart.upper()
  231. elif HEX_LITERAL == LOWER:
  232. ipart = ipart.lower()
  233. fpart = fpart.lower()
  234. else:
  235. assert HEX_LITERAL == KEEP, HEX_LITERAL
  236. if xind:
  237. if HEX_EXPONENT_INDICATOR == UPPER:
  238. xind = xind.upper()
  239. elif HEX_EXPONENT_INDICATOR == LOWER:
  240. xind = xind.lower()
  241. else:
  242. assert HEX_EXPONENT_INDICATOR == KEEP, HEX_EXPONENT_INDICATOR
  243. else: # binary literal
  244. assert prefix[1] in "bB"
  245. if BINARY_PREFIX == REMOVE:
  246. assert isdecimal == False
  247. return refactor(f"{int(ipart, base=2)}{suffix}")
  248. else:
  249. assert BINARY_PREFIX == KEEP, BINARY_PREFIX
  250. else: # decimal literal
  251. if xind:
  252. if EXPONENT_INDICATOR == UPPER:
  253. xind = xind.upper()
  254. elif EXPONENT_INDICATOR == LOWER:
  255. xind = xind.lower()
  256. else:
  257. assert EXPONENT_INDICATOR == KEEP, EXPONENT_INDICATOR
  258. if EXPONENT_SIGN == REMOVE and xpart[0] == '+':
  259. xpart = xpart[1:]
  260. elif EXPONENT_SIGN == ADD and xpart[0] not in "+-":
  261. xpart = "+" + xpart
  262. else:
  263. assert EXPONENT_SIGN == KEEP, EXPONENT_SIGN
  264. if isdecimal:
  265. if not fpart and ZERO_FPART & ADD:
  266. fpart = "0"
  267. elif len(fpart) > 1 and fpart[-1] == "0" and ZERO_FPART & TRUNC:
  268. fpart = fpart[:POSTFIX_ZEROS.search(fpart).start()] or "0"
  269. elif ZERO_FPART == REMOVE and ZEROS.fullmatch(fpart):
  270. fpart = ""
  271. if not ipart and ZERO_IPART & ADD:
  272. ipart = "0"
  273. if not fpart and suffix in "dD" and DOUBLE_TYPE_SUFFIX == REMOVE | ADD_IF_NEEDED:
  274. decimal = ""
  275. elif len(ipart) > 1 and ipart[0] == "0" and ZERO_IPART & TRUNC:
  276. ipart = ipart[PREFIX_ZEROS.search(ipart).end():] or "0"
  277. elif ZERO_IPART == REMOVE and ZEROS.fullmatch(ipart):
  278. ipart = ""
  279. if not ipart and not fpart:
  280. if suffix and DOUBLE_TYPE_SUFFIX == REMOVE | ADD_IF_NEEDED:
  281. ipart = "0"
  282. decimal = ""
  283. else:
  284. fpart = "0"
  285. if not suffix or xind: decimal = "."
  286. elif ipart and fpart:
  287. decimal = "."
  288. return f"{prefix}{ipart}{decimal}{fpart}{xind}{xpart}{suffix}"
  289. def replacer(match: re.Match) -> str:
  290. return refactor(match[0])
  291. if __name__ == "__main__":
  292. for filename in glob(R'src\main\java\com\**\*.java', recursive=True):
  293. with open(filename, 'r') as file:
  294. text = file.read()
  295. replace_count = 0
  296. # start = 0
  297. # i = 0
  298. # while i < len(text):
  299. # if text[i] in ('"', "'"):
  300. # if i > start:
  301. # text = text[0:start] + NUMBER_REGEX.sub(replacer, text[start:i]) + text[i+1:]
  302. # start = None
  303. # ch = text[i]
  304. # escape = False
  305. # i += 1
  306. # while i < len(text):
  307. # if escape:
  308. # escape = False
  309. # elif text[i] == ch:
  310. # start = i + 1
  311. # break
  312. # elif text[i] == '\\':
  313. # escape = True
  314. # i += 1
  315. new_text = NUMBER_OR_STR_REGEX.sub(replacer, text)
  316. if replace_count > 0:
  317. # with open(filename + '.backup', 'w') as file:
  318. # file.write(text)
  319. with open(filename, 'w') as file:
  320. file.write(new_text)
  321. print(f"Replaced {replace_count} occurrence(s) in {filename}")
  322. # break