除了 beginLine、beginColumn、endLine 和 endColumn 之外,是否有选项或某种方法可以保留其源的令牌偏移位置?
我可能不得不使用TOKEN_EXTENDS
, COMMON_TOKEN_ACTION
(or TOKEN_FACTORY
) 选项来存储额外的令牌信息,但我不知道如何检索令牌的偏移量。有任何想法吗?
我正在寻找一个纯解析器解决方案,这意味着与实际文档没有交互(我可以用它来计算之后的偏移量)。
我过去使用的一个作弊方法是为偏移选择默认的行/列信息。如果您不需要行/列信息,您可以执行以下操作:
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
定义,以便为其他被忽略的空白增加偏移量。
所以,最终我发现 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;
}
}