Написание собственного лексера Xtext / ANTLR без файла грамматики - PullRequest
9 голосов
/ 07 ноября 2011

Я пишу плагин Eclipse / Xtext для CoffeeScript, и я понял, что, вероятно, мне понадобится написать лексер для него вручную.Синтаксический анализатор CoffeeScript также использует рукописный лексер для обработки отступов и других трюков в грамматике.

Xtext генерирует класс, расширяющий org.eclipse.xtext.parser.antlr.Lexer, который, в свою очередь, расширяет org.antlr.runtime.Lexer.Так что, я полагаю, мне придется продлить его.Я вижу два способа сделать это

  • Переопределить mTokens().Это делается сгенерированным кодом, изменяя внутреннее состояние.
  • Переопределение nextToken(), что кажется естественным подходом, но тогда мне придется отслеживать внутреннее состояние.

Я не смог найти ни одного примера, как написать даже простой лексер для ANTLR без файла грамматики.Таким образом, самым простым ответом будет указатель на единицу.

Ответ на Xtext: грамматика для языка со значительным / семантическим пробелом относится к todotext , который решает проблемуотступ, изменяя токены в основном входном потоке.Я не хочу идти по этому пути, потому что было бы трудно справиться с другими уловками грамматики coffeescript.

ОБНОВЛЕНИЕ:

Тем временем я понял, что мой вопрос был частично специфичным для Xtext..

Ответы [ 2 ]

8 голосов
/ 09 декабря 2011

Вот что я сделал - и это работает.

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 ;
}

И это все.

6 голосов
/ 25 января 2012

Другим способом (без необходимости создания пользовательского анализатора) является создание пользовательского лексера путем расширения лексера 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);
}

Если вы хотите взглянуть на полный пример, я реализовал собственный лексер для редактора на основе Xtext для StringTemplate с именем hastee .

...