处理antlr 3中的隐藏通道

处理antlr 3中的隐藏通道,antlr,hidden,channel,Antlr,Hidden,Channel,我正在写一个ANTR语法,用于将一种语言翻译成另一种语言,但是关于使用隐藏通道的文档非常稀少。我到处找不到一个例子。我唯一发现的是www.antlr.org上的FAQ,它告诉你如何访问隐藏频道,但不是如何最好地使用此功能。目标语言是Java 在我的语法文件中,我传递空格和注释,如下所示: // Send runs of space and tab characters to the hidden channel. WHITESPACE : (SPACE | TAB)

我正在写一个ANTR语法,用于将一种语言翻译成另一种语言,但是关于使用隐藏通道的文档非常稀少。我到处找不到一个例子。我唯一发现的是www.antlr.org上的FAQ,它告诉你如何访问隐藏频道,但不是如何最好地使用此功能。目标语言是Java

在我的语法文件中,我传递空格和注释,如下所示:

// Send runs of space and tab characters to the hidden channel.        
WHITESPACE 
    :   (SPACE | TAB)+ { $channel = HIDDEN; }
    ;

// Single-line comments begin with --
SINGLE_COMMENT 
    :    ('--' COMMENT_CHARS NEWLINE) {
            $channel=HIDDEN;
        }
    ;

fragment COMMENT_CHARS 
    :   ~('\r' | '\n')*
    ;

// Treat runs of newline characters as a single NEWLINE token.
NEWLINE 
    :   ('\r'? '\n')+ { $channel = HIDDEN; }
    ;
在我的成员部分中,我定义了一种将隐藏通道标记写入输出StringStream的方法

@members {

private int savedIndex = 0;

void ProcessHiddenChannel(TokenStream input) {      
    List<Token> tokens = ((CommonTokenStream)input).getTokens(savedIndex, input.index());
    for(Token token: tokens) {
        if(token.getChannel() == token.HIDDEN_CHANNEL) {
            output.append(token.getText());

        }
    }
    savedIndex = input.index();
}
}
肯定有更好的办法吗

编辑:这是输入语言的一个示例:

-- -----------------------------------------------------------------
--
--
--  Name                Description
--  ==================================
--  IFM1/183         Freq Spectrum Inversion
--                     
-- -----------------------------------------------------------------

PROCEDURE IFM1/183

TITLE "Freq Spectrum Inversion";

HELP
      Freq Spectrum Inversion

ENDHELP;

PRIVILEGE CTRL;

WINDOW MANDATORY;

INPUT

   $Input : @NO_YES
   DEFAULT select %YES when /IFMS1/183.VALUE = %NO;
                  %NO otherwise
           endselect
   PROMPT "Spec Inv";

   $Forced_Cmd : BOOLEAN
   Default FALSE
   Prompt  "Forced Commanding";

DEFINE
   &RetCode   : @PSTATUS := %OK;
   &msg       : STRING;
   &Input     : BOOLEAN;

REQUIRE AVAILABLE(/IFMS1)
        MSG "IFMS1 not available";

REQUIRE /IFMS1/001.VALUE = %MON_AND_CTRL
        MSG "IFMS1 not in control mode";

BEGIN  -- Procedure Body --

    &msg := "IFMS1/183 -> " + toString($Input) + " : "; 

-- pre-check

   IF /IFMS1/183.VALUE = $Input
      AND $Forced_Cmd = FALSE THEN
      EXIT (%OK, MSG &msg + "already set");
   ENDIF;

-- command

   IF $Input =  %YES THEN &Input:= TRUE;
    ELSE  &Input:= FALSE;
   ENDIF;

   SET &RetCode := SEND IFMS1.FREQPLAN
        ( $FreqSpecInv := &Input);
   IF &RetCode <> %OK THEN
      EXIT (&RetCode, MSG &msg + "command failed");
   ENDIF;

-- verify

   SET &RetCode := VERIFY /IFMS1/183.VALUE = $Input TIMEOUT '10';
   IF &RetCode <> %OK THEN
      EXIT (&RetCode, MSG &msg + "verification failed");
   ELSE
      EXIT (&RetCode, MSG &msg + "verified");
   ENDIF;

END

研究继承CommonTokenStream并将子类的一个实例提供给ANTLR。从您给出的代码示例中,我怀疑您可能有兴趣查看版本3中可用的过滤器和重写选项


另外,看看另一个。

我刚刚讨论了我的一些老问题,认为用最有效的最终解决方案来回答是值得的。最后,翻译语言的最佳方法是使用StringTemplate。这将为您重新缩进输出。在ANTLR示例包中有一个非常好的例子叫做“cminus”,它展示了如何使用它。

你能发布一个你正在翻译的语言的例子吗?还有这个翻译的最终结果ANTLR参考书展示了重写模式的例子-选项{rewrite=true;}-以及CommonTokenStream的子类TokenRewriteStream。我没有用过这些,但它们可能很有趣。顺便说一句,我是ANTLR的粉丝,你可能想看看介绍。@Bart:我不知道为什么语言的细节很重要。但输入语言是一种称为STL的定制语言,欧洲航天局使用该语言控制地面站设备。请参阅下面的代码。目标语言是Javascript,在Rhino引擎中运行一些定制。大部分语言转换已完成,但我希望保留注释。“大约有3000个这样的脚本。@安迪和格伦。谢谢你的信息。我将阅读一些关于重写和这个CommonTokenStream的文章。看来评论有限,所以我在原始问题中添加了示例。
-- -----------------------------------------------------------------
--
--
--  Name                Description
--  ==================================
--  IFM1/183         Freq Spectrum Inversion
--                     
-- -----------------------------------------------------------------

PROCEDURE IFM1/183

TITLE "Freq Spectrum Inversion";

HELP
      Freq Spectrum Inversion

ENDHELP;

PRIVILEGE CTRL;

WINDOW MANDATORY;

INPUT

   $Input : @NO_YES
   DEFAULT select %YES when /IFMS1/183.VALUE = %NO;
                  %NO otherwise
           endselect
   PROMPT "Spec Inv";

   $Forced_Cmd : BOOLEAN
   Default FALSE
   Prompt  "Forced Commanding";

DEFINE
   &RetCode   : @PSTATUS := %OK;
   &msg       : STRING;
   &Input     : BOOLEAN;

REQUIRE AVAILABLE(/IFMS1)
        MSG "IFMS1 not available";

REQUIRE /IFMS1/001.VALUE = %MON_AND_CTRL
        MSG "IFMS1 not in control mode";

BEGIN  -- Procedure Body --

    &msg := "IFMS1/183 -> " + toString($Input) + " : "; 

-- pre-check

   IF /IFMS1/183.VALUE = $Input
      AND $Forced_Cmd = FALSE THEN
      EXIT (%OK, MSG &msg + "already set");
   ENDIF;

-- command

   IF $Input =  %YES THEN &Input:= TRUE;
    ELSE  &Input:= FALSE;
   ENDIF;

   SET &RetCode := SEND IFMS1.FREQPLAN
        ( $FreqSpecInv := &Input);
   IF &RetCode <> %OK THEN
      EXIT (&RetCode, MSG &msg + "command failed");
   ENDIF;

-- verify

   SET &RetCode := VERIFY /IFMS1/183.VALUE = $Input TIMEOUT '10';
   IF &RetCode <> %OK THEN
      EXIT (&RetCode, MSG &msg + "verification failed");
   ELSE
      EXIT (&RetCode, MSG &msg + "verified");
   ENDIF;

END