Writing a custom Xtext/ANTLR lexer without a grammar file

夙愿已清 提交于 2019-12-04 03:49:27

Here is what I did -- and it works.

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) {
    // ...
  }
}

Then I have a slightly customized parser containing:

public class BetterParser extends MylangParser {
  @Override
  protected TokenSource createLexer(CharStream stream) {
    MyLexer lexer = new MyLexer(stream);
    return lexer;
  }
}

I also had to change my MylangRuntimeModule.java to contain this method

@Override
public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() {
     return myprj.parser.BetterParser.class ;
}

And that's it.

Another way (without the need to create a custom parser) is to create a custom lexer by extending Xtext's lexer (org.eclipse.xtext.parser.antlr.Lexer) as follows:

public class CustomSTLexer extends Lexer {

    @Override
    public void mTokens() {
      // implement lexer here
    }
}

Then you bind it in your module:

@Override
public void configureRuntimeLexer(Binder binder) {
    binder.bind(Lexer.class)
                .annotatedWith(Names.named(LexerBindings.RUNTIME))
                .to(CustomSTLexer.class);
}

If you want to have a look at a complete example, I have implemented a custom lexer for an Xtext-based editor for StringTemplate called hastee.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!