Парсер языка 1С и транслятор в PowerShell

Программирование - Инструментарий

Недавно мне пришла в голову безумная идея написать транслятор языка 1С в PowerShell. Причем сделать это штатными средствами платформы. Вай нот? Делюсь результатами внезапного спринта.

Что это и зачем это?

Это внешняя обработка, которая позволяет из кода на языке 1С получить код на PowerShell.
Основная изначальная идея - облегчение написания скриптов на PowerShell. Правда в процессе разработки появились и другие идеи...

Внимание! Проект находится на самом раннем этапе разработки со всеми вытекающими...

Причем тут PowerShell?

PowerShell - это пожалуй одно из лучших средств для автоматизации рутинных задач.
Язык очень мощный. Он всегда под рукой в операционной системе Windows и недавно стал доступен в других операционных системах.
PowerShell прекрасен. Но в то же время он очень необычный. Программировать на нем без гугления довольно трудно.

И это всё?

Нет. Обработка логически состоит из двух частей:

  • Один фронтенд - парсер языка 1С
  • Несколько бакендов - генераторов кода

Парсер по исходному коду строит абстрактное синтаксическое дерево, которое может быть передано бакенду для генерации кода.
Транслятор в PowerShell - это только один из возможных бакендов.

Слова непонятные... Ну показывай, что там у тебя...

Обработка выглядит так:
В поле Source (1) вводим код на языке 1С. В поле Output (2) выбираем что хотим увидеть. Например, лексемы как на скриншоте (последовательность лексем - это результат лексического анализа). Далее нажимаем кнопку Translate (3). Результат трансляции будет выведен в поле Result (4).
Формат вывода лексем следующий: <номер строки исходного кода>: <название лексемы> -- `<лексема>`

Что есть кроме лексем?

В поле Output на данный момент такой набор:

  • Lexems - последовательность лексем
  • AST - абстрактное синтаксическое дерево
  • BSL - результат трансляции в язык 1С
  • PS - результат трансляции в язык PowerShell

Что это за дерево такое?

Это специальная структура данных, которая по своей организации напоминает дерево. Узлы дерева - это синтаксические элементы исходного кода.
Почитать об этом можно на википедии: https://ru.wikipedia.org/wiki/Абстрактное_синтаксическое_дерево

Предлагаю взглянуть на простой пример AST:

Обработка выводит AST в формате JSON.

То же самое дерево можно изобразить графически:
Как видно из рисунков, дерево довольно прямолинейно отражает структуру исходного кода. По крайней мере это не далеко от того, как мы сами себе представляем структуру кода.
Абстрактным дерево называется потому что оно обычно содержит не всю информацию об исходном коде. Другими словами, в точности воспроизвести по дереву исходный код не всегда возможно. Например, в дереве выражения могут быть упрощены (не в ущерб их правильности).

Ну OK. А что-то сложнее этого примера обработка умеет?

Конечно! Например, можно получить AST исходного кода самой обработки:

Кроме того работа обработки проверялась на модулях вплоть до 60 000 строк исходного кода (общие модули из ERP).

Так что там с PowerShell?

На данный момент транслятор находится на начальной стадии разработки. В целом трансляция всех синтаксических конструкций уже работает. Но пользоваться этим пока, к сожалению, нельзя. Предстоит еще много работы. Нужно, как минимум, реализовать трасляцию встроенных функций 1С для работы с примитивными типами. А потом еще работу с массивами, структурами и прочим базовым окружением языка 1С.

Да и вообще в PowerShell полно тонких моментов, которые предстоит победить.

Выглядит результат трансляции сейчас так:

Ну, допустим. А транслятор в язык 1С-то для чего?

Дело в том, что обработка парсит не совсем язык 1С (Извиняюсь за желтый заголовок статьи).
На самом деле это новый язык OneShell, который является расширением языка 1С (именно благодаря этому код на 1С парсер тоже переваривает).
Отличия от языка 1С следующие:

  • Точка с запятой не обязательна (даже если два оператора на одной строке)
  • При объявлении переменной возможна ее инициализация
  • Добавлена конструкция Case When Then Else EndCase
  • Возможны параллельные присваивания (семантика PowerShell)
  • Функции могут возвращать несколько значений (семантика PowerShell)
  • Добавлена инструкция +=
  • Параметры передаются всегда по значению (семантика PowerShell). Ключевое слово Val игнорируется
  • Изменен приоритет оператора НЕ

