sccdc.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import argparse
  2. import os
  3. import sys
  4. from sccd.compiler.generic_generator import GenericGenerator, Platforms
  5. from sccd.compiler.DEVS_generator import DEVSGenerator
  6. from sccd.compiler.utils import Enum, Logger, FileWriter
  7. from sccd.compiler.super_class_linker import SuperClassLinker
  8. from sccd.compiler.state_linker import StateLinker
  9. from sccd.compiler.path_calculator import PathCalculator
  10. from sccd.compiler.sccd_constructs import ClassDiagram
  11. from sccd.compiler.generic_language_constructs import GenericConstruct
  12. from sccd.compiler.compiler_exceptions import CompilerException
  13. from sccd.compiler.javascript_writer import JavascriptWriter
  14. from sccd.compiler.python_writer import PythonWriter
  15. def generate(input_file, output_file, target_language, platform):
  16. sccd = xmlToSccd(input_file)
  17. if not target_language:
  18. if sccd.language:
  19. target_language = sccd.language
  20. else:
  21. target_language = "python" # default
  22. elif sccd.language and target_language != sccd.language:
  23. Logger.showError("Diagram specifies target language as \"" + sccd.language + "\", but language option of compiler has been set to \"" + target_language + "\". No output has been generated.")
  24. return
  25. if target_language == "python" and not output_file.endswith(".py") :
  26. output_file += ".py"
  27. elif target_language == "javascript" and not output_file.endswith(".js") :
  28. output_file += ".js"
  29. if platform == 3:
  30. generic = sccdToDEVS(sccd, platform)
  31. else:
  32. generic = sccdToGeneric(sccd, platform)
  33. genericToTarget(generic, target_language, output_file)
  34. def xmlToSccd(xml_file):
  35. cd = ClassDiagram(xml_file) # create AST
  36. cd.accept(SuperClassLinker())
  37. # SuperClassLinker().visit(cd) # visitor linking super classs references
  38. StateLinker().visit(cd) # visitor fixing state references
  39. PathCalculator().visit(cd) # visitor calculating paths
  40. return cd
  41. def sccdToGeneric(sccd, platform):
  42. succesfull_generation = False
  43. generator = GenericGenerator(platform)
  44. sccd.accept(generator)
  45. generic = generator.get()
  46. Logger.showInfo("Classes <" + ", ".join(sccd.class_names) + "> have been converted to generic language constructs.")
  47. return generic
  48. def sccdToDEVS(sccd, platform):
  49. succesfull_generation = False
  50. generator = DEVSGenerator(platform)
  51. sccd.accept(generator)
  52. generic = generator.get()
  53. Logger.showInfo("Classes <" + ", ".join(sccd.class_names) + "> have been converted to generic DEVS constructs.")
  54. return generic
  55. def genericToTarget(generic, target_language, output_file):
  56. try:
  57. f = FileWriter(output_file)
  58. if target_language == "javascript":
  59. writer = JavascriptWriter(f)
  60. elif target_language == "python":
  61. writer = PythonWriter(f)
  62. else:
  63. raise Exception("Language not supported")
  64. generic.accept(writer)
  65. Logger.showInfo("Generic language constructs have been converted to target language constructs and have been written to file '" + output_file + "'.")
  66. finally:
  67. f.close()
  68. def main():
  69. parser = argparse.ArgumentParser(prog="python -m sccd.compiler.sccdc")
  70. parser.add_argument('input', help='The path to the XML file to be compiled.')
  71. parser.add_argument('-o', '--output', type=str, help='The path to the generated code. Defaults to the same name as the input file but with matching extension.')
  72. parser.add_argument('-v', '--verbose', type=int, help='2 = all output; 1 = only warnings and errors; 0 = only errors; -1 = no output. Defaults to 2.', default = 2)
  73. parser.add_argument('-p', '--platform', type=str, help="Let the compiled code run on top of threads, gameloop or eventloop. The default is eventloop.")
  74. parser.add_argument('-l', '--language', type=str, help='Target language, either "javascript" or "python". Defaults to the latter.')
  75. args = vars(parser.parse_args())
  76. #Set verbose
  77. if args['verbose'] is not None:
  78. if args['verbose'] in [-1, 0,1,2] :
  79. Logger.verbose = args['verbose']
  80. else :
  81. Logger.showError("Invalid verbose argument.")
  82. else :
  83. Logger.verbose = 2
  84. #Set source file
  85. source = args['input']
  86. if not source.endswith(".xml") :
  87. Logger.showError("Input file not valid.")
  88. return
  89. #Set target language
  90. if args['language'] :
  91. target_language = args['language']
  92. else :
  93. target_language = ""
  94. #Set output file
  95. if args['output'] :
  96. output = args['output']
  97. else:
  98. output = os.path.splitext(os.path.split(source)[1])[0]
  99. #Set platform
  100. if args['platform'] :
  101. args['platform'] = args['platform'].lower()
  102. if args['platform'] == "threads" :
  103. platform = Platforms.Threads
  104. elif args['platform'] == "gameloop" :
  105. platform = Platforms.GameLoop
  106. elif args['platform'] == "eventloop" :
  107. platform = Platforms.EventLoop
  108. elif args['platform'] == "classicdevs":
  109. if target_language == "" or target_language == "python":
  110. platform = Platforms.classicDEVS
  111. else:
  112. Logger.showError("DEVS currently only supports python.")
  113. else :
  114. Logger.showError("Invalid platform.")
  115. return
  116. else :
  117. platform = Platforms.EventLoop
  118. #Compile
  119. try :
  120. generate(source, output, target_language, platform)
  121. except CompilerException as exception :
  122. Logger.showError(str(exception));
  123. return 1
  124. return 0
  125. if __name__ == "__main__":
  126. sys.exit(main())