Я беру класс разработки компилятора, где мы должны реализовать наш собственный компилятор (используя flex и bison). У меня был опыт разбора (написания парсеров EBNF и рекурсивного спуска), но я впервые пишу компилятор.
Языковой дизайн довольно открыт (профессор оставил это на наше усмотрение). В классе профессор перешел к генерации промежуточного кода. Он сказал, что нам нет необходимости создавать абстрактное синтаксическое дерево или дерево разбора во время синтаксического анализа, и что мы можем генерировать промежуточный код по ходу работы.
Мне показалось, что это сбивает с толку по двум причинам:
Что если вы вызываете функцию до того, как будет определено? Как вы можете решить цель филиала? Я предполагаю, что вам нужно будет сделать правило, что вы должны определять функции, прежде чем использовать их, или, может быть, предварительно определить их (как это делает C?)
Как бы вы справились с условиями? Если у вас есть if-else
или даже просто if
, как вы можете разрешить цель ветвления для if
, когда условие false
(если вы генерируете код по ходу дела)?
Я планировал создать AST, а затем пройтись по дереву после его создания, чтобы разрешить адреса функций и целей ветвления. Это правильно или я что-то упустил?