Конструирование компиляторов - по сути, реализация своего языка программирования, где на входе - текст программы на вашем языке программирования, а на выходе - исполняемый файл. Сам компилятор является обычно заключительной частью работы.
Весь процесс разработки компилятора можно разбить на несколько этапов.
1) Разработка языка. Для этого вам понадобится освоить некоторое количество теоретического материала по контекстно-свободным грамматикам. Вы создадите грамматику – набор правил по которым ваш лексический анализатор будет преобразовывать входной текст в список лексем.
Вот небольшой пример грамматики представляющей выражения со скобками и сложением:
S -> A
A -> A + A
A -> id
A -> ( A )
Здесь id – число (терминал), S, A - нетерминалы, S- начальный нетерминал.
2) Лексический анализ. На этом этапе вы по существующей грамматике (списку лексем) проверяете входной файл на корректность (лексическую, то есть правильность написания слов ) и преобразовываете входную последовательность в список лексем, которые понимает синтаксический анализатор. Реализация лексического анализатора заключается в выделении лексем, и проверке является ли это подходящей лексемой.
|
Входная последовательность |
( |
10 |
+ |
11 |
) |
+ |
12 |
|
Список лексем |
( |
id
|
+
|
id
|
)
|
+
|
id
|
Это пример того как по грамматике сверху будет преобразован текст, каждый id является структурой и он знает что него содержится внутри (какое число).
3) Синтаксический анализ. Теперь список лексем, полученный на предыдущем этапе, будет проверяться на синтаксическую верность – верность построения структур языка. От того, какая у нас грамматика: простого предшествования (ПП), лево-рекурсивная (ЛР), или другая, реализация синтаксического анализатора будет разной. Но по сути, они проходят по списку лексем, накапливая их, и проверяя подходят ли накопленные лексемы под правила языка, и заменяет накопленные на нетерминалы (осуществляя свертки).
(id+id)+id преобразуется в (A+A)+A, затем (А+А) заменяется на А, получается А+А, затем А+А заменяется на А, а А на S. Получен начальный нетерминал, входная последовательности стала пуста, значит, синтаксический анализ прошел успешно, последовательность принимается.
4) Трансляция. Имея свернутую входную последовательность на этом этапе на неё навешивается логика (цикл становится циклом, присваивание значения присваиваем значения), тут, в зависимости от желания разработчика может получится и бинарный файл, и файл на другом языке программирования, или какой то промежуточный код, который в последствии может быть оптимизирован.
Полезные ссылки
Альфред В. Ахо, Моника С. Лам, Рави Сети, Джеффри Д. Ульман "Компиляторы: принципы, технологии и инструментарий"
В.А.Серебряков, М.П.Галочкин, Д.Р. Гончар, М.Г. Фуругян "Теория и реализация языков программирования"