Написание пользовательского лексера Xtext/ANTLR без файла грамматики
Я пишу плагин Eclipse / Xtext для CoffeeScript, и я понял, что мне, вероятно, нужно будет написать лексер для него вручную. Парсер CoffeeScript также использует рукописный lexer для обработки отступов и других трюков в грамматике.
Xtext генерирует класс, который расширяет org.eclipse.xtext.parser.antlr.Lexer
, который, в свою очередь, расширяет org.antlr.runtime.Lexer
. Так что, полагаю, придется его продлить. Я вижу два способа сделать это
- переопределить
mTokens()
. Это делается автоматически код, изменение внутреннего состояния. - переопределить
nextToken()
что кажется естественным подходом, но тогда мне придется отслеживать внутреннее состояние.
Я не мог найти ни одного примера, как написать даже простой лексер для ANTLR без файла грамматики. Поэтому самым простым ответом будет указатель на один.
ответ Xtext: грамматика для языка со значимыми / семантическими пробелами относится к todotext который обрабатывает проблема отступов путем изменения токенов в базовом входном потоке. Я не хочу идти этим путем, потому что было бы трудно справиться с другими трюками грамматики coffeescript.
обновление:
тем временем я понял, что мой вопрос был частично специфичен для Xtext.
2 ответов
вот что я сделал-и это работает.
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 ;
}
и это все.
другой способ (без необходимости создания пользовательского синтаксического анализатора) - создать пользовательский лексер, расширив лексер Xtext (org.затмение.xtext.синтаксический анализатор.antlr.Лексер) следующим образом:
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);
}
Если вы хотите взглянуть на полный пример, я реализовал пользовательский лексер для редактора на основе Xtext для StringTemplate с именем hastee.