除了直线和列之外,如何跟踪令牌的偏移位置?

时间:2013-06-26 02:21:29

标签: java parsing token lexer javacc

除了beginLine,beginColumn,endLine和endColumn之外,是否有选项或某种方法来保留其源的令牌偏移位置?

我可能必须使用TOKEN_EXTENDSCOMMON_TOKEN_ACTION(或TOKEN_FACTORY)选项来存储额外的令牌信息,但我不知道如何检索令牌& #39;偏移量。有什么想法吗?

我正在寻找一个纯粹的解析器解决方案,这意味着,没有与实际文档的交互(我可以用它来计算之后的偏移量)。

2 个答案:

答案 0 :(得分:2)

我过去使用过的作弊是为偏移量选择默认的行/列信息。如果您不需要行/列信息,可以执行以下操作:

options {
    COMMON_TOKEN_ACTION = true;
}
...
TOKEN_MGR_DECLS : {
    static long offset = 0;
    static void CommonTokenAction(Token t) {
        // Poor-man's re-initialization.
        if ((t.beginLine == 1) && (t.beginColumn == 0)) { offset = 0; }
        offset += t.image.length();
        t.beginLine = (int)(offset >> 32);
        t.endLine = (int)(offset);
    }
}

令牌管理器和解析器都不依赖于行/列信息,因此这样做是安全的。可以同样恢复令牌t的偏移信息。

如果确实需要保留行/列信息,可以为令牌类型指定基类以及令牌工厂:

options {
    TOKEN_EXTENDS = "my.AbstractToken";
    TOKEN_FACTORY = "my.TokenFactory";
}
...

定义基本令牌类:

package my;
public abstract class AbstractToken {
    private long offset;
    protected AbstractToken() {
        // The offset hasn't been initialized.
        offset = -1;
    }
    public long getOffset() { return this.offset; }
    void setOffset(long offset) { this.offset = offset; }
}

定义令牌工厂:

package my;
public class TokenFactory {
    private static long offset = 0;
    public static Token newToken(int kind, String image) {
        Token token = new Token(kind, image);
        token.setOffset(offset);
        offset += image.length();
    }
}

您必须手动为下一次解析重置偏移量。我已经掩盖了其他一些细节,但值得注意的是,任何SKIP定义都应该转换为SPECIAL_TOKEN定义,以便为其他被忽略的空格推进偏移量。

答案 1 :(得分:2)

因此,最终我发现SimpleCharStream还跟踪缓冲区的当前偏移量,甚至称为tokenBegin。当通过TokenManager的getNextToken()创建/请求新令牌时,您可以使用它,后者又调用CommonTokenAction。

所以简单的设置可能如下所示:

options
{
    TOKEN_EXTENDS="MyToken";
    COMMON_TOKEN_ACTION=true;
}

令牌基类:

class MyToken
{
    public int offset;
    public Token token;
}

然后是CommonTokenAction定义:

TOKEN_MGR_DECLS:
{
    void CommonTokenAction(Token t)
    {
        MyToken token = (MyToken) t;
        token.offset = input_stream.tokenBegin;
        token.token = t;
    }
}