3

我正在编写用于将一种语言翻译成另一种语言的 ANTRL 语法,但有关使用 HIDDEN 频道的文档非常稀缺。我在任何地方都找不到一个例子。我发现的唯一内容是 www.antlr.org 上的常见问题解答,它告诉您如何访问隐藏频道,但没有告诉您如何最好地使用此功能。目标语言是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();
}
}

现在要使用它,我必须在语法中的每个标记之后调用该方法。

myParserRule
        :       MYTOKEN1 { ProcessHiddenChannel(input); }
                MYTOKEN2 { ProcessHiddenChannel(input); }
        ;

肯定有更好的方法吗?

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

-- -----------------------------------------------------------------
--
--
--  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
4

2 回答 2

0

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

另外,看看这个其他相关的堆栈溢出问题

于 2010-11-20T19:17:51.007 回答
0

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

于 2011-08-28T18:44:47.923 回答