Генерировать вывод вместе с парсером рекурсивного спуска - PullRequest
3 голосов
/ 20 октября 2011

Написание простых парсеров тривиально, и я реализовал несколько за эти годы.В колледже нам тоже пришлось написать один.Но нам никогда не приходилось генерировать значимые результаты, используя этот метод; мы никогда не учились создавать бэкэнд.

Если у меня есть работающий синтаксический анализатор рекурсивного спуска для упрощенного Паскаля и я хочу перевести код на C ++, как бы я поступил?этот?Я не вижу необходимости в промежуточном шаге, таком как создание абстрактного синтаксического дерева.

Итак, как мне вывести вывод скомпилированного или переведенного кода? Единственный полезный пример, который я нашелэто в учебнике Джека Креншоу, но больше внимания уделяется интерфейсу, как и большинству других ресурсов.Связь между моим парсерным кодом и моей грамматикой очень очевидна.Как насчет связи между методами парсера и выводом?Мой метод синтаксического анализа для объявления функции может относиться только к одному вызову EmitLn ( код C ++ здесь ).Но как насчет методов синтаксического анализа, которые не так просты, такие как выражения.Выражения разбиты на, возможно, еще много вызовов, так что намекает на необходимость функции Emit (), которая позволяет разбивать выходной код для выражения по частям. Существует ли какой-либо код котельной пластины для вывода кода, , например, функция EmitLn в книге Джек Креншоу «Давайте создадим компилятор»?Это также показывает, что мне нужно поддерживать базовую таблицу символов, что часто упускается в большинстве примеров.

Я прав?Что еще я должен знать?Какие-либо советы / предложения или ресурсы?Мой большой вопрос в том, что существует так много учебников по внешним интерфейсам компилятора, но как насчет объяснения в конце?Я могу анализировать языки, теперь я хочу развить это, чтобы иметь возможность переводить и компилировать их в другие языки.

Ответы [ 2 ]

3 голосов
/ 20 октября 2011

Существуют тривиальные компиляторы, использующие генераторы кода «на лету», которые выплевывают код как они разбирают, как вы, кажется, пытаетесь сделать. Хорошей новостью является то, что они выглядят легко.

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

Часто на промежуточной структуре проводится очень глубокий анализ определить, как генерировать хороший код с последующим соответствующим генерация кода. Методы для этого хорошо сложны, но мотивированы необходимостью создавать хороший (и правильный) код.

Попробуйте проверить стандартные ресурсы компилятора. Учимся писать компилятор

Оно того стоит время, чтобы прочитать некоторые из этих ссылок в деталях вместо взлома. Если вы настаиваете только на одном, Ахо и Уллман - классическая книга.

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

1 голос
/ 30 августа 2012

Короткий ответ После сопоставления правила в вашей грамматике вызовите функцию, которая делает что-то на основе ввода.

Длинный ответ: Из шаблонов языковой реализации Теренса Парра, обсуждающих синтаксически-ориентированных переводчиков:

интерпретатор, направленный на синтаксис, не создает AST и не переводит исходный код в байт-коды ... Интерпретатор напрямую передает синтаксис для выполнения операторов.

Именно об этой идее я и думал в своем первоначальном вопросе. Продолжая в книге, он описывает технику, как она работает, из чего она состоит, и ограничения. Он работает для DSL и небольших языков, а не для языков общего назначения.

Он утверждает, что такие конструкции, как IF и циклы, неудобно реализовывать. Хотя это, вероятно, правда, у меня не было проблем с реализацией таких функций на моем языке, Peay BASIC . Языки, которые являются последовательностями инструкций или простых утверждений, идеально подходят для этого шаблона; в качестве примера он приводит языки обработки текста.

Грамматика расширена и состоит из пар "соответствуй, назови это". Таким образом, с необходимыми правилами в вашей грамматике должно быть связано действие. Пример оператора присваивания:

assignment : ID '=' expr {interp.assign($ID, $expr.value);};
expr returns [Object value] : ... ;
...