SlideShare uma empresa Scribd logo
1 de 37
Custom Language Plugin для
Jetbrains IDEA
Сбербанк Технологии
Александр Засташков
2015
Область применения
1. Proprietary programming languages
Software AG Apama Event Processing
Language ©
2. Domain specific languages
3. Системы проверки синтаксиса
4. Трансляторы из одного языка в другой
Apama EPL Plugin
1. Подсветка синтаксиса
2. Проверка синтаксиса
3. Навигация по ссылкам
– Программные конструкции определенные внутри
одного файла
– Внешние ссылки
Apama Event Processing Language
on Event A
Event A Event B
on Event B
correlator monitors
Теория
• Alfred V. Aho, Compilers: Principles,
Techniques & Tools
• Terence Parr, Language Implementation
Patterns
• https://confluence.jetbrains.com/display/IDEA
DEV/Developing+Custom+Language+Plugins+f
or+IntelliJ+IDEA
поток символов
Лексический анализатор (Lexer)
Синтаксический анализатор (Parser)
поток лексем
синтаксическое дерево
Остальные фазы компиляции
Процесс компиляции
Таблица символов
Лексический анализатор
Пусть исходная программа содержит инструкцию присваивания:
position = initial + rate * 60
Символы в этом присваивании могут быть сгруппированы в следующие лексемы и
отображены в следующие токены, передаваемые синтаксическому анализатору:
1. position  (id, 1)
2. =  (=, нет значения атрибута)  (=)
3. initial -> (id, 2)
4. +  (+)
5. rate  (id, 3)
6. *  (*)
7. 60  (number, 4)
Выходной поток токенов после лексического анализа будет иметь вид:
(id, 1) (=) (id, 2) (+) (id, 3) (*) (id, 4)
1 position …
2 initial …
3 rate …
4 60 …
… … …
Синтаксический анализатор
Синтаксический анализатор использует первые компоненты токенов, полученных при
лексическом анализе, для создания древовидного промежуточного представления, которое
описывает грамматическую структуру потока токенов.
поток токенов (id, 1) (=) (id, 2) (+) (id, 3) (*) (id, 4)
синтаксическое дерево (=)
/ 
(id, 1) (+)
/ 
(id, 2) (*)
/ 
(id, 3) (id, 4)
Грамматика
Иерархическая структура множества конструкций языка программирования может быть
описана с помощью контекстно свободных грамматик, состоящих из:
1. Терминалы
2. Нетерминалов
3. Продукции
4. Один из нетерминальных символов, указываемый как стартовый или начальный.
boolean_literal ::= true | false
decimal_literal ::= ( '-' | '+' )* ( DECIMAL | ( DIGIT+ DOT? ) )
где
DIGIT = 'regexp:[0-9]+'
Грамматика
Грамматика определяется перечислением ее продукций, причем первой
указывается продукция для стартового символа. Грамматика выводит, или порождает,
строки, начиная со стартового символа и неоднократно замещая нетерминалы телами
продукций этих нетерминалов. Строки токенов, порождаемые из стартового символа,
образуют язык, определяемый грамматикой.
Грамматика может быть описана в форме Бэкуса — Наура или представлена графически в
виде railroad diagram.
program ::= package_specification? using_declaration+ ( event_declaration+ | monitor_declaration )
Разбор (Parsing)
Синтаксический анализ, или разбор, представляет собой выяснение для полученной
строки терминалов способа ее вывода из стартового символа грамматики. Если строка не
может быть выведена из стартового символа, синтаксический анализатор сообщает об
ошибке в строке.
Задачу синтаксического анализа можно представить как построение дерева разбора.
S ::= xyz | aBC
грамматика: B ::= c | cd строка: acddf
C ::= eg | df
S S S S S
| / |  / |  / |  / | 
a B C a B C a B C a B C
| | / | / | | 
c c d c d d f
Инструменты
1. Jetbrains IDEA Community Edition
• Языково-независимая часть платформы
• Специфическая для конкретного языка
2. git clone git://git.jetbrains.org/idea/community.git idea
3. Плагины:
• Plugin DevKit
Набор инструментов для разработки плагинов под платформу Intellij IDEA
• Grammar-Kit
Плагин для описания грамматик в форме Бэкуса — Наура
• PsiViewer
Intellij IDEA Program Structure Interface
Конфигурация SDK
Создание проекта
Язык EPL и иконка
Тип файла EPL
Список расширений файлов EPL
EPL Plugin Run/Debug Configuration
Запуск плагина
Jetbrains IDEA logs: https://devnet.jetbrains.com/docs/DOC-181
При запуске Run / Debug Configuration и создании нового файла с зарегистрированным
расширением IDEA автоматически ассоциирует его с разрабатываемым плагином.
Реализация лексического анализатора
Лексический анализатор (lexer) – база для всего дальнейшего функционала Custom
Language Plugin.
IDEA вызывает lexer в трех основных контекстах:
1. Подсветка синтаксиса
2. Построение синтаксического дерева файла
3. Построение индекса слов содержащихся в файле
Лексический анализатор для IDEA можно создать:
1. Реализацией интерфейса com.intellij.lexer.Lexer
2. Используя генератор лексических анализаторов JFlex (jflex.de)
JFlex генерирует лексические анализаторы на основе *.flex файлов, которые в свою очередь
могут быть сгенерированы из грамматики при помощи IDEA GrammarKit Plugin.
Процесс синтаксического анализа в IDEA
1. Построение абстрактного синтаксического дерева (AST), определяющее структуру
программы
monitor M {  monitor_declaration
} |
+-- monitor
|
+-- identifier
|
+-- {
|
+-- }
2. Во второй фазе строится PSI (Program Structure Interface) дерево поверх AST,
добавляя семантику и методы для манипуляции языковыми конструкциями
Синтаксический анализатор для IDEA можно создать:
1. Реализацией интерфейса com.intellij.lang.PsiParser
2. Сгенерировать из грамматики используя IDEA Grammar-Kit Plugin
Типы лексем и связанных с AST узлами элементов
PsiViewer Plugin
Для отладки PSI структур удобно использовать IDEA PsiViewer Plugin. С его помощью можно
смотреть структуру PSI дерева для целевого языка, свойства каждого PSI элемента и
отображение исходного кода на соответствующую структуру PSI элементов.
Грамматика EPL
Грамматика EPL описывается в файле epl.bnf. На ее основе средствами IDEA Grammar-Kit
Plugin возможна генерация совместимых с платформой лексических и синтаксических
анализаторов.
BNF файл грамматики состоит из трех разделов:
1. Секции заголовка:
parserClass="com.intellij.epl.parser.EplParser“
psiClassPrefix="Epl"
psiImplClassSuffix="Impl"
psiPackage="com.intellij.epl.psi"
psiImplPackage="com.intellij.epl.psi.impl"
elementTypeHolderClass="com.intellij.epl.psi.EplTypes"
elementTypeClass="com.intellij.epl.psi.EplElementType"
tokenTypeClass="com.intellij.epl.psi.EplTokenType"
psiImplUtilClass="com.intellij.epl.psi.EplPsiImplUtil"
Грамматика EPL
2. Секции лексем, которые возможно при необходимости задать регулярными
выражениями для удобства их последующего использования:
tokens=[
ID = 'regexp:[a-zA-Z_$][a-zA-Z0-9_$]*'
DIGIT = 'regexp:[0-9]+'
DECIMAL = 'regexp:[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?'
NON_EMPTY_STRING = 'regexp:"([^"]|.)*"'
EMPTY_STRING = '""'
DOCUMENTATION = 'regexp:/**([^*]|[rn]|(*+([^*/]|[rn])))**+/'
BLOCK_COMMENT = 'regexp:/*([^*]|[rn]|(*+([^*/]|[rn])))**+/'
LINE_COMMENT = 'regexp://.*'
OP_ASSIGNMENT = ":="
OP_PLUS = "+"
OP_MINUS = "-"
OP_AR_MUL = "*"
OP_AR_DIV = "/"
Грамматика EPL
3. Непосредственно грамматическими правилами:
root ::= program
program ::= { package_specification | using_declaration | monitor_declaration |
event_declaration |
event_instance | DOCUMENTATION | BLOCK_COMMENT | LINE_COMMENT }*
package_specification ::= package identifier ( '.' identifier )* ';'
identifier ::= ID
{
methods = [getReference]
}
monitor_declaration ::= persistent? monitor identifier '{'
{ import_declaration | event_declaration | variable_declaration |
action_definition | DOCUMENTATION | BLOCK_COMMENT | LINE_COMMENT }* '}‘
…
Grammar-Kit Plugin
Формат flex файлов
Flex файл представляет собой спецификацию, на основе которой будет сгенерирован java
класс лексического анализатора. Основными его разделами являются:
1. Определение пакета лексического анализатора и импортируемых зависимостей
package com.intellij.epl;
import com.intellij.lexer.*;
import com.intellij.psi.tree.IElementType;
import static com.intellij.epl.psi.EplTypes.*;
2. Кода, который следует включить в неизменном виде в создаваемый класс:
%{
public _EplLexer() {
this((java.io.Reader)null);
}
%}
Формат flex файлов
3. Модификатора доступа создаваемого класса, его имени и реализуемых интерфейсов
%public
%class _EplLexer
%implements FlexLexer
4. Типа элементов создаваемых лексем:
%type IElementType
5. Последовательности символов описываемых регулярными выражениями:
EOL="r"|"n"|"rn"
LINE_WS=[ tf]
WHITE_SPACE=({LINE_WS}|{EOL})+
ID=[a-zA-Z_$][a-zA-Z0-9_$]*
DIGIT=[0-9]+
DECIMAL=[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?
Формат flex файлов
6. Правила и действия
%%
<YYINITIAL> {
{WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; }
"""" { return EMPTY_STRING; }
":=" { return OP_ASSIGNMENT; }
"+" { return OP_PLUS; }
…
"package" { return PACKAGE; }
"using" { return USING; }
"persistent" { return PERSISTENT; }
…
{ID} { return ID; }
{DIGIT} { return DIGIT; }
{DECIMAL} { return DECIMAL; }
Генерация лексического и
синтаксического анализаторов
1. Генерация лексического анализатора в IDEA происходит в два этапа:
 генерация файла *.flex из файла грамматики *.bnf
Grammar-Kit -> Generate JFlex Lexer
 генерация лексического анализатора на основе сгенерированного
*.flex файла
Grammar-Kit -> Run JFlex Generator
2. Синтаксический анализатор генерируется из из файла грамматики
*.bnf
Grammar-Kit -> Generate Parser Code
Реализация класса подсветки синтаксиса
Подсветка синтаксиса реализуется отображением классов лексем на
соответствующие инстансы com.intellij.openapi.editor.colors.TextAttributesKey
Реализация страницы настроек цветовой
схемы плагина
Необходима реализация com.intellij.openapi.options.colors.ColorSettingsPage
Регистрация реализованных точек
расширения
Для активации реализованных / сгенерированных классов их необходимо зарегистрировать как
точки расширения в файле META-INF/plugin.xml
Навигация по структуре программы
Ссылка (на переменную, метод и т. д. ) представляет собой указатель на один из узлов
дерева и может находиться либо в текущем, либо во внешнем файле.
Навигация по структуре программы
Реализация метода getReference() должна возвращать конкретный узел PSI дерева, который
откроется в текстовом редакторе.
Что дальше?
• Find Usages
• Code Completion
• Остальные фичи IDEA для Custom Language
IntelliJ IDEA Custom Languages repo:
https://plugins.jetbrains.com/category/index?pr=idea&category_id=48

Mais conteúdo relacionado

Mais procurados

Язык программирования Pascal
Язык программирования PascalЯзык программирования Pascal
Язык программирования PascalSchool 242
 
Programming Concepts
Programming ConceptsProgramming Concepts
Programming ConceptsMister_Lee
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.Igor Shkulipa
 
основы програмирования Pascal
основы програмирования Pascalосновы програмирования Pascal
основы програмирования Pascalliza2209
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программированияguestfc8ae0
 
Отладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программОтладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программTatyanazaxarova
 
Cреда программирования
Cреда программированияCреда программирования
Cреда программированияirina8682
 
презентация языки программирования
презентация языки программированияпрезентация языки программирования
презентация языки программированияnhfkzkz
 
Построение систем автоматического протоколирования Си/Си++ кода
Построение систем автоматического протоколирования Си/Си++ кодаПостроение систем автоматического протоколирования Си/Си++ кода
Построение систем автоматического протоколирования Си/Си++ кодаTatyanazaxarova
 
Programming history. Algorithm
Programming history. AlgorithmProgramming history. Algorithm
Programming history. AlgorithmIhor Porotikov
 
Презентация. Основы Pascal
Презентация. Основы PascalПрезентация. Основы Pascal
Презентация. Основы PascalEvgen67
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Tatyanazaxarova
 
Candidates for-php-developers-tests
Candidates for-php-developers-testsCandidates for-php-developers-tests
Candidates for-php-developers-testsguest5fa21c
 
паскаль язык структурного программирования
паскаль   язык структурного программированияпаскаль   язык структурного программирования
паскаль язык структурного программированияЕлена Ключева
 
языки программирования
языки программированияязыки программирования
языки программированияanastastish
 

Mais procurados (19)

Язык программирования Pascal
Язык программирования PascalЯзык программирования Pascal
Язык программирования Pascal
 
Programming Concepts
Programming ConceptsProgramming Concepts
Programming Concepts
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.
 
основы програмирования Pascal
основы програмирования Pascalосновы програмирования Pascal
основы програмирования Pascal
 
лек13 3
лек13 3лек13 3
лек13 3
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программирования
 
Отладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программОтладка и оптимизация многопоточных OpenMP-программ
Отладка и оптимизация многопоточных OpenMP-программ
 
Cреда программирования
Cреда программированияCреда программирования
Cреда программирования
 
презентация языки программирования
презентация языки программированияпрезентация языки программирования
презентация языки программирования
 
Построение систем автоматического протоколирования Си/Си++ кода
Построение систем автоматического протоколирования Си/Си++ кодаПостроение систем автоматического протоколирования Си/Си++ кода
Построение систем автоматического протоколирования Си/Си++ кода
 
Programming history. Algorithm
Programming history. AlgorithmProgramming history. Algorithm
Programming history. Algorithm
 
Презентация. Основы Pascal
Презентация. Основы PascalПрезентация. Основы Pascal
Презентация. Основы Pascal
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциям
 
C++ теория
C++ теорияC++ теория
C++ теория
 
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
 
Candidates for-php-developers-tests
Candidates for-php-developers-testsCandidates for-php-developers-tests
Candidates for-php-developers-tests
 
Step 5
Step 5Step 5
Step 5
 
паскаль язык структурного программирования
паскаль   язык структурного программированияпаскаль   язык структурного программирования
паскаль язык структурного программирования
 
языки программирования
языки программированияязыки программирования
языки программирования
 

Destaque

Write Your Own Compiler in 24 Hours
Write Your Own Compiler in 24 HoursWrite Your Own Compiler in 24 Hours
Write Your Own Compiler in 24 HoursPhillip Trelford
 
Esprima - What is that
Esprima - What is thatEsprima - What is that
Esprima - What is thatAbhijeet Pawar
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easyIngvar Stepanyan
 
Write Your Own JVM Compiler
Write Your Own JVM CompilerWrite Your Own JVM Compiler
Write Your Own JVM CompilerErin Dees
 

Destaque (6)

04 j flex
04 j flex04 j flex
04 j flex
 
Write Your Own Compiler in 24 Hours
Write Your Own Compiler in 24 HoursWrite Your Own Compiler in 24 Hours
Write Your Own Compiler in 24 Hours
 
Esprima - What is that
Esprima - What is thatEsprima - What is that
Esprima - What is that
 
Lexing and parsing
Lexing and parsingLexing and parsing
Lexing and parsing
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easy
 
Write Your Own JVM Compiler
Write Your Own JVM CompilerWrite Your Own JVM Compiler
Write Your Own JVM Compiler
 

Semelhante a Custom Language Plugin for JetBrains IDEA

Применение статического анализа при разработке программ
Применение статического анализа при разработке программПрименение статического анализа при разработке программ
Применение статического анализа при разработке программTatyanazaxarova
 
Inroducing SAP ABAP - Presentation with basics SAP ABAP
Inroducing SAP ABAP - Presentation with basics SAP ABAPInroducing SAP ABAP - Presentation with basics SAP ABAP
Inroducing SAP ABAP - Presentation with basics SAP ABAPmikhailshurgulaya
 
10 компонентные и офисные приложения на платформе microsoft
10 компонентные и офисные приложения на платформе microsoft10 компонентные и офисные приложения на платформе microsoft
10 компонентные и офисные приложения на платформе microsoftKewpaN
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
Язык программирования SocLang (VKLang)
Язык программирования SocLang (VKLang)Язык программирования SocLang (VKLang)
Язык программирования SocLang (VKLang)Alexander Petrov
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.Igor Shkulipa
 
Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?COMAQA.BY
 
9 структура компонентных приложений
9 структура компонентных приложений9 структура компонентных приложений
9 структура компонентных приложенийKewpaN
 
основы ооп на языке C#. часть 1. введение в программирование
основы ооп на языке C#. часть 1. введение в программированиеосновы ооп на языке C#. часть 1. введение в программирование
основы ооп на языке C#. часть 1. введение в программированиеYakubovichDA
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language RuntimeGetDev.NET
 
Zend Framework и мультиязычность
Zend Framework и мультиязычностьZend Framework и мультиязычность
Zend Framework и мультиязычностьStepan Tanasiychuk
 
Ayan9r1 po(1)
Ayan9r1 po(1)Ayan9r1 po(1)
Ayan9r1 po(1)Ayan_R
 

Semelhante a Custom Language Plugin for JetBrains IDEA (20)

Применение статического анализа при разработке программ
Применение статического анализа при разработке программПрименение статического анализа при разработке программ
Применение статического анализа при разработке программ
 
Inroducing SAP ABAP - Presentation with basics SAP ABAP
Inroducing SAP ABAP - Presentation with basics SAP ABAPInroducing SAP ABAP - Presentation with basics SAP ABAP
Inroducing SAP ABAP - Presentation with basics SAP ABAP
 
10 компонентные и офисные приложения на платформе microsoft
10 компонентные и офисные приложения на платформе microsoft10 компонентные и офисные приложения на платформе microsoft
10 компонентные и офисные приложения на платформе microsoft
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 
Интегрированная среда для языка Рефал
Интегрированная среда для языка РефалИнтегрированная среда для языка Рефал
Интегрированная среда для языка Рефал
 
Net framework
Net frameworkNet framework
Net framework
 
Язык программирования SocLang (VKLang)
Язык программирования SocLang (VKLang)Язык программирования SocLang (VKLang)
Язык программирования SocLang (VKLang)
 
Symfony 3
Symfony 3Symfony 3
Symfony 3
 
43828
4382843828
43828
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 
лек13 6
лек13 6лек13 6
лек13 6
 
Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?
 
9 структура компонентных приложений
9 структура компонентных приложений9 структура компонентных приложений
9 структура компонентных приложений
 
основы ооп на языке C#. часть 1. введение в программирование
основы ооп на языке C#. часть 1. введение в программированиеосновы ооп на языке C#. часть 1. введение в программирование
основы ооп на языке C#. часть 1. введение в программирование
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language Runtime
 
Zend Framework и мультиязычность
Zend Framework и мультиязычностьZend Framework и мультиязычность
Zend Framework и мультиязычность
 
RichFaces: обзор
RichFaces: обзорRichFaces: обзор
RichFaces: обзор
 
Ayan9r1 po(1)
Ayan9r1 po(1)Ayan9r1 po(1)
Ayan9r1 po(1)
 
Lecture 11 1
Lecture 11 1Lecture 11 1
Lecture 11 1
 

Custom Language Plugin for JetBrains IDEA

  • 1. Custom Language Plugin для Jetbrains IDEA Сбербанк Технологии Александр Засташков 2015
  • 2. Область применения 1. Proprietary programming languages Software AG Apama Event Processing Language © 2. Domain specific languages 3. Системы проверки синтаксиса 4. Трансляторы из одного языка в другой
  • 3. Apama EPL Plugin 1. Подсветка синтаксиса 2. Проверка синтаксиса 3. Навигация по ссылкам – Программные конструкции определенные внутри одного файла – Внешние ссылки Apama Event Processing Language on Event A Event A Event B on Event B correlator monitors
  • 4.
  • 5. Теория • Alfred V. Aho, Compilers: Principles, Techniques & Tools • Terence Parr, Language Implementation Patterns • https://confluence.jetbrains.com/display/IDEA DEV/Developing+Custom+Language+Plugins+f or+IntelliJ+IDEA
  • 6. поток символов Лексический анализатор (Lexer) Синтаксический анализатор (Parser) поток лексем синтаксическое дерево Остальные фазы компиляции Процесс компиляции Таблица символов
  • 7. Лексический анализатор Пусть исходная программа содержит инструкцию присваивания: position = initial + rate * 60 Символы в этом присваивании могут быть сгруппированы в следующие лексемы и отображены в следующие токены, передаваемые синтаксическому анализатору: 1. position  (id, 1) 2. =  (=, нет значения атрибута)  (=) 3. initial -> (id, 2) 4. +  (+) 5. rate  (id, 3) 6. *  (*) 7. 60  (number, 4) Выходной поток токенов после лексического анализа будет иметь вид: (id, 1) (=) (id, 2) (+) (id, 3) (*) (id, 4) 1 position … 2 initial … 3 rate … 4 60 … … … …
  • 8. Синтаксический анализатор Синтаксический анализатор использует первые компоненты токенов, полученных при лексическом анализе, для создания древовидного промежуточного представления, которое описывает грамматическую структуру потока токенов. поток токенов (id, 1) (=) (id, 2) (+) (id, 3) (*) (id, 4) синтаксическое дерево (=) / (id, 1) (+) / (id, 2) (*) / (id, 3) (id, 4)
  • 9. Грамматика Иерархическая структура множества конструкций языка программирования может быть описана с помощью контекстно свободных грамматик, состоящих из: 1. Терминалы 2. Нетерминалов 3. Продукции 4. Один из нетерминальных символов, указываемый как стартовый или начальный. boolean_literal ::= true | false decimal_literal ::= ( '-' | '+' )* ( DECIMAL | ( DIGIT+ DOT? ) ) где DIGIT = 'regexp:[0-9]+'
  • 10. Грамматика Грамматика определяется перечислением ее продукций, причем первой указывается продукция для стартового символа. Грамматика выводит, или порождает, строки, начиная со стартового символа и неоднократно замещая нетерминалы телами продукций этих нетерминалов. Строки токенов, порождаемые из стартового символа, образуют язык, определяемый грамматикой. Грамматика может быть описана в форме Бэкуса — Наура или представлена графически в виде railroad diagram. program ::= package_specification? using_declaration+ ( event_declaration+ | monitor_declaration )
  • 11. Разбор (Parsing) Синтаксический анализ, или разбор, представляет собой выяснение для полученной строки терминалов способа ее вывода из стартового символа грамматики. Если строка не может быть выведена из стартового символа, синтаксический анализатор сообщает об ошибке в строке. Задачу синтаксического анализа можно представить как построение дерева разбора. S ::= xyz | aBC грамматика: B ::= c | cd строка: acddf C ::= eg | df S S S S S | / | / | / | / | a B C a B C a B C a B C | | / | / | | c c d c d d f
  • 12. Инструменты 1. Jetbrains IDEA Community Edition • Языково-независимая часть платформы • Специфическая для конкретного языка 2. git clone git://git.jetbrains.org/idea/community.git idea 3. Плагины: • Plugin DevKit Набор инструментов для разработки плагинов под платформу Intellij IDEA • Grammar-Kit Плагин для описания грамматик в форме Бэкуса — Наура • PsiViewer Intellij IDEA Program Structure Interface
  • 15. Язык EPL и иконка
  • 18. EPL Plugin Run/Debug Configuration
  • 19. Запуск плагина Jetbrains IDEA logs: https://devnet.jetbrains.com/docs/DOC-181 При запуске Run / Debug Configuration и создании нового файла с зарегистрированным расширением IDEA автоматически ассоциирует его с разрабатываемым плагином.
  • 20. Реализация лексического анализатора Лексический анализатор (lexer) – база для всего дальнейшего функционала Custom Language Plugin. IDEA вызывает lexer в трех основных контекстах: 1. Подсветка синтаксиса 2. Построение синтаксического дерева файла 3. Построение индекса слов содержащихся в файле Лексический анализатор для IDEA можно создать: 1. Реализацией интерфейса com.intellij.lexer.Lexer 2. Используя генератор лексических анализаторов JFlex (jflex.de) JFlex генерирует лексические анализаторы на основе *.flex файлов, которые в свою очередь могут быть сгенерированы из грамматики при помощи IDEA GrammarKit Plugin.
  • 21. Процесс синтаксического анализа в IDEA 1. Построение абстрактного синтаксического дерева (AST), определяющее структуру программы monitor M {  monitor_declaration } | +-- monitor | +-- identifier | +-- { | +-- } 2. Во второй фазе строится PSI (Program Structure Interface) дерево поверх AST, добавляя семантику и методы для манипуляции языковыми конструкциями Синтаксический анализатор для IDEA можно создать: 1. Реализацией интерфейса com.intellij.lang.PsiParser 2. Сгенерировать из грамматики используя IDEA Grammar-Kit Plugin
  • 22. Типы лексем и связанных с AST узлами элементов
  • 23. PsiViewer Plugin Для отладки PSI структур удобно использовать IDEA PsiViewer Plugin. С его помощью можно смотреть структуру PSI дерева для целевого языка, свойства каждого PSI элемента и отображение исходного кода на соответствующую структуру PSI элементов.
  • 24. Грамматика EPL Грамматика EPL описывается в файле epl.bnf. На ее основе средствами IDEA Grammar-Kit Plugin возможна генерация совместимых с платформой лексических и синтаксических анализаторов. BNF файл грамматики состоит из трех разделов: 1. Секции заголовка: parserClass="com.intellij.epl.parser.EplParser“ psiClassPrefix="Epl" psiImplClassSuffix="Impl" psiPackage="com.intellij.epl.psi" psiImplPackage="com.intellij.epl.psi.impl" elementTypeHolderClass="com.intellij.epl.psi.EplTypes" elementTypeClass="com.intellij.epl.psi.EplElementType" tokenTypeClass="com.intellij.epl.psi.EplTokenType" psiImplUtilClass="com.intellij.epl.psi.EplPsiImplUtil"
  • 25. Грамматика EPL 2. Секции лексем, которые возможно при необходимости задать регулярными выражениями для удобства их последующего использования: tokens=[ ID = 'regexp:[a-zA-Z_$][a-zA-Z0-9_$]*' DIGIT = 'regexp:[0-9]+' DECIMAL = 'regexp:[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?' NON_EMPTY_STRING = 'regexp:"([^"]|.)*"' EMPTY_STRING = '""' DOCUMENTATION = 'regexp:/**([^*]|[rn]|(*+([^*/]|[rn])))**+/' BLOCK_COMMENT = 'regexp:/*([^*]|[rn]|(*+([^*/]|[rn])))**+/' LINE_COMMENT = 'regexp://.*' OP_ASSIGNMENT = ":=" OP_PLUS = "+" OP_MINUS = "-" OP_AR_MUL = "*" OP_AR_DIV = "/"
  • 26. Грамматика EPL 3. Непосредственно грамматическими правилами: root ::= program program ::= { package_specification | using_declaration | monitor_declaration | event_declaration | event_instance | DOCUMENTATION | BLOCK_COMMENT | LINE_COMMENT }* package_specification ::= package identifier ( '.' identifier )* ';' identifier ::= ID { methods = [getReference] } monitor_declaration ::= persistent? monitor identifier '{' { import_declaration | event_declaration | variable_declaration | action_definition | DOCUMENTATION | BLOCK_COMMENT | LINE_COMMENT }* '}‘ …
  • 28. Формат flex файлов Flex файл представляет собой спецификацию, на основе которой будет сгенерирован java класс лексического анализатора. Основными его разделами являются: 1. Определение пакета лексического анализатора и импортируемых зависимостей package com.intellij.epl; import com.intellij.lexer.*; import com.intellij.psi.tree.IElementType; import static com.intellij.epl.psi.EplTypes.*; 2. Кода, который следует включить в неизменном виде в создаваемый класс: %{ public _EplLexer() { this((java.io.Reader)null); } %}
  • 29. Формат flex файлов 3. Модификатора доступа создаваемого класса, его имени и реализуемых интерфейсов %public %class _EplLexer %implements FlexLexer 4. Типа элементов создаваемых лексем: %type IElementType 5. Последовательности символов описываемых регулярными выражениями: EOL="r"|"n"|"rn" LINE_WS=[ tf] WHITE_SPACE=({LINE_WS}|{EOL})+ ID=[a-zA-Z_$][a-zA-Z0-9_$]* DIGIT=[0-9]+ DECIMAL=[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?
  • 30. Формат flex файлов 6. Правила и действия %% <YYINITIAL> { {WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; } """" { return EMPTY_STRING; } ":=" { return OP_ASSIGNMENT; } "+" { return OP_PLUS; } … "package" { return PACKAGE; } "using" { return USING; } "persistent" { return PERSISTENT; } … {ID} { return ID; } {DIGIT} { return DIGIT; } {DECIMAL} { return DECIMAL; }
  • 31. Генерация лексического и синтаксического анализаторов 1. Генерация лексического анализатора в IDEA происходит в два этапа:  генерация файла *.flex из файла грамматики *.bnf Grammar-Kit -> Generate JFlex Lexer  генерация лексического анализатора на основе сгенерированного *.flex файла Grammar-Kit -> Run JFlex Generator 2. Синтаксический анализатор генерируется из из файла грамматики *.bnf Grammar-Kit -> Generate Parser Code
  • 32. Реализация класса подсветки синтаксиса Подсветка синтаксиса реализуется отображением классов лексем на соответствующие инстансы com.intellij.openapi.editor.colors.TextAttributesKey
  • 33. Реализация страницы настроек цветовой схемы плагина Необходима реализация com.intellij.openapi.options.colors.ColorSettingsPage
  • 34. Регистрация реализованных точек расширения Для активации реализованных / сгенерированных классов их необходимо зарегистрировать как точки расширения в файле META-INF/plugin.xml
  • 35. Навигация по структуре программы Ссылка (на переменную, метод и т. д. ) представляет собой указатель на один из узлов дерева и может находиться либо в текущем, либо во внешнем файле.
  • 36. Навигация по структуре программы Реализация метода getReference() должна возвращать конкретный узел PSI дерева, который откроется в текстовом редакторе.
  • 37. Что дальше? • Find Usages • Code Completion • Остальные фичи IDEA для Custom Language IntelliJ IDEA Custom Languages repo: https://plugins.jetbrains.com/category/index?pr=idea&category_id=48