Расширения в основном направлены на удобство и более глубокую поддержку возможностей PowerShell.
Трансляция в 1С на данный момент учитывает не все возможности OneShell (впрочем трансляция в PS тоже). Делалась она для тестирования работы парсера на языке 1С.

Какая польза от всей этой чепухи?

В текущем состоянии проекта пользы действительно никакой нет. Но в умелых руках обработка может послужить базой для других разработок. Быть может кто-то реализует оптимизатор кода 1С или статический анализатор.

Делалось это just for fun. Устроил себе хакатон от скуки. А статью решил написать чтобы узнать мнение сообщества о данном начинании. Востребован ли парсер? А транслятор? Интересуют ли подробности?

Обработка прикреплена к статье. Баги просьба писать тут: https://github.com/tsukanov-as/OneShell/issues

Прошу прощения за сумбур.

Скачать файлы

Наименование Файл Версия Размер
OneShell.epf
.epf 17,69Kb
07.08.17
6
.epf 17,69Kb 6 Скачать

См. также

Комментарии
1. Сергѣй Батанов (baton_pk) 208 07.08.17 10:23 Сейчас в теме
Изменен приоритет оператора НЕ

Это плохо. По-моему, стоит придерживаться совместимости кода.
2. Александр Цуканов (tsukanov) 34 07.08.17 10:39 Сейчас в теме
(1) Согласен что сомнительно. Я думаю над этим.
3. Артур Аюханов (artbear) 877 07.08.17 10:49 Сейчас в теме
Не в обиду автору, но OneScript рулит, полная совместимость с языком 1С + много собственных библиотек
4. Александр Цуканов (tsukanov) 34 07.08.17 10:59 Сейчас в теме
(3) Рулит, да )
У OneShell те же цели, но немного другой подход.
Вы не будете связаны по рукам и ногам реализацией OneShell.
Ведь результат - это код на PowerShell, который можно править.
А еще PowerShell - это очень богатый бакенд с прямым доступом к .NET
Добавлять поддержку новых возможностей и библиотек можно будет очень быстро.
Ну и OneShell изначально задуман как язык с большими возможностями чем 1С.
Например, вы сможете создавать массивы так:
x = 1, 2, 3, 4, 5
CyberCerber; +1 Ответить 2
5. Сергѣй Батанов (baton_pk) 208 07.08.17 11:04 Сейчас в теме
(4)
Добавлять поддержку новых возможностей и библиотек можно будет очень быстро.

вот тут вас ждут боль и разочарование :) продумывать архитектуру создания и подключения библиотек - тот ещё головняк.
6. Александр Цуканов (tsukanov) 34 07.08.17 11:11 Сейчас в теме
(5) Представляю :) Ну по крайней мере будет не скучно ;)
7. Сергѣй Батанов (baton_pk) 208 07.08.17 11:18 Сейчас в теме
(6) не скучно - это здорово. Лишь бы не заглохло, как например https://infostart.ru/public/558205/ , или https://infostart.ru/public/190148/ , или иные проекты.

Если что, заглядывайте к нам: https://github.com/EvilBeaver/OneScript и https://gitter.im/EvilBeaver/OneScript
kostyaomsk; artbear; +2 Ответить 2
8. Александр Цуканов (tsukanov) 34 07.08.17 11:20 Сейчас в теме
(7) Заглохнет или нет - зависит от заинтересованности сообщества (наверно).
Обещать ничего не буду.

Если что

OK )
9. Артур Аюханов (artbear) 877 07.08.17 11:22 Сейчас в теме
(4) Я, как некоторые из нас, пользовался и переболел PowerShell.
Даже целый продукт по автообновлению 1С 77 на 3000 рабочих мест сделал на PowerShell

главная беда Powershell - его синтаксис слишком уж необычен, и пользуясь им периодически, каждый раз приходится делать серьезные усилия для восстановления знаний по языку и библиотекам.

