除了beginLine,beginColumn,endLine和endColumn之外,是否有选项或某种方法来保留其源的令牌偏移位置?
我可能必须使用TOKEN_EXTENDS
,COMMON_TOKEN_ACTION
(或TOKEN_FACTORY
)选项来存储额外的令牌信息,但我不知道如何检索令牌& #39;偏移量。有什么想法吗?
我正在寻找一个纯粹的解析器解决方案,这意味着,没有与实际文档的交互(我可以用它来计算之后的偏移量)。
答案 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;
}
}