Как работают парсеры C / C ++? - PullRequest
3 голосов
/ 21 января 2011

Я потратил много времени на изучение работы парсера PHP:

переводит код PHP в код наконец-то c.

Но как переводится код c в исполняемые файлы?

Кстати, как судить, можно ли каким-то образом преобразовать язык A в язык B с математической точки зрения?

Ответы [ 4 ]

10 голосов
/ 21 января 2011

Это действительно большой и действительно глубокий вопрос, который затрагивает многие аспекты информатики.

В конечном итоге все программы на компьютере выполняются путем выдачи инструкции процессору в машинном коде.Не существует единого «машинного кода», и каждый процессор имеет свой собственный набор инструкций, которые могут быть выполнены.Обычно это низкоуровневые операции, такие как «загрузить значение в память» или «добавить два значения вместе».Теоретически, каждая программа может быть написана в машинном коде, но это случается редко.Машинный код, по сути, представляет собой последовательность нулей и единиц, которые определенным образом декодируются процессором, и было бы практически невозможно создать такую ​​сложную систему непосредственно таким способом.

На шаг выше машинного кода - ассемблер , очень макроуровневый язык очень низкого уровня, который обычно имеет однозначное соответствие с машинным кодом.Например, у вас могут быть такие команды, как «добавить», которые делают сложение, «саб» для вычитания или «вызов» для вызовов функций.В конечном итоге код преобразуется в машинный код с помощью ассемблера , программы, которая переводит сборку в машинный код.Можно собрать большие сложные системы в сборке, но это очень сложно.

Многие языки программирования, такие как C и C ++, скомпилированы , что означает, что специальная программа, называемая compiler переводит исходный код на ассемблер, который затем может быть преобразован непосредственно в машинный код.Таким образом, вы можете программировать код, который работает на высоком уровне - он может иметь переменные, функции, объекты, шаблоны, исключения и т. Д. - но который может работать непосредственно на оборудовании машины.Другие языки программирования интерпретируются , что означает, что специальная программа, называемая интерпретатор , анализирует исходный код, создает его некоторое представление в памяти, а затем переводит его в сборку либо косвенным образом(используя программу для управления выполнением инструкций) или напрямую (генерируя ассемблер по мере необходимости).

Теория о том, как преобразовать один язык в другой, была тщательно изучена.Есть много проблем, начиная от «как ты вообще смотришь на исходный код программы и понимаешь, на что ты смотришь?»на "Какой самый эффективный способ преобразовать эту программу в какой-то другой язык?"Первый включает лексирование , разбор и семантический анализ ;последний включает оптимизацию и генерацию кода .

Как правило, программу на любом языке можно преобразовать в эквивалентную программу на другом языке, хотя может быть заметнаяпотеря в эффективности.Некоторые языки программирования имеют специальные функции, которые обращаются к базовому оборудованию и, следовательно, не могут быть написаны на языках, которые не имеют доступа к этому оборудованию, но это редко бывает.Типичная мера того, можно ли переписать программу на другом языке, - это спросить, являются ли эти два языка Turing-complete , математическим термином, указывающим, достаточно ли язык программирования выразителен для кодирования определенных классов функций.

Надеюсь, это поможет!

6 голосов
/ 21 января 2011

PHP на самом деле не «переводит» код на C; интерпретатор PHP интерпретирует PHP при выполнении исполняемого кода, а интерпретатор PHP - это конечный автомат, который знает, как выполнить весь PHP в процессе. Никакого промежуточного С не требуется или не желательно. Поскольку он интерпретируется, каждый раз, когда исполняемый файл PHP интерпретирует программу PHP, он переоценивается.

Интерпретатор PHP написан на C, но он мог быть на C ++, ассемблере, Pascal, Erlang, bash или Java, или как вам угодно. (Я думаю, что это началось в Perl, но моя память становится нечеткой.)

C компилируется с помощью компилятора , который запускается один раз, прежде чем программа может быть запущена тысячи раз. Большинство компиляторов C делают несколько «проходов»: lexing ввод в токены , парсинг токенов в дерево , затем изменение Абстрактное синтаксическое дерево для генерации таблиц символов для каждой из областей выполнения. После того, как абстрактное синтаксическое дерево подверглось различным оптимизациям, таким как удаление мертвого кода и статическое одиночное присвоение , дерево передается в генератор кода , который будет генерировать требуемый объектный файл для ввода, который может быть запущен для целевой архитектуры , о которой идет речь. Объектный файл связан с компоновщиком с объектами (функциями и переменными в C), не определенными в этой конкретной единице перевода , так что программа может быть загружена компоновщиком / загрузчик во время выполнения.

книга драконов - это обычно лучший источник знаний о компиляторах, но я рекомендую вместо этого Шаблоны языковой реализации Pragprog .

5 голосов
/ 21 января 2011

Насколько я понимаю, ваша главная проблема, похоже, связана с процессом компиляции.Как вы упомянули в ваших комментариях, вы запутались в парсере и компиляторе.Позвольте мне немного помочь вам:

alt text

Разбор - это только один из этапов процесса компиляции.Чтобы лучше понять ваш вопрос, вы должны сначала понять, как работают компиляторы.Как правило, вышеупомянутые несколько шагов обычно используются компиляторами.Чтобы понять вышесказанное, потребуется немного поработать.Если вы хотите углубиться дальше, прочитайте лекции от по этой ссылке .Исходный и целевой код зависят от контекста.Обычно исходный код - это язык высокого уровня, а целевой код - машинный код.

2 голосов
/ 21 января 2011

как определить, можно ли каким-то образом преобразовать язык A в язык B с математической точки зрения?

Если оба языка завершены по Тьюрингу , то можно перевести одинв другое.

Что касается вашего предположения PHP на C, существуют компиляторы "источник-источник", такие как HipHop , но это не распространенный случай.Большинство динамически типизированных языков компилируются в байт-код и запускаются на виртуальной машине.

Что касается C, компилятор переводит его по существу на язык ассемблера для целевого процессора.

Если вы хотитеузнайте больше, вы можете прочитать о дизайне компилятора, абстрактных синтаксических деревьях и семантике языка.Хотя, если вы новичок в этом, нужно сразу принять участие, так что Stack Overflow действительно не лучшее место для начала с такой большой темой.

...