_build_latex_antlr.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import os
  2. import subprocess
  3. import glob
  4. from sympy.utilities.misc import debug
  5. here = os.path.dirname(__file__)
  6. grammar_file = os.path.abspath(os.path.join(here, "LaTeX.g4"))
  7. dir_latex_antlr = os.path.join(here, "_antlr")
  8. header = '''\
  9. # *** GENERATED BY `setup.py antlr`, DO NOT EDIT BY HAND ***
  10. #
  11. # Generated from ../LaTeX.g4, derived from latex2sympy
  12. # latex2sympy is licensed under the MIT license
  13. # https://github.com/augustt198/latex2sympy/blob/master/LICENSE.txt
  14. #
  15. # Generated with antlr4
  16. # antlr4 is licensed under the BSD-3-Clause License
  17. # https://github.com/antlr/antlr4/blob/master/LICENSE.txt
  18. '''
  19. def check_antlr_version():
  20. debug("Checking antlr4 version...")
  21. try:
  22. debug(subprocess.check_output(["antlr4"])
  23. .decode('utf-8').split("\n")[0])
  24. return True
  25. except (subprocess.CalledProcessError, FileNotFoundError):
  26. debug("The 'antlr4' command line tool is not installed, "
  27. "or not on your PATH.\n"
  28. "> Please refer to the README.md file for more information.")
  29. return False
  30. def build_parser(output_dir=dir_latex_antlr):
  31. check_antlr_version()
  32. debug("Updating ANTLR-generated code in {}".format(output_dir))
  33. if not os.path.exists(output_dir):
  34. os.makedirs(output_dir)
  35. with open(os.path.join(output_dir, "__init__.py"), "w+") as fp:
  36. fp.write(header)
  37. args = [
  38. "antlr4",
  39. grammar_file,
  40. "-o", output_dir,
  41. # for now, not generating these as latex2sympy did not use them
  42. "-no-visitor",
  43. "-no-listener",
  44. ]
  45. debug("Running code generation...\n\t$ {}".format(" ".join(args)))
  46. subprocess.check_output(args, cwd=output_dir)
  47. debug("Applying headers, removing unnecessary files and renaming...")
  48. # Handle case insensitive file systems. If the files are already
  49. # generated, they will be written to latex* but LaTeX*.* won't match them.
  50. for path in (glob.glob(os.path.join(output_dir, "LaTeX*.*")) or
  51. glob.glob(os.path.join(output_dir, "latex*.*"))):
  52. # Remove files ending in .interp or .tokens as they are not needed.
  53. if not path.endswith(".py"):
  54. os.unlink(path)
  55. continue
  56. new_path = os.path.join(output_dir, os.path.basename(path).lower())
  57. with open(path, 'r') as f:
  58. lines = [line.rstrip() + '\n' for line in f.readlines()]
  59. os.unlink(path)
  60. with open(new_path, "w") as out_file:
  61. offset = 0
  62. while lines[offset].startswith('#'):
  63. offset += 1
  64. out_file.write(header)
  65. out_file.writelines(lines[offset:])
  66. debug("\t{}".format(new_path))
  67. return True
  68. if __name__ == "__main__":
  69. build_parser()