Обработка скрытого канала в antlr 3

Я пишу грамматику ANTRL для перевода одного языка на другой, но документации по использованию HIDDEN канала очень мало. Нигде не могу найти примера. Единственное, что я нашел, - это FAQ на 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

person KuleRucket    schedule 17.11.2010    source источник
comment
Не могли бы вы опубликовать пример языка, на котором вы переводите? (а также окончательный результат этого перевода)   -  person Bart Kiers    schedule 17.11.2010
comment
Справочник ANTLR показывает примеры с режимом перезаписи - options {rewrite = true;} - и подклассом CommonTokenStream, TokenRewriteStream. Я ими не пользовался, но они могут быть интересны.   -  person Andy Thomas    schedule 17.11.2010


Ответы (2)


Рассмотрите возможность наследования CommonTokenStream и передачи экземпляра вашего подкласса в ANTLR. Из приведенного вами примера кода я подозреваю, что вам может быть интересно взглянуть на фильтр и параметры перезаписи, доступные в версии 3.

Также обратите внимание на этот другой связанный вопрос о переполнении стека.

person Glenn    schedule 20.11.2010
comment
Кстати, я поклонник ANTLR, и вы, возможно, захотите проверить dynamicsoftware.com/java/server / antlr для вступления. - person Glenn; 20.11.2010
comment
@Bart: Я не уверен, почему детали языков важны. Но язык ввода - это специальный язык под названием STL, который используется Европейским космическим агентством для управления оборудованием наземных станций. См. Код ниже. Целевым языком является Javascript с некоторыми настройками, работающими в движке Rhino. Большая часть языкового преобразования завершена, но я хочу сохранить комментарии. Таких скриптов около 3000. - person KuleRucket; 22.11.2010
comment
@ Энди и Гленн. Спасибо за информацию. Я немного почитаю о перезаписи и этом CommonTokenStream. - person KuleRucket; 22.11.2010
comment
Похоже, количество комментариев ограничено, поэтому я добавил образец к исходному вопросу. - person KuleRucket; 22.11.2010

Я только что рассмотрел некоторые из моих старых вопросов и подумал, что стоит ответить, предложив окончательное решение, которое сработало лучше всего. В конце концов, лучший способ перевести язык - использовать StringTemplate. Это позаботится о том, чтобы изменить отступ на выходе для вас. В пакете примеров ANTLR есть очень хороший пример cminus, который показывает, как его использовать.

person KuleRucket    schedule 28.08.2011