我正在为CoffeeScript编写一个Eclipse / Xtext插件,我意识到我可能需要手工编写一个词法分析器。 CoffeeScript解析器还使用hand-written lexer来处理语法中的缩进和其他技巧。
Xtext生成一个扩展org.eclipse.xtext.parser.antlr.Lexer
的类,后者又扩展org.antlr.runtime.Lexer
。所以我想我会扩展它。我可以看到两种方法来做到这一点
mTokens()
。这是由生成的代码完成的,改变了内部状态。nextToken()
这似乎是一种自然的方法,但我必须跟踪内部状态。我找不到任何例子如何在没有语法文件的情况下为ANTLR编写简单的词法分析器。所以最简单的答案就是指向一个。
Xtext: grammar for language with significant/semantic whitespace的答案是指todotext,它通过更改基础输入流中的标记来处理缩进问题。我不想这样做,因为很难处理coffeescript语法的其他技巧。
更新:
与此同时,我意识到我的问题部分是特定于Xtext的。
答案 0 :(得分:8)
这就是我所做的 - 而且有效。
public class MyLexer extends myprj.parser.antlr.internal.InternalMylangLexer {
private SomeExternalLexer externalLexer;
public Lexer(CharStream in) {
super(in);
externalLexer = new SomeExternalLexer(in);
}
@Override
public Token nextToken() {
Token token = null;
ExternalToken extToken = null;
try {
extToken = externalLexer.nextToken();
if (extToken == null) {
token = CommonToken.INVALID_TOKEN;
}
else {
token = mapExternalToken(extToken);
}
}
catch (Exception e) {
token = CommonToken.INVALID_TOKEN;
}
return token;
}
protected Token mapExternalToken(ExternalToken extToken) {
// ...
}
}
然后我有一个稍微定制的解析器,其中包含:
public class BetterParser extends MylangParser {
@Override
protected TokenSource createLexer(CharStream stream) {
MyLexer lexer = new MyLexer(stream);
return lexer;
}
}
我还必须更改我的MylangRuntimeModule.java
以包含此方法
@Override
public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() {
return myprj.parser.BetterParser.class ;
}
就是这样。
答案 1 :(得分:6)
另一种方法(无需创建自定义解析器)是通过扩展Xtext的词法分析器(org.eclipse.xtext.parser.antlr.Lexer)来创建自定义词法分析器,如下所示:
public class CustomSTLexer extends Lexer {
@Override
public void mTokens() {
// implement lexer here
}
}
然后将其绑定在您的模块中:
@Override
public void configureRuntimeLexer(Binder binder) {
binder.bind(Lexer.class)
.annotatedWith(Names.named(LexerBindings.RUNTIME))
.to(CustomSTLexer.class);
}
如果你想看一个完整的例子,我已经为StringTemplate的一个名为hastee的基于Xtext的编辑器实现了一个自定义词法分析器。