0

我想与您分享一个我必须在 ANTLR4 中实施的孤岛解决方案。

  1. 语言的结构。我必须为其编写语法的语言源自 PL/SQL,并带有一些额外的结构。我不会在这里详细介绍,因为这是题外话。
  2. PUT该语言定义了一个具有以下结构的特殊命令:

    PUT [<SPECIALISED LANGUAGE>].

我的解决方案是:

  1. 覆盖 Lexer 的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. 在 Lexer 中添加一些代码:

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

非常欢迎任何反馈!亲切的问候,沃尔夫冈·哈默

4

1 回答 1

3

这真的应该是一个社区维基。

我的第一个主要评论是你需要摆脱这ANTLRStringStream门课。ANTLR 4 提供的ANTLRInputStream类提供了 ANTLR 3 中的功能。ANTLRStringStreamIntStream接口CharStream在 ANTLR 4 中进行了修改和广泛记录,以消除有问题的rewind方法和其他未定义的行为。你不应该重新引入它们。

于 2013-02-12T15:43:04.967 回答