Поэтому я практически отказался от его использования уже года четыре как :(
и в основном пользуюсь скриптами OneScript + командными файлами
10. Артур Аюханов (artbear) 877 07.08.17 11:24 Сейчас в теме
(7) Сергей и сам в свое время писал язык, аналог 1С, так что знает, о чем говорит "лишь бы не заглохло" :)
11. Андрей Овсянкин (Evil Beaver) 4201 07.08.17 11:28 Сейчас в теме
Вэлкам, чо. А вообще, вы бы добили прямой проброс .net классов в 1script, вот польза была бы всем - не рассказать. Там и осталось то всего ничего - убедиться, что односкриптовый managed com нормально модет рефлексировать и обычные .net классы. И если что, допилить его.
12. Сергѣй Батанов (baton_pk) 208 07.08.17 11:30 Сейчас в теме
(11) никогда бы не подумал, что дам эту ссылку тебе https://github.com/EvilBeaver/OneScript/issues :-D
13. Александр Цуканов (tsukanov) 34 07.08.17 11:33 Сейчас в теме
(11) Я, к несчастью, очень плохо знаю C#. Доводилось на нем писать всего один раз ~200 строк. Погружаться в изучение пока нет мотивации.
14. Андрей Овсянкин (Evil Beaver) 4201 07.08.17 12:23 Сейчас в теме
15. Андрей Овсянкин (Evil Beaver) 4201 07.08.17 12:25 Сейчас в теме
(13) Я его вообще не знал, пока узнать не захотелось. Тот же 1С, только нерусский.
16. Сергѣй Батанов (baton_pk) 208 07.08.17 12:37 Сейчас в теме
(13)
(15)
+1, погрузился в C# только ради Односкрипта, до этого разве что лабораторные студентам за сто рублей клепал.
17. Александр Цуканов (tsukanov) 34 07.08.17 12:47 Сейчас в теме
(15)
(16)
Да я в общем то могу на нем писать. Сам язык и концепции мне знакомы (по аналогам в других языках).
Не шарю только в библиотеках. Совсем.
Скажем так... На текущий момент для меня фан - это делать странные вещи на ограниченном языке 1С )))
18. Сергѣй Батанов (baton_pk) 208 07.08.17 12:56 Сейчас в теме
(17)
Идея для фана: Сделайте генератор на язык 1С, но без подпрограмм: чтобы результирующий код мог исполняться 1С-ной командой Выполнить.
То есть пишу с процедурами и функциями, а на выходе код без процедур и функций.

Большое спасибо скажу.
brr; tsukanov; +2 Ответить 1
19. Александр Цуканов (tsukanov) 34 07.08.17 13:57 Сейчас в теме
(18) Вау. Прямо в точку. Это одна из моих идей ))
И, думаю, что смогу это сделать через Goto.
brr; vdscom; +2 Ответить 1
20. Сергѣй Батанов (baton_pk) 208 07.08.17 14:00 Сейчас в теме
(19)
И, думаю, что смогу это сделать через Goto.

Вау. Прямо в точку. Это одна из моих идей. Точнее, единственная.
21. Александр Цуканов (tsukanov) 34 07.08.17 14:07 Сейчас в теме
(20) Ну другие варианты сложно представить, да :D
22. Сергѣй Батанов (baton_pk) 208 07.08.17 14:12 Сейчас в теме
(21) Я ещё думал через Выполнить: в текстовую переменную транслируешь код процедуры, вызов заменяешь на Выполнить(ТекстПроцедуры___ТакаяТоПроцедура).
но лучше метки, хотя там полно развлечений со стэком.
23. Павел Одинцов (Darklight) 07.08.17 14:25 Сейчас в теме
Круто-круто! И парсинг языка 1С в AST дерево - круто! И генерация кода из AST в PowerShell и в 1С тоже - очень круто! И расшиоение языка 1С - сверх круто!
Давай, жги ещё - народу нравится!
А слабы перенять фичи расширениям 1С, как в C# Ну про LINQ я пока промолчу. Но хотя бы анонимные функции, кортежи (хотя, возможно, это уже есть), ленивая инициализация, перегрузка методов ;-)
24. Yauhen Makei (mrDSide) 93 07.08.17 14:57 Сейчас в теме
25. Александр Цуканов (tsukanov) 34 07.08.17 14:58 Сейчас в теме
(23) Тише, тише :D
Пообещать могу только функции высшего порядка и замыкания (без этого в PowerShell никак).
Всё же не стоит плодить сущности без необходимости ;)
26. Yauhen Makei (mrDSide) 93 07.08.17 15:01 Сейчас в теме
Вот бы кто-нибудь Just For Fun! сделал из emacs некое подобие EDT.
27. Александр Закиров (sasha777666) 208 07.08.17 15:11 Сейчас в теме
Ошибка инициализации модуля: ВнешняяОбработка.OneShell.Форма.Form.Форма
по причине:
{ВнешняяОбработка.OneShell.Форма.Form.Форма(55,23)}: Процедура или функция с указанным именем не определена (StrTemplate)
FormResult.AddLine(<<?>>StrTemplate("%1: %2 -- `%3`", Scanner.Line, Scanner.Tok, Scanner.Lit));
{ВнешняяОбработка.OneShell.Форма.Form.Форма(75,22)}: Процедура или функция с указанным именем не определена (StrConcat)
FormResult.SetText(<<?>>StrConcat(Backend.Result));
{ВнешняяОбработка.OneShell.Форма.Form.Форма(83,22)}: Процедура или функция с указанным именем не определена (StrConcat)
FormResult.SetText(<<?>>StrConcat(Backend.Result));
28. Сергѣй Батанов (baton_pk) 208 07.08.17 15:14 Сейчас в теме
(27) Платформа у вас старая. Какая версия? 8.3.6+ нужна
29. Александр Закиров (sasha777666) 208 07.08.17 15:17 Сейчас в теме
30. Александр Цуканов (tsukanov) 34 07.08.17 15:17 Сейчас в теме
31. Александр Закиров (sasha777666) 208 07.08.17 15:18 Сейчас в теме
32. Sergey Andreev (starik-2005) 1040 07.08.17 15:27 Сейчас в теме
Давно хотел сделать что-то подобное в PHP или Python, чтобы можно было бы нанять 1С-ников за тарелку супа, а на выходе получить компилируемый (Python) код, что могло бы решить множество проблем (с теми же 1С лицензиями). Остается вопрос о переносимости форм, но это, ИМХО, тоже решаемо.

