Иллюстрированный самоучитель по задачам и примерам Assembler

Элементы компиляции программ

Рассмотрим еще одну грамматику для языка идентификаторов Gident.

Gident-{Vt-(.. +. – . е. 0. 1. 2. 3. 4. 5. 6. 7. 8, 9). VrHreal. S. M. N. К. Т), Р, 2=(< real >)}

Множество правил Р грамматики Gident:

Gident › letter| ident letter | ident figure letter › A|B|C|… X|Y|Z figure › 0|l|2|…8|9

Видно, что это тоже грамматика языка класса 3.

А теперь приведем пример грамматики, генерирующей язык класса 2. С ее помощью смоделируем псевдоязык, похожий на Pascal, который мы используем в нашей книге для пояснения некоторых алгоритмов:

Vt=(Программа, ПЕРЕМЕННЫЕ, НАЧ_ПРОГ. КОН_ПРОГ, НАЧ_БЛОК. КОН_БЛОК. "."
.ID. CHJNT. СН_ REAL. ":".":". "/". REAL. INTJYTE. INT_WORD. INT_OWORD.
",".":"". "="."+"."-"."*". DIV. MOO. "(". ")". "[". "]". "<".">", "==",">="."=<".
ЧИТАТЬ, ПИСАТЬ, ДЛЯ. ДОДЕЛАТЬ. ПОКА. ДО.ВНИЗ, ЕСЛИ. ЕСЛИ. ДО. ТО. ПЕРЕЙТИ_НА. ПОВТОРИТЬ).
Vn>>(prog, prog-name, dec-list, stmt-list, dec .id-list, type .var .varjnd .ind.
label .go_to .stmt, assign, read, write, until, for .call_func .exp .term,
factor, index-exp .body, condition .cond_op). P. Z-(< prog >) }.

Множество правил Р грамматики G:

prog › ПРОГРАММА prog-name ПЕРЕМЕННЫЕ dec-list НАЧ_ПРОГ stmt-list КОН_ПРОГ
prog-name › ID
dec-list › dec | dec-list: dec
dec › type id-list
type › INTJYTE | INT_WORD | INT_DWORD | REAL
1d-list › var | id-list, var
var › ID | varjnd
var_ind › ID ind
ind › [ exp ]
stmt-list › stmt | stmt-list; stmt
stmt › assign | read | write | for | while | until | label | go_to | cond op | call_
func
assign › var: – exp exp › term | exp + term | exp – term
term › factor | term * factor | term DIV factor| term MOD factor
 factor › var | CH_INT | CH_REAL | (exp)
read › ЧИТАТЬ (id-list) ~ write › ПИСАТЬ (id-list) for › ДЛЯ index-exp ДЕЛАТЬ
body until › ПОВТОРИТЬ body ПОКА logical_exp call_func › ID (id-list) cond_op › ЕСЛИ
logical_exp TO body while › ПОКА logical_exp ДЕЛАТЬ body label › ID:
stmt-list go_to › ПЕРЕЙТИ_НА idjabel idjabel › ID
index-exp › var: = exp ДО exp | exp Д0ВНИЗ exp logical_exp › (condition)
condition › l_exp < l_exp | l_exp <@062> l_exp | l_exp > – l_exp | l_exp =< l_exp |
 l_exp – l_exp | l_exp ИЛИ
l_exp | l_exp И l_exp | l_exp XOR l_exp | HE l_exp l_exp › exp | condition
body › stmt | НАЧ_БЛОК stmt-list КОН_БЛОК

Посмотрим внимательно на правило вывода, в левой части которого стоит начальный символ языка prog. Правая часть этого правила представляет собой сентенциальную форму, содержащую все необходимые элементы программы. На примере этой грамматики хорошо видно, что представляет собой алфавит языка программирования. По сути это совокупность лексем, которые программист использует для написания программы и которые в терминах языка являются терминальными символами, а также нетерминалов, которые имеют смысл в рамках грамматики. Более того, к терминальным символам относятся также символы ID (идентификатор), CHINT (целое число) и CHREAL (вещественное число). В программе им соответствуют совершенно разные сочетания символов букв, цифр и разделительных знаков, например идентификаторы – chl, sab, masl; целые числа – 1, 24, 98584; вещественные числа – +33.5, 0.95е-3. С точки зрения синтаксиса эти разные по написанию объекты являются терминальными символами – идентификатором, целым числом, вещественным числом. Это ключевой момент. Мы к нему еще вернемся, а пока давайте посмотрим, каким превращениям подвергается исходный текст программы, для того чтобы превратиться в форму, пригодную для машинного исполнения.

Описание процесса трансляции программы

Транслятор представляет собой программу, выполняющую анализ исходного кода на некотором языке программирования и формирующую объектный модуль. Процесс преобразования исходного кода называется трансляцией. Вместо термина "транслятор", часто употребляется слово "компилятор", и соответственно процесс преобразования называется компиляцией. Не вдаваясь в описание лишних подробностей, будем считать эти названия синонимами и в дальнейшем изложении использовать их исходя из своих пристрастий.

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

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.