自定义嵌入式语言netbeans

时间:2016-01-10 13:23:34

标签: parsing netbeans antlr netbeans-8 netbeans-plugins

我正在为Netbeans IDE开发插件,它将为新的自定义语言提供支持。我使用ANTLR功能为我的自定义语言创建了解析器和词法分析器。此外,我的语言包含一些非常复杂的“类SQL”查询,因此我决定为“类似SQL”的查询编写单独的语法。因此,我必须为我的“类SQL”语言创建解析器和词法分析器。因此,我有两种语言,其中“类SQL”语言是嵌入式语言。 Netbeans提供了类EmbeddingProvider,它负责嵌入语言。
这是我的EmbeddingProvider:

@EmbeddingProvider.Registration(mimeType = "text/x-lorx", targetMimeType = "text/x-sqll")
public class LorxEmbeddingProvider extends EmbeddingProvider {

    @Override
    public List<Embedding> getEmbeddings(Snapshot snapshot) {
        TokenHierarchy th = snapshot.getTokenHierarchy();
        TokenSequence<LorxTokenId> ts = th.tokenSequence(LorxTokenId.getLanguage());
        List<Embedding> embeddings = new ArrayList<>();

        while(ts.moveNext()) {
            Token currToken = ts.token();
            if(currToken.id().ordinal() == LorxTokenType.SqllLiteral.id) {
                embeddings.add(snapshot.create(currToken.text(), "text/x-sqll"));
            }
        }
        return embeddings;
    }

    @Override
    public int getPriority() {
        return 140;
    }

    @Override
    public void cancel() {

    }

}

注释用于确定顶级语言("text/x-lorx")及其嵌入式语言(“text / x-sqll”)。 当我们在编辑器中打开某个文件或将插入符移动到另一个位置时,方法getEmbeddings(Snapshot snapshot)会执行。
我使用Snapshot类来获取当前打开文件的标记序列。在这个代码示例中,我正在迭代令牌以搜索SqllLiteral令牌(就像[select * from ...])。如果我找到这个令牌,我会创建新的嵌入。

public class SqllParserFactory extends ParserFactory {

    @Override
    public Parser createParser(Collection<Snapshot> snapshots) {
        return new SqllNBParser();
    }

}

完成getEmbeddings(Snapshot snapshot)方法后,嵌入式语言的SqllParserFactory会为sqll语言创建新的解析器,然后什么都不会发生。我想知道我是否走在正确的道路上,如果有人给我建议如何将嵌入式语言文本拆分成令牌,我会很高兴。

2 个答案:

答案 0 :(得分:0)

您可以尝试使用LanguageProvider而不是使用EmbeddingProvider。

@ServiceProvider(service = LanguageProvider.class)
public class MyEmbeddingLanguageProvider extends LanguageProvider {

    @Override
    public LanguageEmbedding<?> findLanguageEmbedding(Token<?> token, 
            LanguagePath languagePath, InputAttributes inputAttributes) {

        Language embeddedLanguage = MimeLookup.getLookup("text/sqll").lookup(Language.class);

        if (embeddedLanguage != null && languagePath.mimePath().equals("text/x-lorx")) {
            if (token.id().ordinal() == LorxTokenType.SqllLiteral.id) {
                return LanguageEmbedding.create(embeddedLanguage, 0, 0, true);
            }
        }
        return null;
    }

    @Override
    public Language<?> findLanguage(String mimeType) {
        return null;
    }
}

它应该用于标记两种语言(这可以导致良好的语法着色)。不幸的是,解析嵌入式语言可能无法正常工作。

答案 1 :(得分:0)

通过覆盖LanguageHierarchy类中的方法解决了该问题。我以前试图覆盖这个方法,但我错误地使用了它。问题在于将错误的参数传递给方法LanguageEmbedding.create(SqllTokenId.getLanguage(), 0, 0);。我没有传递零,而是传递了令牌的长度,因此它正在跳过我的令牌,因为第二个参数是startSkipLength而第三个参数是endSkipLength。下面的代码是正确的。 LorxTokenType.SqllLiteral是我的“类似sql”查询的标记。它现在被解析为嵌入式语言,并由另一个词法分析器和解析器处理(在我的例子中由Sqll lexer和parser处理)。

@Override
    protected LanguageEmbedding<?> embedding(Token<LorxTokenId> token, LanguagePath languagePath, InputAttributes inputAttributes) {
        if(token.id().ordinal() == LorxTokenType.SqllLiteral.id) {
           return LanguageEmbedding.create(SqllTokenId.getLanguage(), 0, 0);
        }
        return null;
    }