Я собираюсь сделать побочный проект, целью которого является перевод кода с одного языка программирования на другой. Языки, с которых я начинаю работать, – это PHP и Python (с Python на PHP должно быть проще начать), но в идеале я бы мог добавить другие языки с относительной легкостью. План:
Это ориентировано на веб-разработку. Оригинальный и целевой код будет сидеть поверх фреймворков (которые мне также придется писать). Эти рамки будут охватывать шаблон проектирования MVC и следовать строгим правилам кодирования. Это должно сделать перевод несколько проще.
Я также рассматриваю IOC и инъекции зависимостей, поскольку они могут облегчить процесс перевода и уменьшить вероятность ошибок.
Я буду использовать модуль парсера Python, который позволяет мне играть с абстрактным деревом синтаксиса. По-видимому, ближе всего к PHP можно добавить token_get_all () , что является началом.
С этого момента я могу построить AST, таблицы символов и поток управления.
Тогда я верю, что могу начать выводить код. Мне не нужен идеальный перевод . Мне все равно придется просматривать сгенерированный код и исправлять проблемы. В идеале переводчик должен обозначать проблематичные переводы.
Прежде чем спросить: «Что, черт возьми, в этом смысл?» Ответ будет … Это будет интересный опыт обучения. Если у вас есть какие-либо сведения о том, как сделать это менее сложным, сообщите мне.
Мне больше интересно узнать, какие шаблоны я мог бы применять для кода, чтобы упростить перевод (т.е. IoC, SOA?) Кода, чем как сделать перевод.
Я создавал инструменты (DMS Software Reengineering Toolkit) для выполнения манипуляций с универсальными программами (с переводом на язык, являющимся особым случаем) с 1995 года, при поддержке сильной команды компьютерных ученых. DMS обеспечивает общий синтаксический анализ, построение АСТ, таблицы символов, анализ управления и потока данных, применение правил перевода, регенерацию исходного текста с комментариями и т. Д., Все параметры которого определяются явными определениями компьютерных языков.
Объем оборудования, который вам нужен для этого, огромен (особенно если вы хотите иметь возможность сделать это для нескольких языков в общем виде), а затем вам понадобятся надежные парсеры для языков с ненадежными определениями (PHP – прекрасный пример этого ).
Нет ничего плохого в том, что вы думаете о создании переводчика на языке или его попытке, но я думаю, что вы найдете это гораздо более сложной задачей для реальных языков, чем вы ожидаете. У нас есть около 100 человеко-лет, вложенных в просто DMS, а еще 6-12 месяцев в каждое «надежное» определение языка (включая ту, которую мы мучительно создаем для PHP), и многое другое для неприятных языков, таких как C ++. Это будет «адский опыт»; это было для нас. (Вы можете найти раздел технических документов на вышеуказанном веб-сайте, интересный, чтобы начать с начала обучения).
Люди часто пытаются создать какой-то обобщенный механизм, начиная с какой-то технологии, с которой они знакомы, что делает часть работы. (Атрибуты Python – отличный пример). Хорошая новость заключается в том, что часть работы завершена. Плохая новость заключается в том, что в машинах есть встроенные в него предположения, большинство из которых вы не обнаружите, пока не попытаетесь бороться с чем-то другим. В этот момент вы узнаете, что оборудование подключено к тому, чтобы делать то, что оно изначально делает, и действительно будет действительно противостоять вашей попытке заставить его сделать что-то еще. (Я подозреваю, что попытка получить Python AST для моделирования PHP будет очень весело).
Причина, по которой я начал строить DMS, состояла в том, чтобы создать основы, в которых было очень мало таких предположений. Внутри есть некоторые, которые дают нам головные боли. Пока нет черных дыр. (Самая трудная часть моей работы за последние 15 лет – попытаться предотвратить проникновение таких предположений).
Многие люди также ошибаются, полагая, что, если они смогут разобрать (и, возможно, получить АСТ), они на пути к чему-то сложному. Одним из трудных уроков является то, что вам нужны таблички с символами и анализ потока для хорошего анализа или преобразования программ. АСТ необходимы, но недостаточно. Именно по этой причине книга компилятора Aho & Ullman не останавливается на главе 2. (OP имеет это право в том, что он планирует построить дополнительные машины за пределами AST). Подробнее об этой теме см. « Жизнь после анализа» .
Замечание о том, что «мне не нужен совершенный перевод», вызывает беспокойство. То, что делают слабые переводчики, составляет «легкий» 80% кода, оставляя трудным 20% делать вручную. Если приложение, которое вы намерены преобразовать, довольно мало, и вы только намерены его конвертировать один раз, тогда 20% в порядке. Если вы хотите преобразовать многие приложения (или даже те же, что и с незначительными изменениями с течением времени), это не приятно. Если вы попытаетесь преобразовать 100K SLOC, тогда 20% – это 20 000 оригинальных строк кода, которые трудно перевести, понять и изменить в контексте еще 80 000 строк переведенной программы, которые вы уже не понимаете. Это требует огромных усилий. На уровне миллионной линии это практически невозможно на практике. (Удивительно, что есть люди, которые не доверяют автоматическим инструментам и настаивают на том, чтобы перевести миллионы линейных систем вручную, это еще сложнее, и они обычно обнаруживают мучительно длительные задержки, высокие затраты и часто прямые сбои.)
То, что вы должны снимать для перевода крупномасштабных систем, – это коэффициенты конверсии в процентах от девяностых, или, скорее всего, вы не сможете выполнить ручную часть операции перевода.
Другим ключевым соображением является размер кода для перевода. Требуется много энергии для создания надежного переводчика, даже с хорошими инструментами. Хотя кажется, что сексуально и здорово создавать переводчика вместо простого ручного преобразования, для небольших базовых кодов (например, до примерно 100 тыс. SLOC в нашем опыте) экономика просто не оправдывает его. Никто не любит этот ответ, но если вам действительно нужно перевести только 10K SLOC кода, вам, вероятно, лучше просто кусать пулю и делать это. И да, это больно.
Я считаю, что наши инструменты очень хороши (но тогда я довольно предвзятый). И еще очень сложно построить хорошего переводчика; это занимает около 1,5-2 человеко-лет, и мы знаем, как использовать наши инструменты. Разница в том, что с помощью этого большого механизма мы преуспеваем значительно чаще, чем мы терпим неудачу.
В моем ответе будет рассмотрена конкретная задача синтаксического анализа Python, чтобы перевести его на другой язык, а не на аспекты более высокого уровня, которые Ира хорошо ответила на его ответ.
Короче: не используйте модуль парсера, есть более простой способ.
Модуль ast
, доступный с Python 2.6, намного более подходит для ваших нужд, поскольку он дает вам готовый АСТ для работы. Я написал статью об этом в прошлом году, но, короче говоря, использую метод parse
ast
для анализа исходного кода Python в AST. Модуль parser
даст вам дерево разбора, а не AST. Остерегайтесь разницы .
Теперь, поскольку АСТ Python достаточно детализированы, учитывая AST, передняя задача не является ужасно трудной. Я полагаю, что вы можете иметь простой прототип для некоторых частей функциональности, готовых довольно быстро. Однако для получения полного решения потребуется больше времени, главным образом потому, что семантика языков отличается. Простое подмножество языка (функции, базовые типы и т. Д.) Можно легко перевести, но как только вы попадете в более сложные слои, вам понадобится тяжелая техника для эмуляции ядра одного языка в другом. Например, рассмотрите генераторы Python и списки, которые не существуют в PHP (к моим лучшим знаниям, которые, по общему признанию, являются слабыми при использовании PHP).
Чтобы дать вам один последний совет, рассмотрите инструмент 2to3
, созданный разработчиками Python, чтобы перевести код Python 2 в код Python 3. Во-первых, у него есть большинство элементов, которые нужно перевести на Python. Однако, так как ядра Python 2 и 3 аналогичны, там не требуется эмуляционное оборудование.
Написание переводчика не является невозможным, особенно учитывая, что стажер Джоэла сделал это в течение лета.
Если вы хотите сделать один язык, это легко. Если вы хотите сделать больше, это немного сложнее, но не слишком много. Самое сложное состоит в том, что, хотя любой полный язык обучения может делать то, что делает другой полный язык обучения, встроенные типы данных могут изменить то, что делает феноменальный язык.
Например:
word = 'This is not a word' print word[::-2]
берет много кода на C ++, чтобы дублировать (хорошо, хорошо, вы можете сделать это довольно коротко с некоторыми циклами, но все же).
Наверное, это немного в стороне.
Вы когда-нибудь писали токенизатор / парсер, основанный на грамматике языка? Вероятно, вам захочется узнать, как это сделать, если вы этого не сделали, потому что это основная часть этого проекта. То, что я хотел бы сделать, это получить базовый синтаксис Turing – что-то довольно похожее на байт-код Python. Затем вы создаете лексер / парсер, который принимает грамматику языка (возможно, используя BNF ) и на основе грамматики компилирует язык на ваш промежуточный язык. Тогда то, что вы хотите сделать, это сделать наоборот – создать парсер с вашего языка в целевые языки на основе грамматики.
Наиболее очевидной проблемой, которую я вижу, является то, что сначала вы, вероятно, создадите ужасно неэффективный код, особенно на более мощных * языках, таких как Python.
Но если вы сделаете это так, то вы, вероятно, сможете найти способы оптимизации вывода по мере продвижения. Обобщить:
* мощным я имею в виду, что это занимает 4 строки:
myinput = raw_input("Enter something: ") print myinput.replace('a', 'A') print sum(ord(c) for c in myinput) print myinput[::-1]
Покажите мне другой язык, который может сделать что-то подобное в 4 строках, и я покажу вам язык, столь же мощный, как Python.
Есть несколько ответов, в которых вам не нужно беспокоиться. Ну, как это полезно? Ты хочешь учиться? Ты можешь выучить. Это компиляция. Так получилось, что ваш целевой язык не является машинным кодом, а другим языком высокого уровня. Это делается все время.
Есть относительно простой способ начать работу. Во-первых, зайдите http://sourceforge.net/projects/lime-php/ (если вы хотите работать на PHP) или некоторые из них и выполните код примера. Затем вы можете написать лексический анализатор, используя последовательность регулярных выражений и токенов подачи для создаваемого парсера. Ваши семантические действия могут либо выводить код непосредственно на другом языке, либо создавать некоторую структуру данных (мыслить объекты, человек), которые вы можете массировать и перемещаться для генерации выходного кода.
Вам повезло с PHP и Python, потому что во многих отношениях они являются одним и тем же языком, как и другие, но с различным синтаксисом. Жесткая часть преодолевает семантические различия между форматами грамматики и структурами данных. Например, у Python есть списки и словари, в то время как PHP имеет только массивы-члены.
Подход «ученика» заключается в создании чего-то, что работает нормально для ограниченного подмножества языка (например, только для операторов печати, простой математики и назначения переменных), а затем постепенно устраняет ограничения. Это в основном то, что делали «большие» парни в этой области.
О, и поскольку у вас нет статических типов в Python, лучше всего писать и полагаться на функции PHP, такие как «python_add», который добавляет числа, строки или объекты в соответствии с тем, как это делает Python.
Очевидно, что это может стать намного больше, если вы позволите.
Вы можете взглянуть на компилятор Vala , который переводит Vala (C # -подобный язык) на C.