ANTLR4的 TokenStreamRewriter.getText() 在自定义DOCTYPE解析规则中丢失空格

编程语言 2026-07-10

我在使用ANTLR4解析XML文件,然后使用 TokenStreamRewriter.getText() 输出解析后的内容。
对于普通XML标签(例如 <foo><gm-A-1/>),输出是正确的:空格和换行被保留。

然而,对于我新增的自定义DOCTYPE解析规则,输出 丢失了所有空格,即使原始XML包含空格和换行。

预期行为:
我希望DOCTYPE输出能够保留原始格式,包括空格和换行,如下所示:

<!DOCTYPE doc [
    <!ENTITY e0 ''>
    <!ENTITY e1 '&e0;'>
]>

实际行为:
TokenStreamRewriter.getText() 产生的输出看起来像这样:

<!DOCTYPEdoc[<!ENTITYe0''><!ENTITYe1'&e0;'>]>

所有空格都被移除,所有内容被拼接在一起。

使用的解析规则:

dtd :
    DOCTYPE_OPEN Name LBRACK misc* entityDecl* RBRACK CLOSE misc* entityRef?
;

entityDecl
    : ENTITY_OPEN Name STRING misc* CLOSE
;

entityRef
    : '<' Name '>' EntityRef '<' '/' Name '>'
;

问题描述:
我怀疑这个问题来自词法层TokenStreamRewriter.getText() 只是把 token.text 拼接在一起,因此如果词法分析器跳过了空白符,它们就不会出现在输出中。

我想知道:

  1. 如何修改ANTLR4的词法和/或语法规则,使DOCTYPE的输出保留空格?
  2. 是否有推荐的方法,确保 TokenStreamRewriter.getText() 的输出文本几乎与原始XML相同?

我尝试过的:

  • 手动在访问者中添加空格可以实现,但很繁琐。
  • 即使使用 rewriter.getText(ctx.start, ctx.stop),在空白符被跳过时也没有帮助。

解决方案

我查看了 .g4 文件,发现了一个 INSIDE 模式。在其中,空白符被跳过(S : [ \t\r\n] -> skip;),因此所有内容被视为一个连续的流。这就是一切都挤在一起的原因。等待48小时后我将接受这个答案并关闭问题。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章