Как стать автором
Обновить

Комментарии 7

Реализовать парсинг языка разметки в обычный текст и добавить маппинг индексов из естественного текста в исходный текст.

А зачем парсить именно в текст, а не в дерево разбора? Последнее кажется более логичным вариантом, ведь в нем можно помечать какие элементы нужно проверять, какие — нет (ссылки, цитаты), а какие — проверять по особому (исходный код). В перспективе такое дерево можно использовать и для других функций (например, линтер или перевод). Я рассмотрел такой метод, особенно если Grazie позиционируется под IT.


Но реализация парсера для LaTeX оказалась сложнее, потому что LaTeX не имеет контекстно-свободной грамматики.

Может LaTeX и сложнее, но полноценной контекстно-свободной грамматики под Markdown я тоже не встречал. Как-то даже сам пытался ее написать, но ничего не вышло. В нем много моментов, где требуется дополнительный код для проверки переносов, пробелов и других штук (семантических предикатов).


Как я уже написала, Tree-sitter генерирует парсер на C. Для использования в JavaScript у него есть биндер, который генерирует .wasm файл, и его уже можно запускать в браузере.

Даже странно, что нет биндера в нативный JavaScript. Я конечно толком не изучал эту тему, но этот биндер разве нельзя заюзать node-tree-sitter? nodejs вроде можно адаптировать в браузерный формат.


Я выбрала последний вариант и переписала грамматику из .js в .g4 для ANTLR4. Он генерирует лексер, парсер и визитер на JS, а с помощью antlr4ts можно это всё сгенерировать на TypeScript. Проблема была в том, что одна страница латеха обрабатывалась около 700 мс, а после упрощения грамматики получилось ускорить всего в 2 раза. С такой скоростью обработки страница сайта зависала после каждого введенного символа.

А можно взглянуть на грамматику и сам парсер? Возможно смогу помочь соптимизировать, т.к. 700 мс — это очень много.


В итоге было принято решение отказаться от написания парсера и построения AST. Вместо этого было бы достаточно удалять синтаксические конструкции с помощью регулярных выражений и таким образом получать естественный текст.

А заюзать ANTLR лексер без парсера нельзя было? Он как правило намного легче и быстрее парсера. Все-таки регулярные выражения — это крайний и не лучший вариант.

Добрый день! Простите за долгий ответ, сессия... стажировка....

А зачем парсить именно в текст, а не в дерево разбора?

Парсится в AST само собой и, как Вы хорошо подметили, "в нем можно помечать какие элементы нужно проверять, какие — нет". Так делалось, например, в маркдауне. Там использовалась библиотека от unified с набором методов, в которых можно указать какие вершины при разборе не надо рассматривать. И уже из AST после выкидывания ненужных вершин получался естественный текст, который перенаправлялся в существующий функционал для проверки.

Я конечно толком не изучал эту тему, но этот биндер разве нельзя заюзать node-tree-sitter?

В проекте нет node.js и его не хотели добавлять.

А можно взглянуть на грамматику и сам парсер?

Не могу ответить на такой вопрос, тк уже не в проекте :(

700 мс — это очень много.

Там уже не 700, а 5мс :) 700мс было как раз при самой первой реализации с ANTLR.

А заюзать ANTLR лексер без парсера нельзя было?

Была такая мысль, да. Но я решила сделать свой парсер и у него была такая хорошая производительность относительно ANTLR, что оставили его. Интересный вопрос: а насколько быстрее лексер ANTLR без парсера чем с ним? У меня не получилось с ходу найти какие-либо метрики.

В проекте нет node.js и его не хотели добавлять.

А эта версия в браузере разве не может запускаться (помимо node.js)?


Там уже не 700, а 5мс :) 700мс было как раз при самой первой реализации с ANTLR.

Ну так написано, что после упрощения грамматике удалось ускорить в два раза, т.е. в 350мс, а это все равно долго. И из-за этого вы перешли на регулярки как понял.


Интересный вопрос: а насколько быстрее лексер ANTLR без парсера чем с ним?

Существенно быстрее, т.е. лексер — это, можно сказать, регулярка, которые покрывает весь текст, а не часть (хотя ANTLR лексер на самом деле может быть контекстно-свободным, но это не суть). И работает даже лучше обычных регулярок, т.к. при захвате символов учитываются все токены, а не один. В результате его работы получается линейная структура из токенов. А парсер возвращает древовидное представление, в нем могут быть возвраты, скорость работы медленней.

А эта версия в браузере разве не может запускаться (помимо node.js)?

Запуск в браузере требовал дополнительного разрешения на запуск файлов. Это увеличивает время проверки каждой версии плагина в Гугле :(

Ну так написано, что после упрощения грамматике удалось ускорить в два раза, т.е. в 350мс, а это все равно долго. И из-за этого вы перешли на регулярки как понял.

Да, так и было.

Существенно быстрее, т.е. лексер — это, можно сказать, регулярка, которые покрывает весь текст, а не часть (хотя ANTLR лексер на самом деле может быть контекстно-свободным, но это не суть). И работает даже лучше обычных регулярок, т.к. при захвате символов учитываются все токены, а не один. В результате его работы получается линейная структура из токенов. А парсер возвращает древовидное представление, в нем могут быть возвраты, скорость работы медленней.

Звучит круто, спасибо за ответ! Жаль не успели попробовать и проверить на практике.

Полноценный парсер теха — это большая головная боль, особенно когда его потом надо во что-то сконвертировать. Единственный проект, который более или менее с этим справляется — это https://dlmf.nist.gov/LaTeXML/. Там компилятор теха в XML, из которого потом можно сделать человека (после доработки напильником).

А точно ли васм это проблема? Писали расширение с ядром на раст и все изменения рассматривают не больше, чем за сутки

Я не помню уже что конкретно в коде требовалось, но суть в том, что нужно было доп. разрешение на использование wasm файла и это могло увеличить время проверки плагина в Гугле. Может быть это бы также были сутки, но кто знает)

Зарегистрируйтесь на Хабре , чтобы оставить комментарий