Регулярное выражение для Лексера.
Posted: 29.01.2019 01:08
Я не так давно описывал, что создал и дорабатываю тяжелый самодельный лексер для ECMA6.
Функционал стандартных доступных лексеров для JS мне показался слабо выраженным.
Потому я решил создать структурно-типизированый лексер.
Под структурной типизацией я подразумеваю, определение не только типов данных и ключевых слов,
но и градацию этих данных и слов по областям применения в коде.
На текущий момент уже определены все доступные Объекты для самой спецификации, а так же все доступные объекты для Клиентских DOM, BOM.
Это же касается и всех доступных методов и пропсов. Так же проработаны отображения в древе всех объявлений переменных, функций (как явных так и анонимных), классов и т.д.
Планирую внести еще подсветку для конструкций REACT и несколько других фреймворков.
Столкнулся с проблемой, из-за которой не могу доработать Шаблоны и части фреймворков.
Суть проблемы - правильная подсветка сложных шаблонов.
Сейчас приведу пример, решение которого позволит закончить работу над лексером.
Инструкции и рекомендации все прочитаны (даже EControl в разрезе этого вопроса поднят).
Просто не хватает креативности для создания регулярки. С чем и прошу помочь.
В новых спецификациях ecma есть новый вид строки через обратные кавычки `str` с применением шаблонов по типу ${value}
Вот пример разбираемого текста:
В этом примере нужно подсветить только текстовую составляющую , а значения паттерна ${value} (не сам паттерн а только _inside части), подсвечивать остальными правилами лексера.
Если я правильно понимаю работу парсера лексеров, то подсветку можно задавать двумя способами:
1. Применить стиль на парсер строки (закладка Парсер).
2. Применить стиль на Шаблон правил (закладка Правила).
Причем следующий парсер или правило переназначает стиль, что был наложен предыдущим Парсером (правилом).
Если использовать простой парсер / (?s)(`) (.)*? (\1|\Z) / для выделения всего блока текста,
то он перезапишет подсветку паттерна ${value} и все в пределах `` будет засвечно одним стилем.
и наоборот, если поставить парсер строки приоритетом ниже то паттерн ${value} перезапишет парсер строки,
что приведет к тому, что покрашен будет только само ${value} , а текст вокруг потеряет подсветку и станет цветом по умолчанию.
Значит, что бы внутренние значения шаблонов могли подсвечиваться по ECMA,
нам нужно составить такое регулярное выражение, что бы строка парсилась
от знака ` до сочетания ${ и продолжала краситься после } и аж до закрывающего `
Получается у нас есть 4 определения для регулярного выражения:
видно что у нас есть по два открывающих и два закрывающих определения, их можно сгруппировать
а так же для мульти-строк добавим ключ (?s) что бы точка искала и переводы строк.
Такой шаблон работает хорошо, но из-за (\}) текст начинает парситься также после определения классов (в примере это "problem_place = `problem_text`;" ). Так как в классе есть этот же символ.
значит для открывающего (\}) определения нужно подставить (?<=) проверку на принадлежность знака } к паттерну ${value}
В проверку вставляем начало паттерна и получается (?<=\$\{.*?) (\})
Отлично, теперь после SomeClass1 текст не парсится, но вот после SomeClass2 текст начинает парситься, так как из-за ключа (?s) , парсер в тексте находит паттерн ${multiline_bottom} и правило срабатывает в TRUE и подсвечивает стилем код, идущий после ...some_value'}. Корень проблемы в том, что мы используем (.*?) для определения текста. Это необходимо потому, что внутри ${value} могут быть не только название переменной, но так же вычисляемые выражения с разными знаками и переводами строки.
Вот это и есть проблема.
Помогите додумать регулярку.
Либо если есть возможность, дать ссылку на Лексер, с решением этой проблемы через Правила.
Я уже 4 дня шаманю, не получается никак. Пробовал уже костыль делать, СабЛексер от ` до ` но там свои проблемы и нюансы.
Решение этой проблемы позволит применить аналогию для решения Шаблонов для остальных фреймворков.
п.с. В идеале нужно ставить еще проверку на весь патерн перед закрывающим ` и явно указывать пробельные символы до и после фигурных скобок, но я решил свести пример к минимальному значению.
Функционал стандартных доступных лексеров для JS мне показался слабо выраженным.
Потому я решил создать структурно-типизированый лексер.
Под структурной типизацией я подразумеваю, определение не только типов данных и ключевых слов,
но и градацию этих данных и слов по областям применения в коде.
На текущий момент уже определены все доступные Объекты для самой спецификации, а так же все доступные объекты для Клиентских DOM, BOM.
Это же касается и всех доступных методов и пропсов. Так же проработаны отображения в древе всех объявлений переменных, функций (как явных так и анонимных), классов и т.д.
Планирую внести еще подсветку для конструкций REACT и несколько других фреймворков.
Столкнулся с проблемой, из-за которой не могу доработать Шаблоны и части фреймворков.
Суть проблемы - правильная подсветка сложных шаблонов.
Сейчас приведу пример, решение которого позволит закончить работу над лексером.
Инструкции и рекомендации все прочитаны (даже EControl в разрезе этого вопроса поднят).
Просто не хватает креативности для создания регулярки. С чем и прошу помочь.
В новых спецификациях ecma есть новый вид строки через обратные кавычки `str` с применением шаблонов по типу ${value}
Вот пример разбираемого текста:
Code: Select all
class SomeClass1 {'some_prop : some_value'};
let problem_place = `problem_text`;
` solo_text `
` left_text ${left_inside} centr_text ${right_inside} right_text`
` start_text ${top_inside}
midle_text ${bottom_inside}
end_text`
class SomeClass2 {'some_prop : some_value'};
let problem_place = `problem_text`;
Если я правильно понимаю работу парсера лексеров, то подсветку можно задавать двумя способами:
1. Применить стиль на парсер строки (закладка Парсер).
2. Применить стиль на Шаблон правил (закладка Правила).
Причем следующий парсер или правило переназначает стиль, что был наложен предыдущим Парсером (правилом).
Если использовать простой парсер / (?s)(`) (.)*? (\1|\Z) / для выделения всего блока текста,
то он перезапишет подсветку паттерна ${value} и все в пределах `` будет засвечно одним стилем.
и наоборот, если поставить парсер строки приоритетом ниже то паттерн ${value} перезапишет парсер строки,
что приведет к тому, что покрашен будет только само ${value} , а текст вокруг потеряет подсветку и станет цветом по умолчанию.
Значит, что бы внутренние значения шаблонов могли подсвечиваться по ECMA,
нам нужно составить такое регулярное выражение, что бы строка парсилась
от знака ` до сочетания ${ и продолжала краситься после } и аж до закрывающего `
Получается у нас есть 4 определения для регулярного выражения:
Code: Select all
1) ` txt ` == /(`) (.*?) (`)/
2) ` txt ${ == /(`) (.*?) (\$\{)/
3) } txt ` == /(\}) (.*?) (`)/
4) } txt ${ == /(\}) (.*?) (\$\{)/
а так же для мульти-строк добавим ключ (?s) что бы точка искала и переводы строк.
Code: Select all
(?s)
( (`) | (\}) )
(.*?)
( (\$\{) | (`) )
значит для открывающего (\}) определения нужно подставить (?<=) проверку на принадлежность знака } к паттерну ${value}
В проверку вставляем начало паттерна и получается (?<=\$\{.*?) (\})
Code: Select all
(?s)
( (`) | (?<=\$\{.*)\} )
(.*?)
( (\$\{) | (`) )
Вот это и есть проблема.
Помогите додумать регулярку.
Либо если есть возможность, дать ссылку на Лексер, с решением этой проблемы через Правила.
Я уже 4 дня шаманю, не получается никак. Пробовал уже костыль делать, СабЛексер от ` до ` но там свои проблемы и нюансы.
Решение этой проблемы позволит применить аналогию для решения Шаблонов для остальных фреймворков.
п.с. В идеале нужно ставить еще проверку на весь патерн перед закрывающим ` и явно указывать пробельные символы до и после фигурных скобок, но я решил свести пример к минимальному значению.