Грамматика и парсер 1C (BSL) на основе Lezer. Поддерживает синтаксис языка программирования 1С:Предприятие. Парсер предназначен для использования в веб-приложениях и браузерных редакторах кода.
О Lezer: Lezer — это парсер-генератор от команды CodeMirror, предназначенный для создания эффективных парсеров с поддержкой инкрементального парсинга. Это делает его идеальным выбором для интеграции в веб-редакторы кода, где требуется быстрое обновление синтаксического дерева при каждом изменении текста. Парсер генерируется из декларативной грамматики и предоставляет структурированное дерево разбора (AST) для дальнейшей обработки кода.
- Особенности
- Установка
- Использование
- Поддерживаемые конструкции
- Производительность
- Разработка
- Структура проекта
- ✅ Парсинг BSL кода с поддержкой основных конструкций языка
- ✅ Поддержка русских и английских ключевых слов (регистронезависимо)
- ✅ Инкрементальный парсинг для эффективного обновления дерева при изменениях
- ✅ Визуализация дерева парсинга в веб-интерфейсе
- ✅ Полная поддержка выражений, операторов и структур управления
- ✅ Поддержка комментариев и директив препроцессора
npm installили
yarn installimport { LezerBslParser } from './src/parser/LezerBslParser'
const parser = new LezerBslParser()
const code = `
Процедура Тест()
Перем а = 1;
Возврат а + 2;
КонецПроцедуры
`
const tree = parser.parse(code)
// Работа с деревом парсингаДля эффективного обновления при изменениях в редакторе:
const parser = new LezerBslParser()
let tree = parser.parse(initialCode)
// При изменении кода
const changes = [
{
rangeOffset: 10,
rangeLength: 5,
text: "НовыйТекст"
}
]
tree = parser.update(newCode, changes)Запустите демо-приложение для визуализации дерева парсинга:
npm run devОткройте браузер по адресу, указанному в консоли (обычно http://localhost:5173).
- Процедуры и функции
- Параметры (с модификатором
Знач/Val) - Переменные (
Перем/Var) - Экспортные методы (
Экспорт/Export)
- Условные операторы:
Если/If,ИначеЕсли/ElsIf,Иначе/Else - Циклы:
Пока/While,Для/For(сКаждого/EachиПо/To) - Обработка исключений:
Попытка/Try,Исключение/Except Возврат/Return,ВызватьИсключение/Raise
- Арифметические операции:
+,-,*,/ - Операторы сравнения:
=,<>,>,<,>=,<= - Логические операции:
И/AND,ИЛИ/OR,НЕ/NOT - Вызовы методов и доступ к свойствам
- Индексация массивов
- Литералы: числа, строки,
Истина/True,Ложь/False,Неопределено/Undefined - Создание объектов:
Новый/New
- Однострочные комментарии (
//) - Директивы препроцессора (
#) - Регистронезависимые ключевые слова
Парсер демонстрирует высокую производительность как при полном парсинге, так и при инкрементальных обновлениях:
| Размер файла | Полный парсинг | Инкр. вставка | Инкр. удаление | Лучший метод |
|---|---|---|---|---|
| 93 символов | 🟢 0.04 ms | 🟡 0.16 ms | 🟢 0.03 ms | Удаление |
| 652 символов | 🟢 0.26 ms | 🟡 0.24 ms | 🟢 0.21 ms | Удаление |
| 3.4K символов | 🟡 0.87 ms | 🔴 1.14 ms | 🟢 1.11 ms | Полный |
| 9.4K символов | 🔴 2.02 ms | 🟢 1.15 ms | 🟢 0.98 ms | Удаление |
| 611K символов | 🔴 80.88 ms | 🟢 38.33 ms | 🟡 51.11 ms | Вставка |
Вывод: Инкрементальный парсинг эффективен для файлов >9K символов, показывая ускорение до 2.1x.
Подробные результаты бенчмарков
Модуль: small (93 символов)
| Тест | Операций/сек | Среднее время (ms) | p75 (ms) | p99 (ms) |
|---|---|---|---|---|
| Полный парсинг | 18,625.93 | 0.0537 | 0.0572 | 0.0708 |
| Инкрементальное обновление - вставка | 6,830.76 | 0.1464 | 0.1732 | 0.9030 |
| Инкрементальное обновление - удаление | 21,453.94 | 0.0466 | 0.0489 | 0.0648 |
Модуль: medium (652 символов)
| Тест | Операций/сек | Среднее время (ms) | p75 (ms) | p99 (ms) |
|---|---|---|---|---|
| Полный парсинг | 6,387.01 | 0.1566 | 0.1710 | 0.3532 |
| Инкрементальное обновление - вставка | 3,431.45 | 0.2914 | 0.2975 | 0.9233 |
| Инкрементальное обновление - удаление | 5,974.52 | 0.1674 | 0.2035 | 0.2668 |
Модуль: large (3420 символов)
| Тест | Операций/сек | Среднее время (ms) | p75 (ms) | p99 (ms) |
|---|---|---|---|---|
| Полный парсинг | 1,052.65 | 0.9500 | 1.0442 | 2.6493 |
| Инкрементальное обновление - вставка | 863.53 | 1.1580 | 1.1046 | 2.5731 |
| Инкрементальное обновление - удаление | 1,239.97 | 0.8065 | 0.9917 | 1.3745 |
Модуль: very-large (9433 символов)
| Тест | Операций/сек | Среднее время (ms) | p75 (ms) | p99 (ms) |
|---|---|---|---|---|
| Полный парсинг | 493.96 | 2.0245 | 2.4930 | 3.3026 |
| Инкрементальное обновление - вставка | 867.26 | 1.1531 | 1.3599 | 2.4179 |
| Инкрементальное обновление - удаление | 1,023.69 | 0.9769 | 1.2182 | 1.6887 |
Модуль: big (610980 символов)
| Тест | Операций/сек | Среднее время (ms) | p75 (ms) | p99 (ms) |
|---|---|---|---|---|
| Полный парсинг | 12.36 | 80.88 | 101.40 | 104.05 |
| Инкрементальное обновление - вставка | 26.09 | 38.33 | 56.59 | 68.81 |
| Инкрементальное обновление - удаление | 19.57 | 51.11 | 54.79 | 57.00 |
Для запуска бенчмарков используйте:
npm run test:benchmarkПосле изменения грамматики в src/bsl.grammar:
npm run gen-lezer-bslnpm testnpm run buildnpm run previewlezer-bsl/
├── src/
│ ├── bsl.grammar # Грамматика Lezer для BSL
│ ├── main.ts # Веб-интерфейс для визуализации
│ └── parser/
│ ├── bslParser.ts # Сгенерированный парсер (не редактировать)
│ ├── bslParser.terms.ts
│ └── LezerBslParser.ts # Обёртка с инкрементальным парсингом
├── tests/
│ └── parser.test.ts # Тесты парсера
├── index.html # HTML для демо-приложения
└── package.json