我发现有C# antlr4语法。我为该语法为C#构建了antlr4解析器。它起作用了。我可以遍历解析树,并看到有一些节点具有一些子节点。
现在,我想从这个解析树重新生成C#源代码。
我能以某种方式生成(语法之外的) antlr解析器的逆解析器,而不是解析,当给定解析树时,它将生成导致该解析树的源代码?
编辑:
我目前在CoffeeScript中的尝试是遍历源代码树,使用原始源代码和antlr放在节点中的开始和停止位置来装饰它,然后再次遍历它以打印源代码。唯一的问题是多个节点在源代码中从完全相同的空格开始。为了解决这个问题,我有一些讨厌的逻辑,只将源代码放在最深层的节点中:
antlr = require 'antlr4'
{CSharp4Parser} = require './CSharp4Parser'
{CSharp4Lexer} = require './CSharp4Lexer'
input = "namespace A { class B {}; class C {} }"
cstream = new antlr.InputStream(input)
lexer = new CSharp4Lexer(cstream)
tstream = new antlr.CommonTokenStream(lexer)
parser = new CSharp4Parser(tstream)
parser.buildParseTrees = true ;
tree = parser.compilation_unit();
decorateWithSource = new antlr.tree.ParseTreeListener();
start =
prev: null
stop =
prev: null
o = (msg) -> process.stdout.write(msg)
decorateWithSource.enterEveryRule = (a) ->
if start.prev
start.prev.before = input.substr(start.prev.start.start, a.start.start - start.prev.start.start)
if stop.prev
stop.prev.after = input.substr(stop.prev.stop.start, a.start.start - stop.prev.stop.start)
start.prev = a
stop.prev = null
decorateWithSource.exitEveryRule = (a) ->
if start.prev
start.prev.before = input.substr(start.prev.start.start, a.stop.start - start.prev.start.start)
if stop.prev
stop.prev.after = input.substr(stop.prev.stop.start, a.stop.start - stop.prev.stop.start)
start.prev = null
stop.prev = a
walker = new antlr.tree.ParseTreeWalker();
walker.walk(decorateWithSource, tree);
stop.prev.after = input.substr(stop.prev.stop.start)
printOut = new antlr.tree.ParseTreeListener();
printOut.enterEveryRule = (a) ->
o (a.before || ''), ' -> '+parser.ruleNames[a.ruleIndex]
printOut.exitEveryRule = (a) ->
o (a.after || ''), ' < '+parser.ruleNames[a.ruleIndex]
walker.walk(printOut, tree);我尝试做的是将C#源文件(来自重新编译的错误代码)读入树中,然后通过用OMeta编写的转换器传递它(这会将我的环境缩小到具有OMeta实现的语言,如C#、js或coffeescript,可能还有其他语言),然后写回修复后的源代码。
也许手动遍历解析树来生成代码对我来说已经足够好了。
发布于 2015-05-15 23:34:55
这并不容易;ANTLR实际上并不是为此而设计的。
您可以研究StringTemplates,它可以让您遍历整个树并输出大致正确的代码。
如果你想重新生成细节良好的源代码,这是不够的。请看我在How to build a prettyprinter上的回答。
https://stackoverflow.com/questions/30261095
复制相似问题