Я хотел бы поделиться с вами островным решением, которое мне пришлось реализовать в ANTLR4.
- Структура языка. Язык, для которого мне пришлось написать грамматику, является производным от PL/SQL с некоторыми дополнительными конструкциями. Я не буду вдаваться в подробности здесь, так как это не по теме.
Язык определяет специальную команду
PUT
со следующей структурой:PUT [<SPECIALISED LANGUAGE>]
.
Моим решением было:
Переопределить метод
nextToken
Лексера:public Token nextToken() { if (f_current_idx != -1) { _input.seek(f_current_idx); f_current_idx = -1; } Token l_token = super.nextToken(); return l_token; }
Добавьте код в лексер:
PUT : 'PUT' { f_current_idx = _input.index(); ((ANTLRStringStream) _input).rewind(); SRC_PUTLexer l_put_lexer = new SRC_PUTLexer(_input); UnbufferedTokenStream<Token> l_tokenStream = new UnbufferedTokenStream<Token>(l_put_lexer); if (l_tokenStream.LA(2) == SRC_PUTLexer.LBRACK) { new SRC_PUTParser(l_tokenStream).start_rule(); f_current_idx = _input.index(); } };
Кроме того, необходимо было определить класс ANTLRStringStream
, который исчез в ANTLR 4:
public class ANTLRStringStream extends ANTLRInputStream {
protected int markDepth = 0;
protected int lastMarker;
protected ArrayList<Integer> markers;
public ANTLRStringStream() {
super();
}
public ANTLRStringStream(String input) {
super(input);
}
public int mark() {
if ( markers==null ) { markers = new ArrayList<Integer>(); }
markers.add(markDepth, index()); markDepth++; lastMarker = markDepth;
return markDepth;
}
public void rewind(int m) {
int state = (int) markers.get(m); seek(state); release(m);
}
public void rewind() { rewind(lastMarker); }
public void release(int marker) {
markDepth = marker; markDepth--;
}
}
Любая обратная связь будет очень кстати! С уважением, Вольфганг Хаммер