Островное решение с ANTLR4

Я хотел бы поделиться с вами островным решением, которое мне пришлось реализовать в ANTLR4.

  1. Структура языка. Язык, для которого мне пришлось написать грамматику, является производным от PL/SQL с некоторыми дополнительными конструкциями. Я не буду вдаваться в подробности здесь, так как это не по теме.
  2. Язык определяет специальную команду PUT со следующей структурой:

    PUT [<SPECIALISED LANGUAGE>].

Моим решением было:

  1. Переопределить метод 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;
    }
    
  2. Добавьте код в лексер:

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

Любая обратная связь будет очень кстати! С уважением, Вольфганг Хаммер


person wolfgang hämmer    schedule 12.02.2013    source источник


Ответы (1)


Это действительно должно быть вики сообщества.

Мой первый важный комментарий: вам нужно избавиться от класса ANTLRStringStream. ANTLRInputStream класс, предоставляемый ANTLR 4, обеспечивает функциональность ANTLRStringStream в ANTLR 3. /IntStream.java" rel="nofollow">IntStream и CharStream были пересмотрены и подробно задокументированы в ANTLR 4, чтобы избавиться от проблемных методов rewind и другого неопределенного поведения. Вы не должны повторно вводить их.

person Sam Harwell    schedule 12.02.2013