在Antlr4中使用文本属性时如何保留空白

在Antlr4中使用文本属性时如何保留空白,antlr,antlr4,Antlr,Antlr4,当我调用token的text属性时,我想保留空白,有什么办法吗? 情况如下: 我们有以下代码 IF L > 40 THEN; ELSE IF A = 20 THEN PUT "HELLO"; 在这种情况下,我想将其转换为: if (!(L>40){ if (A=20) put "hello"; } Antlr中的规则是: stmt_if_block: IF expr THEN x=stmt

当我调用token的text属性时,我想保留空白,有什么办法吗? 情况如下: 我们有以下代码

IF L > 40 THEN;

ELSE

  IF A = 20 THEN
      PUT "HELLO";
在这种情况下,我想将其转换为:

if (!(L>40){

      if (A=20)
          put "hello";
}
Antlr中的规则是:

stmt_if_block: IF expr
               THEN x=stmt
               (ELSE y=stmt)?
               {
                 if ($x.text.equalsIgnoreCase(";"))
                 {
                   WriteLn("if(!(" + $expr.text +")){");
                   WriteLn($stmt.text);
                   Writeln("}");
                 }
               }
但结果似乎是:

if(!(L>40))
{
   ifA=20put"hello";
}
原因是,
$stmt
中的空白已被删除。我想知道是否有办法保留这些空白
多谢各位

更新:如果我添加

SPACE: [ ] -> channel(HIDDEN);
空间将被保留,结果如下所示,令牌之间有许多空格:

 IF SUBSTR(WNAME3,M-1,1) = ')'             THEN                                        M = L;                                  ELSE                                        M = L - 1;
这就是我用于此目的的C#扩展方法:

公共静态字符串GetFullText(此ParserRuleContext上下文)
{
if(context.Start==null | | | context.Stop==null | | | context.Start.StartIndex<0 | | context.Stop.StopIndex<0)
返回context.GetText();//回退
返回context.Start.InputStream.GetText(Interval.Of(context.Start.StartIndex,context.Stop.StopIndex));
}
因为您使用的是java,所以必须对其进行翻译,但它应该很简单——API是一样的

说明:获取第一个令牌,获取最后一个令牌,并从输入流中获取第一个令牌的第一个字符和最后一个令牌的最后一个字符之间的文本。

@Lucas,但在java中,如果您在翻译时遇到问题:

私有字符串getFullText(ParserRuleContext上下文){
if(context.start==null | | | context.stop==null | | context.start.getStartIndex()<0 | | context.stop.getStopIndex()<0)
返回context.getText();
返回context.start.getInputStream().getText(Interval.of(context.start.getStartIndex(),context.stop.getStopIndex());
}

看起来
InputStream
removeLastChild
/
addChild
操作之后并不总是更新。这个解决方案在一种语法上帮助了我,但在另一种语法上却不起作用

为……工作

不适用于modern(出于某些原因,inputStream.getText包含旧文本)

我正在尝试实现函数名替换,如下所示:

enterPostfixExpression(ctx: PostfixExpressionContext) {
   // Get identifierContext from ctx
   ...
   const token = CommonTokenFactory.DEFAULT.createSimple(GroovyParser.Identifier, 'someNewFnName');
   const node = new TerminalNode(token);
   identifierContext.removeLastChild();
   identifierContext.addChild(node);

UPD:我在第一个实现中使用了访问者模式

谢谢你,Lucas,但它没有帮助。所以现在我使用SPACE:[]->channel(隐藏);然后执行修剪文本。您正在尝试使用纯字符串黑客技术在语言之间进行动态(完全本地)代码翻译(这是您的PL/1到Java的示例)。您可能会生成工作结果,但这将是糟糕的代码,因为它没有考虑程序其他部分的上下文。(在您的特殊情况下,它完全无法翻译PL/1 PUT子句;这是动态生成器所遇到的典型问题)。忽略大问题,处理间距问题的一种方法是不尝试在翻译的程序中保留原始程序的间距;没有充分的理由相信这些是兼容的,更不用说会产生可读的结果了。您最好将(PL/1)AST转换为(Java)AST,然后使用适合目标的间距预打印结果。看,我知道这是旧的,但我登录此更新投票。非常感谢你。