ANTLR @header, @parser, опция суперкласса и базовый файл io (Java) - PullRequest
7 голосов
/ 23 сентября 2011

Я хочу использовать действия анализатора с базовым файлом io (Java), например PrintWriter в грамматике ANTLR.Должен ли я использовать опцию суперкласса или я могу использовать @header?В обоих случаях, как я могу объявить объект PrintWriter и как я должен обрабатывать исключения?

1 Ответ

10 голосов
/ 23 сентября 2011

Параметр superClass=... используется, чтобы позволить вашему Parser расширить пользовательский класс.Так что я не думаю, что это то, что вам нужно.

Все в разделе @header будет размещено в начале вашего Parser класса.Это используется для импорта классов:

@header {
  import java.io.PrintWriter;
}

Обратите внимание, что @header {...} - это сокращение от @parser::header {...}.Вы также можете определить: @lexer::header {...} для своего лексера.

А внутри секций @member {...} (или: @parser::member {...}, @lexer::member {...}) вы можете добавить переменные экземпляра и методы, которые можно использовать внутри либоParser или Lexer:

@header {
  import java.io.PrintWriter;
}

@members {
  PrintWriter writer;
}

Небольшая демонстрация грамматики, парсер которой запишет проанализированные числа конкретному записывающему устройству:

grammar T;

@header {
  import java.io.PrintWriter;
}

@members {
  PrintWriter writer;

  public TParser(TokenStream input, String fileName) {
    super(input);
    try {
      writer = new PrintWriter(fileName);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}

parse
  :  numbers EOF
  ;

numbers
  :  (NUM {
            writer.println("parsed: " + $NUM.text);
            writer.flush();
          }
     )+
  ;

NUM : '0'..'9'+;
WS  : ' ' {skip();};

, который можно проверить с помощью:

import java.io.File;
import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    String source = "42 500000000 666";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer), "log.txt");
    parser.parse();
  }
}

Если вы запустите приведенный выше класс, будет создан файл с именем log.txt, содержащий:

parsed: 42
parsed: 500000000
parsed: 666

Обратите внимание, что существует строгий порядок всех этих @... иoptions {...} и т. Д. Экземпляры:

  1. grammar определение
  2. options блок (без @ знак!)
  3. tokens блок (без@ знак!)
  4. @header блок
  5. @members блок

grammar T;

options {
  // options here
}

tokens {
  // imaginary tokens here
}

@header  { 
  // ... 
}

@members { 
  // ... 
}

РЕДАКТИРОВАТЬ

ANTLRStarter писал:

Как я могу добавить код, которыйвыполняется в конце класса лексера / парсера?

Нет встроенной функциональности для такой вещи.Но вы можете легко создать собственный метод wrapUp() в вашем парсере:

@members {

  // ...

  private void wrapUp() {
    // wrap up your parser in here
  }
}

и затем автоматически вызывать этот метод из точки входа вашей грамматики, например:

parse
@after {this.wrapUp();}
  :  numbers EOF
  ;

Любойкод, помещенный в блок @after {...} правила, выполняется, когда все в правиле правильно сопоставлено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...