2010-11-17 59 views
3

我正在編寫一種用於將一種語言翻譯爲另一種語言的ANTRL語法,但使用HIDDEN通道的文檔非常稀少。我無法在任何地方找到示例。我唯一發現的是www.antlr.org上的FAQ,它告訴你如何訪問隱藏的頻道,但不知道如何最好地使用這個功能。目標語言是Java。在antlr中處理隱藏通道3

在我的語法文件,我通過空格和像這樣評論過:

// 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; } 
    ; 

在我的成員部分我已經定義的方法寫的隱藏通道令牌來我的輸出字符串流...

@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 
+0

你能發表一個你正在翻譯的語言的例子嗎? (也是此翻譯的最終結果) – 2010-11-17 11:51:39

+0

ANTLR參考手冊顯示了「重寫模式」的示例 - 選項{rewrite = true;}和CommonTokenStream的子類TokenRewriteStream。我沒有使用過這些,但他們可能會感興趣。 – 2010-11-17 15:09:59

回答

0

查找到繼承CommonTokenStream和餵養你的子類的實例爲ANTLR。從您給出的代碼示例中,我懷疑您可能有興趣查看版本3中提供的篩選器和重寫選項。

另外,請查看此其他related stack overflow question

+0

順便說一句,我是ANTLR的粉絲,你可能想看看http://www.dynamicalsoftware.com/java/server/antlr的介紹。 – Glenn 2010-11-20 19:19:04

+0

@Bart:我不知道爲什麼這些語言的細節很重要。但輸入語言是一種稱爲STL的自定義語言,由歐洲空間局用於控制接地設備。請參閱下面的代碼。目標語言是在Rhino引擎中運行一些定製的Javascript。大部分語言轉換已完成,但我想保留評論。大約有3000個這樣的腳本。 – KuleRucket 2010-11-22 08:13:53

+0

@安迪和格倫。謝謝(你的)信息。我會在重寫和CommonTokenStream上做一些閱讀。 – KuleRucket 2010-11-22 08:17:42

0

我剛剛經歷了一些我的老問題,並認爲值得迴應最終解決方案,效果最好。最後,翻譯語言的最好方法是使用StringTemplate。這需要爲您重新縮進輸出。 ANTLR示例包中有一個稱爲'cminus'的非常好的示例,演示瞭如何使用它。