Я пытаюсь использовать ANTLR (пробовал 3.3 и 3.4). Странная вещь случается, когда я пытаюсь запустить свой тестовый код. Пожалуйста, сначала посмотрите мой очень простой код, потом я объясню свою проблему.
Тестовая грамматика:
lexer grammar CSVLexer;
Comma
: ','
;
LineBreak
: '\r'? '\n'
| '\r'
;
SimpleValue
: ~(',' | '\r' | '\n' | '"')+
;
QuotedValue
: '"' ('""' | ~'"')* '"'
;
Тестовый код:
import org.antlr.runtime.*;
public class JMain {
public static void main(String[] args) throws Exception {
String source = "val1,val2,val3";
CSVLexer lexer = new CSVLexer(new ANTLRStringStream(source));
CommonTokenStream tokens = new CommonTokenStream(lexer);
int n = 1;
for (Object o : tokens.getTokens()) {
CommonToken token = (CommonToken) o;
System.out.println("token(" + n + ") = " + token.getText().replace("\n", "\\n"));
n++;
}
}
}
Compiation:
$ export CLASSPATH=antlr3.jar
$ java org.antlr.Tool CSVLexer.g
$ javac *.java
$ java JMain
Первая проблема в том, что он ничего не печатает :). Я работаю в Intellij IDEA (10), и я безуспешно пытался запустить код отсюда (с ANTLR в CLASSPATH). ОДНАКО, если я установлю точку останова на int i = 1
, отладлю и подожду, скажем 1-3 секунды, прежде чем продолжить, это работает! Если я запускаю его в режиме отладки без точки останова, это не так. Может кто-нибудь объяснить мне, в чем может быть проблема? Спасибо.
РЕДАКТИРОВАТЬ:
Итак, я попробовал ту поставить:
tokens.fill()
сразу после
CommonTokenStream tokens = new CommonTokenStream(lexer);
и это сработало. Однако затем я начал отлаживать конструктор CommonTokenStream (несколько минут), и когда я включил tokens.fill()
, я получил IndexOutOfBoundException. Так что что-то в фоновом режиме что-то сделало, но я не вижу других потоков в IDEA.
EDIT2:
Проблема решена. Похоже, что сначала нужно вызвать fill()
и что BufferedTokenStream
, вероятно, не предназначено для такого использования. Я следовал этому уроку http://bkiers.blogspot.com/2011/03/2-introduction-to-antlr.html, где он, вероятно, как-то работал на автора (интересно почему). Отладчик IntelliJ IDEA вызывал toString()
для локальных объектов, а он в свою очередь вызывал fill()
, поэтому он работал, когда я устанавливал точку останова. toString()
Модифицирующее состояние - зло!