2016-01-10 3 views
0

Я разрабатываю плагин для NetBeans IDE, который обеспечит поддержку нового пользовательского языка. Я создал парсер и лексер для моего пользовательского языка, используя функции ANTLR. Кроме того, мой язык содержит некоторые «похожие на SQL» запросы, которые очень сложны, поэтому я решил написать отдельную грамматику для «SQL-подобных» запросов. Следовательно, я должен был сделать парсер и лексер для моего «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"), и это встроенный язык ("текст/х-sqll"). Метод getEmbeddings(Snapshot snapshot) выполняется, когда мы открываем какой-либо файл в редакторе или просто перемещаем каретку в другую позицию.
Я использую класс Snapshot для получения последовательности токенов текущего открытого файла. В этом примере кода я повторяю токены в поисках маркера SqllLiteral (это как [select * from ...]). Если я найду этот токен, я создам новое Embedding.

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 lexer и parsers, почему возникает проблема с разбиением (встроенным) текстом языка на токены? Вот что делает его ANTLR lexer *. –

ответ

0

Вместо использования встроенного программного обеспечения вы можете попробовать использовать 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-like». Теперь он разрешен как внедренный язык и обрабатывается другим лексером и синтаксическим анализатором (в моем случае с помощью 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; 
    } 
Смежные вопросы