g4.lua 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. -- Usage
  2. --[[
  3. add_requires("antlr4", "antlr4-runtime")
  4. set_languages("c++17")
  5. set_exceptions("cxx")
  6. target("test")
  7. set_kind("object")
  8. add_files("src/*.g4")
  9. add_rules("@antlr4/g4")
  10. add_packages("antlr4", "antlr4-runtime")
  11. --]]
  12. rule("g4")
  13. set_extensions(".g4")
  14. add_deps("@find_antlr4")
  15. if xmake.version():ge("3.0.0") then
  16. on_prepare_files(function (target, jobgraph, sourcebatch, opt)
  17. import("core.project.depend")
  18. import("utils.progress")
  19. local group_name = path.join(target:fullname(), "generate/g4")
  20. local autogendir = path.join(target:autogendir(), "rules/antlr4")
  21. jobgraph:group(group_name, function()
  22. for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
  23. local jave_job = path.join(group_name, sourcefile)
  24. local sourcefile_dir = path.normalize(path.join(autogendir, path.directory(sourcefile)))
  25. target:add("includedirs", sourcefile_dir, {public = true})
  26. os.mkdir(sourcefile_dir)
  27. jobgraph:add(jave_job, function (index, total, opt)
  28. local java = target:data("antlr4.tool")
  29. local argv = target:data("antlr4.tool.argv")
  30. table.join2(argv, target:values("antlr4.flags"))
  31. local fileconfig = target:fileconfig(sourcefile)
  32. if fileconfig then
  33. table.insert(argv, (fileconfig.visitor and "-visitor" or "-no-visitor"))
  34. table.insert(argv, (fileconfig.listener and "-listener" or "-no-listener"))
  35. end
  36. table.insert(argv, "-o")
  37. table.insert(argv, autogendir)
  38. table.insert(argv, "-lib")
  39. table.insert(argv, sourcefile_dir)
  40. table.insert(argv, sourcefile)
  41. depend.on_changed(function()
  42. progress.show(opt.progress or 0, "${color.build.object}compiling.g4 %s", sourcefile)
  43. os.vrunv(java.program, argv)
  44. end, {
  45. files = sourcefile,
  46. dependfile = target:dependfile(sourcefile),
  47. changed = target:is_rebuilt()
  48. })
  49. end)
  50. end
  51. end)
  52. end, {jobgraph = true})
  53. on_build_files(function (target, jobgraph, sourcebatch, opt)
  54. for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
  55. local group_name = path.join(target:fullname(), "obj", sourcefile)
  56. local sourcefile_dir = path.normalize(path.join(target:autogendir(), "rules/antlr4", path.directory(sourcefile)))
  57. jobgraph:group(group_name, function()
  58. local batchcxx = {
  59. rulename = "c++.build",
  60. sourcekind = "cxx",
  61. sourcefiles = {},
  62. objectfiles = {},
  63. dependfiles = {}
  64. }
  65. -- g4 file have 3 case
  66. -- lexer grammar LuaLexer;
  67. -- parser grammar LuaParser;
  68. -- grammar C;
  69. local sourcefile_string = io.readfile(sourcefile)
  70. local lexer_name = sourcefile_string:match("lexer grammar (%w+);")
  71. local parser_name = sourcefile_string:match("parser grammar (%w+);")
  72. -- lexer and parser same name
  73. local grammar_name = sourcefile_string:match("grammar (%w+);")
  74. if lexer_name or parser_name then
  75. if lexer_name then
  76. table.insert(batchcxx.sourcefiles, path.join(sourcefile_dir, lexer_name .. ".cpp"))
  77. end
  78. if parser_name then
  79. table.insert(batchcxx.sourcefiles, path.join(sourcefile_dir, parser_name .. ".cpp"))
  80. end
  81. elseif grammar_name then
  82. table.insert(batchcxx.sourcefiles, path.join(sourcefile_dir, grammar_name .. "Parser.cpp"))
  83. table.insert(batchcxx.sourcefiles, path.join(sourcefile_dir, grammar_name .. "Lexer.cpp"))
  84. end
  85. for _, sourcefile in ipairs(batchcxx.sourcefiles) do
  86. local objectfile = target:objectfile(sourcefile)
  87. local dependfile = target:dependfile(objectfile)
  88. table.insert(target:objectfiles(), objectfile)
  89. table.insert(batchcxx.objectfiles, objectfile)
  90. table.insert(batchcxx.dependfiles, dependfile)
  91. end
  92. import("private.action.build.object")(target, jobgraph, batchcxx, opt)
  93. end)
  94. end
  95. end, {jobgraph = true, distcc = true})
  96. else
  97. on_config(function (target)
  98. local includedirs = {}
  99. local autogendir = path.join(target:autogendir(), "rules/antlr4")
  100. for _, sourcebatch in pairs(target:sourcebatches()) do
  101. if sourcebatch.rulename == "@antlr4/g4" then
  102. for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
  103. table.insert(includedirs, path.normalize(path.join(autogendir, path.directory(sourcefile))))
  104. end
  105. break
  106. end
  107. end
  108. target:add("includedirs", table.unique(includedirs), {public = true})
  109. end)
  110. before_buildcmd_file(function (target, batchcmds, sourcefile_g4, opt)
  111. local autogendir = path.join(target:autogendir(), "rules/antlr4")
  112. local sourcefile_dir = path.normalize(path.join(autogendir, path.directory(sourcefile_g4)))
  113. batchcmds:mkdir(sourcefile_dir)
  114. local java = target:data("antlr4.tool")
  115. local argv = target:data("antlr4.tool.argv")
  116. table.join2(argv, target:values("antlr4.flags"))
  117. local fileconfig = target:fileconfig(sourcefile_g4)
  118. if fileconfig then
  119. table.insert(argv, (fileconfig.visitor and "-visitor" or "-no-visitor"))
  120. table.insert(argv, (fileconfig.listener and "-listener" or "-no-listener"))
  121. end
  122. table.insert(argv, "-o")
  123. table.insert(argv, autogendir)
  124. table.insert(argv, "-lib")
  125. table.insert(argv, sourcefile_dir)
  126. table.insert(argv, path(sourcefile_g4))
  127. batchcmds:show_progress(opt.progress, "${color.build.object}compiling.g4 %s", sourcefile_g4)
  128. batchcmds:vrunv(java.program, argv)
  129. local _build = function (sourcefile_cxx)
  130. local objectfile = target:objectfile(sourcefile_cxx)
  131. table.insert(target:objectfiles(), objectfile)
  132. batchcmds:show_progress(opt.progress, "${color.build.object}compiling.$(mode) %s", sourcefile_cxx)
  133. batchcmds:compile(sourcefile_cxx, objectfile)
  134. batchcmds:add_depfiles(sourcefile_g4)
  135. batchcmds:set_depmtime(os.mtime(objectfile))
  136. batchcmds:set_depcache(target:dependfile(objectfile))
  137. end
  138. -- g4 file have 3 case
  139. -- lexer grammar LuaLexer;
  140. -- parser grammar LuaParser;
  141. -- grammar C;
  142. local g4_string = io.readfile(sourcefile_g4)
  143. local lexer_name = g4_string:match("lexer grammar (%w+);")
  144. local parser_name = g4_string:match("parser grammar (%w+);")
  145. -- lexer and parser same name
  146. local grammar_name = g4_string:match("grammar (%w+);")
  147. if lexer_name or parser_name then
  148. if lexer_name then
  149. _build(path.join(sourcefile_dir, lexer_name .. ".cpp"))
  150. end
  151. if parser_name then
  152. _build(path.join(sourcefile_dir, parser_name .. ".cpp"))
  153. end
  154. elseif grammar_name then
  155. _build(path.join(sourcefile_dir, grammar_name .. "Lexer.cpp"))
  156. _build(path.join(sourcefile_dir, grammar_name .. "Parser.cpp"))
  157. end
  158. end)
  159. end