编写没有语法文件的自定义 Xtext/ANTLR 词法分析器

发布于 2024-12-13 21:02:57 字数 890 浏览 0 评论 0原文

我正在为 CoffeeScript 编写一个 Eclipse/Xtext 插件,我意识到我可能需要手动为其编写一个词法分析器。 CoffeeScript 解析器还使用 手写词法分析器处理语法中的缩进和其他技巧。

Xtext 生成一个扩展 org.eclipse.xtext.parser.antlr.Lexer 的类,该类又扩展 org.antlr.runtime.Lexer 。所以我想我会延长它。我可以看到两种方法来

  • 覆盖mTokens()。这是通过生成的代码来完成的,改变内部状态。
  • 覆盖 nextToken() 这似乎是一种自然的方法,但随后我必须跟踪内部状态。

我找不到任何示例如何在没有语法文件的情况下为 ANTLR 编写一个简单的词法分析器。所以最简单的答案是指向一个的指针。

Xtext:具有重要/语义空白的语言的语法 指的是 todotext通过更改底层输入流中的标记来解决缩进问题。我不想走那条路,因为处理咖啡脚本语法的其他技巧会很困难。

更新:

我同时意识到我的问题部分是 Xtext 特定的。

I'm writing an Eclipse/Xtext plugin for CoffeeScript, and I realized I'll probably need to write a lexer for it by hand. CoffeeScript parser also uses a hand-written lexer to handle indentation and other tricks in the grammar.

Xtext generates a class that extends org.eclipse.xtext.parser.antlr.Lexer which in turn extends org.antlr.runtime.Lexer. So I suppose I'll have extend it. I can see two ways to do that

  • Override mTokens(). This is done by the generated code, changing the internal state.
  • Override nextToken() which seems a natural approach, but then I'll have to keep track of the internal state.

I couldn't find any example how to write even a simple lexer for ANTLR without a grammar file. So the easiest answer would be a pointer to one.

An answer to Xtext: grammar for language with significant/semantic whitespace refers to todotext which handles the problem of indentation by changing the tokens in the underlying input stream. I don't want to go that way, because it would be difficult to handle other tricks of the coffeescript grammar.

UPDATE:

I realized in the meantime that my question was partly Xtext specific.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

回梦 2024-12-20 21:02:57

这就是我所做的——而且它有效。

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

就是这样。

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.

殤城〤 2024-12-20 21:02:57

另一种方法(无需创建自定义解析器)是通过扩展 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 的基于 Xtext 的编辑器实现了一个自定义词法分析器,名为 hastee

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文