2016-01-10 59 views
0

我正在開發Netbeans IDE的插件,它將提供對新的自定義語言的支持。我使用ANTLR特性爲我的自定義語言創建瞭解析器和詞法分析器。此外,我的語言包含一些非常複雜的「類似於SQL」的查詢,因此我決定爲「SQL-like」查詢編寫單獨的語法。因此,我必須爲我的「類似SQL」語言製作解析器和詞法分析器。因此,我有兩種語言,其中「類似SQL的」語言是嵌入式語言。 Netbeans提供了EmbeddingProvider類,它負責嵌入語言。
這是我EmbeddingProvider:自定義嵌入式語言netbeans

@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")和它的嵌入式語言( 「文本/ 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語言新的分析器,然後偏偏不信邪。我想知道如果我是正確的,並且如果有人給我一個建議如何將嵌入式語言文本拆分爲令牌,我會很高興。

+0

有一個有趣的問題隱藏在這裏*某處*,但事實上,幾乎不可能分辨出您面臨的實際問題。我建議閱讀你的問題,然後想象別人是否可以合理地理解它。你需要向我們解釋,因爲我們不知道你在說什麼,因爲說實話,我們不知道。請記住,你有很多我們不知道的背景。儘可能保持簡單和清晰。 – RubberDuck

+0

如果OP已經有ANTLR詞法分析器和分析器,爲什麼在將(嵌入式)語言文本分解爲令牌時存在問題?這是他的ANTLR詞法分析程序*所做的。 –

回答

0

除了使用EmbeddingProvider之外,您可以嘗試使用LanguageProvider。

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

它應該用於標記兩種語言(這可以導致很好的語法着色)。不幸的是,嵌入式語言的解析可能不起作用。

+0

非常感謝您的回答。我找到了解決我的問題的方法。這是解決嵌入式語言的另一種方法。 – podhornyi96

0

該問題已通過覆蓋類LanguageHierarchy中的方法得到解決。我試圖覆蓋此方法之前,但我用它不正確。問題在於將錯誤參數傳遞給方法LanguageEmbedding.create(SqllTokenId.getLanguage(), 0, 0);。我沒有傳遞零,而是傳遞了令牌的長度,所以它跳過了我的令牌,因爲第二個參數是startSkipLength,第三個參數是endSkipLength。下面的代碼是正確的。 LorxTokenType.SqllLiteral是我的「類似於sql」查詢的標記。它現在被解析爲嵌入式語言並由另一個詞法分析器和解析器處理(在我的情況下,由Sqll詞法分析器和解析器)。

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