Автору респект.
33. Сергѣй Батанов (baton_pk) 208 07.08.17 15:30 Сейчас в теме
(32)
но это, ИМХО, тоже решаемо.

вот только решил бы кто уже наконец
34. Caponid V (caponid) 07.08.17 18:18 Сейчас в теме
хм.. а вот так...

аа = .50;

{ВнешняяОбработка.OneShell.МодульОбъекта(1063)}: Expected operand
Raise "Expected operand";


Зато все виды строк обработал правильно)

как я понимаю для AST комментарии игнорируются? как и директива Экспорт?
35. Александр Цуканов (tsukanov) 34 07.08.17 18:35 Сейчас в теме
(34) Ну так в 1С это тоже не прокатит )
36. Александр Цуканов (tsukanov) 34 07.08.17 18:38 Сейчас в теме
(34)
как я понимаю для AST комментарии игнорируются? как и директива Экспорт?

Сейчас да. Экспорт я наверно таки добавлю в AST.
А вот с комментами беда. Сначала я хотел хранить их в AST, но уткнулся в то, что части строк могут перемежаться с комментариями.
Т.е. получается и строки пришлось бы хранить частями. Мне показалось это лишним усложнением
37. Caponid V (caponid) 07.08.17 20:24 Сейчас в теме
(35)
Ну так в 1С это тоже не прокатит )
- это работает.. хотя даже в типовых уже такое перестал видеть, но сам формат записи остался...

(36)
Мне показалось это лишним усложнением
- та да... пришлось бы вводить еще номер линии комментария относительно начала строки.
хотя сами 1совцы не стали париться с комментариями в запросах....
38. Александр Цуканов (tsukanov) 34 07.08.17 20:51 Сейчас в теме
(37)
- это работает.. хотя даже в типовых уже такое перестал видеть, но сам формат записи остался...

Работает где?
Я вижу в 1С:
Неправильная константа типа Число аа = <<?>>.50; (Проверка: Сервер)
39. Caponid V (caponid) 08.08.17 10:07 Сейчас в теме
Хм, действительно... но ведь точно было... у меня нет версий младше 8.2.19 - на ней тоже ошибку выдает...
зачем-то в своем парсере я этот формат числа вводил)))

Число(".10") ->> 0.1
40. Vladimir Vasiliev (vasvl123) 62 09.08.17 13:00 Сейчас в теме
41. Александр Цуканов (tsukanov) 34 09.08.17 14:38 Сейчас в теме
(40) Вангую компилятор onescript на onescript )
42. Валентин Бомбин (so-quest) 126 09.08.17 15:12 Сейчас в теме
отмечусь что бы не потерять.
43. Vladimir Vasiliev (vasvl123) 62 09.08.17 16:58 Сейчас в теме
(41) транслятор со своего языка на onescript
Оставьте свое сообщение