Комментарии 3
Почему выбрали именно Python как цель для конвертации. Это сделано просто "потому что можем", с прицелом на использование такой модели в Production?
Как альтернативу можно рассмотреть Babelfish, который анализирует любой файл на любом поддерживаемом языке, извлекает из него AST и преобразовывает его в UAST, в котором узлы не привязаны к синтаксису исходного языка. На входе мы можем иметь JavaScript или C#, но на уровне UAST мы не увидим никаких различий.
Мы (Positive Technologies) тоже работаем над подобным проектом PT Pattern Matching. Только он не трансформирует код, а ищет паттерны, которые описываются вручную или с помощью DSL.
Для трансформации одного языка программирования в другой мы решили использовать ANTLR 4 и одну из его грамматик, а именно ECMAScript.g4.
Сразу порекомендую использовать нашу грамматику JavaScript из-за следующего:
- Поддержка ECMAScript 6.
- Поддержка устаревшего синтаксиса Html Comment, CData.
- Увеличенная скорость лексера.
- Более легковесный синтаксис.
- Универсальные встаки кода, правда с Python и JavaScript скорее всего все равно будут сложности.
Хотите ли вы сохранять формат пользовательского ввода (пробелы, пустые строки), либо же вы хотите приводить текст к более стандартному легче читаемому виду. С одной стороны, второй вариант будет выглядеть более профессионально, с другой — пользователь вашего компилятора может быть в итоге не доволен, так как он, вероятно, хочет получить на выходе идентичный его вводу формат.
Можно разбивать скрытые токены на лидирующие и замыкающие, а затем связывать их с основными. Тогда получится full fidelity tree. Также об этом я рассказывал в докладе Теория и практика парсинга формальных языков.
Установим JavaScript runtime, для этого нам потребуется npm пакет antlr4 — JavaScript target for ANTLR 4.
Рассматривали возможность использования TypeScript рантайма? Все же типизированный язык. А так вообще самые быстрые рантаймы — Java и C#.
Возможно следующее поколение молодых ANTLR-вцев скачает уже вашу более идеальную версию грамматики.
И вы не стесняйтесь присылать фиксы :)
visit() отвечает за обход дерева.
visitChildren() отвечает за обход узлов.
Не очень понятно. Обычно visit
внутри себя вызывает accept
, который непосредственно вызывает переопределенный метод конкретного узла. А visitChildren
— реализация обхода потомков конкретного узла по-умолчанию, если поведение обхода не переопределено.
К потомкам можно обращаться как по имени, так и по порядковому номеру.
А также по элементным меткам. Например, можно написать array : '{' el+=INT (',' el+=INT)* '}' ;
, а потом обращаться к массиву el
.
Компилятор на JavaScript с использованием ANTLR