Лабораторная работа №12. Генератор кода 5.3

Общие принципы организации условного перехода в ассемблере. Инструкция cmp. Создание меток перехода, генерирование условных переходов для реализации инструкций while или if.

Ассемблерный код выполняется последовательно и построчно. Однако существует и возможность перейти к другому участку кода. Для этого необходимо поставить перед этим участком определенную метку. Безусловный переход к метке выполняется в ассемблере по инструкции jmp. Это унарная инструкция - в качестве единственного аргумента она принимает имя метки. Условный переход реализуется с помощью инструкций условных переходов, следующих за инструкцией cmp. При этом обычно переход к метке выполняется по невыполнению условия в коде. Все виды условных переходов представлены в таблице.

Инструкция Пояснение Код на «нашем» языке Код на ассемблере
je jump equal a == b mov ax, a mov bx, b cmp ax, bx jne label
jne jump not equal a!= b mov ax, a mov bx, b cmp ax, bx je label
jl jump a < b mov ax, a mov bx, b cmp ax, bx jge label
jle jump less or equal a <= b mov ax, a mov bx, b cmp ax, bx jg label
jg jump greater a > b mov ax, a mov bx, b cmp ax, bx jle label
jge jump greater or equal a >= b mov ax, a mov bx, b cmp ax, bx jl label

Метки, генерируемые для переходов в ассемблерном коде, будут носить неоригинальные названия – «label» плюс порядковый номер метки. В классе CodeGenerator заведем счетчик для хранения текущей используемой метки (этот счетчик сообщит и общее количество используемых меток), далее реализуем метод добавления метки в ассемблерный код и метод получения текущей метки.

private static int countLabels = 0;

добавитьМетку()

{

количествоМеток++;

}

Строка получитьТекущуюМетку()

{

Вернуть «label» + количествоМеток.вСтроку();

}

В синтаксическом анализаторе добавим поле хранящее имя текущей метки. Далее доработаем его методы.

tType разобратьВыражение()

{

tType t = разобратьСложениеИлиВычитание();

если(LexicalAnalyzer.текущаяЛексема == Lexems.Равно

|| LexicalAnalyzer.текущаяЛексема == Lexems.НеРавно

|| LexicalAnalyzer.текущаяЛексема == Lexems.Меньше

|| LexicalAnalyzer.текущаяЛексема == Lexems.Больше

|| LexicalAnalyzer.текущаяЛексема == Lexems.МеньшеИлиРавно

|| LexicalAnalyzer.текущаяЛексема == Lexems.БольшеИлиРавно)

{

Строка переход = «»;

switch(LexicalAnalyzer.текущаяЛексема)

{

case Lexems.Равно:

переход = «jne»;

break;

case Lexems.НеРавно:

переход = «je»;

break;

case Lexems.Больше:

переход = «jle»;

break;

case Lexems.БольшеИлиРавно:

переход = «jl»;

break;

case Lexems.Меньше:

переход = «jge»;

break;

case Lexems.МеньшеИлиРавно:

переход = «jg»;

break;

}

LexicalAnalyzer.разобратьСледующуюЛексему();

разобратьСложениеИлиВычитание();

CodeGenerator.добавитьИнструкцию("pop ax");

CodeGenerator.добавитьИнструкцию("pop bx");

CodeGenerator.добавитьИнструкцию("cmp bx, ax");

CodeGenerator.добавитьИнструкцию(переход + «» + текущаяМетка);

текущаяМетка = «»;

t = tType.Bool;

}

вернуть t;

}

разобратьВетвление()

{

проверитьЛексему(Lexems.If);

CodeGenerator.добавитьМетку();

Строка нижняяМетка = CodeGenerator.получитьТекущуюМетку();

текущаяМетка = нижняяМетка;

CodeGenerator.добавитьМетку();

Строка меткаДляВыхода = CodeGenerator.получитьТекущуюМетку();

разобратьВыражение();

проверитьЛексему(Lexems.Then);

разобратьПоследовательностьИнструкций();

CodeGenerator. добавитьИнструкцию("jmp " + меткаДляВыхода);

пока(LexicalAnalyzer.текущаяЛексема == Lexems.ElseIf)

{

CodeGenerator. добавитьИнструкцию(нижняяМетка + «:»);

CodeGenerator.добавитьМетку();

нижняяМетка = CodeGenerator.получитьТекущуюМетку();

текущаяМетка = нижняяМетка;

LexicalAnalyzer.разобратьСледующуюЛексему();

разобратьВыражение();

проверитьЛексему(Lexems.Then);

разобратьПоследовательностьИнструкций();

CodeGenerator.добавитьИнструкцию("jmp " + меткаДляВыхода);

}

если(LexicalAnalyzer.текущаяЛексема == Lexems.Else)

{

CodeGenerator.добавитьИнструкцию(нижняяМетка + «:»);

LexicalAnalyzer.разобратьСледующуюЛексему();

разобратьПоследовательностьИнструкций();

}

проверитьЛексему(Lexems.EndIf);

CodeGenerator. добавитьИнструкцию(меткаДляВыхода + «:»);

}

разобратьЦикл()

{

проверитьЛексему(Lexems.While);

CodeGenerator.добавитьМетку();

Строка верхняяМетка = CodeGenerator.получитьТекущуюМетку();

CodeGenerator.добавитьМетку();

Строка нижняяМетка = CodeGenerator.получитьТекущуюМетку();

текущаяМетка = нижняяМетка;

CodeGenerator.добавитьИнструкцию(верхняяМетка + «:»);

разобратьВыражение();

разобратьПоследовательностьИнструкций();

проверитьЛексему(Lexems.While);

CodeGenerator.добавитьИнструкцию("jmp " + верхняяМетка);

CodeGenerator.добавитьИнструкцию(нижняяМетка + «:»);

}

Замечания по коду:

1) Так как строки в C# являются неизменяемым и ссылочным типом, приравнивание строк необходимо выполнять с копированием их значения - метод String.Copy();

2) Генерация ассемблерного кода для других видов цикла (for, do…while) реализуется аналогично.

Примеры кода:

Файлы SyntaxAnalyzer.cs, CodeGenerator.cs в проекте.


ВАРИАНТЫ К ЛАБОРАТОРНЫМ РАБОТАМ

Во всех вариантах все переменные должны быть объявлены до начала вычислений. <Буква> – буква латинского алфавита (a...z). <Цифра> – цифра от 0 до 9.

Вариант 1

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= <Список присваиваний>
<Объявление переменных>::= Var <Список переменных>
<Список переменных>::= <Идент> | <Идент>, <Список переменных>
<Список присваиваний>::= <Присваивание> | <Присваивание> <Список присваиваний>

<Присваивание>::= <Идент> = <Выражение>

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение>

<Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 2

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Var <Список переменных>;

<Список переменных>::= <Идент> | <Идент>, <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний>

<Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 3

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>
<Описание вычислений>::= [ <Список присваиваний> ]
<Объявление переменных>::= Var <Список переменных>;
<Список переменных>::= <Идент> | <Идент>, <Список переменных>
<Список присваиваний>::= <Присваивание> | <Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение>

<Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 4

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>
<Описание вычислений>::= <Список присваиваний>
<Объявление переменных>::= Var <Список переменных>;
<Список переменных>::= <Идент> | <Идент>, <Список переменных>
<Список присваиваний>::= <Присваивание> | <Присваивание> <Список присваиваний>

<Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.><Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 5

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End <Объявление переменных>::= Var <Список переменных>

<Список переменных>::= <Идент> | <Идент>, <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания.

Вариант 6

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End <Объявление переменных>::= Var <Список переменных>

<Список переменных>::= <Идент>; | <Идент>, <Список переменных> |

<Идент>; <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.><Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> | < Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 7

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Var <Список переменных>:Integer;

<Список переменных>::= <Идент> | <Идент>, <Список переменных>

<Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>;

<Выражение>::= <Ун.оп.><Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 8

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Var <Список переменных>:Logical;

<Список переменных>::= <Идент> | <Идент>, <Список переменных>

<Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.><Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "!"

<Бин.оп.>::= "&" | "|" | "^"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= 0 | 1

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 9

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Var <Список переменных>:Boolean; <Список переменных>::= <Идент> | <Идент>, <Список переменных>

<Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= ".NOT."

<Бин.оп.>::= ".AND." | ".OR." | ".XOR."

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= 0 | 1

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 10

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Integer <Список переменных>

<Список переменных>::= <Идент>; | <Идент>, <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 11

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= <Тип переменных> <Список переменных>

<Тип переменных>::= Integer | Long Integer

<Список переменных>::= <Идент>; | <Идент>, <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 12

<Программа>::= <Объявление переменных> <Описание вычислений> <Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End <Объявление переменных>::= Int <Список переменных> |

Int <Список переменных> <Объявление переменных>

<Список переменных>::= <Идент>; | <Идент>, <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 13

<Программа>::= <Объявление переменных> <Описание вычислений><Оператор печати>

<Описание вычислений>::= <Список присваиваний>
<Объявление переменных>::= Int <Список переменных>
<Список переменных>::= <Идент> | <Идент>, <Список переменных>
<Список присваиваний>::= <Присваивание> | <Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение>

<Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= <Цифра> <Const> | <Цифра>
<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 14

<Программа>::= <Объявление переменных> <Описание вычислений><Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Int <Список переменных>;

<Список переменных>::= <Идент> | <Идент>, <Список переменных> <Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний>

<Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "-"

<Бин.оп.>::= "-" | "+" | "*" | "/"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> | <Буква><Идент>

<Const>::= <Цифра> <Const> | <Цифра>

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 15

<Программа>::= <Объявление переменных> <Описание вычислений><Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Logical <Список переменных>

<Список переменных>::= <Идент> | <Идент>, <Список переменных>

<Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент>:= <Выражение>;

<Выражение>::= <Ун.оп.><Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= "!"

<Бин.оп.>::= "&" | "|" | "^"

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= 0 | 1

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Вариант 16

<Программа>::= <Объявление переменных> <Описание вычислений><Оператор печати>

<Описание вычислений>::= Begin <Список присваиваний> End

<Объявление переменных>::= Boolean <Список переменных>:

<Список переменных>::= <Идент> | <Идент>, <Список переменных>

<Список присваиваний>::= <Присваивание> |

<Присваивание> <Список присваиваний> <Присваивание>::= <Идент> = <Выражение>;

<Выражение>::= <Ун.оп.> <Подвыражение> | <Подвыражение> <Подвыражение>:: = (<Выражение>) | <Операнд> |

< Подвыражение > <Бин.оп.> <Подвыражение>

<Ун.оп.>::= ".NOT."

<Бин.оп.>::= ".AND." | ".OR." | ".XOR."

<Операнд>::= <Идент> | <Const>

<Идент>::= <Буква> <Идент> | <Буква>

<Const>::= 0 | 1

<Оператор печати>::=Print <Идент>

На одной строке может быть только объявление переменных или один оператор присваивания

Общие обозначения нетерминалов:

S=<Программа>

D= <Объявление переменных>

F= <Описание вычислений>

P= <Оператор печати>

V= <Список переменных>

I=<Идент>

G= <Список присваиваний>

A=<Присваивание>

E=<Выражение>

H=<Подвыражение>

O=<Операнд>

C=<Const>

N=<Цифра>

Общие обозначения терминалов – алфавит.

U= <Ун.оп.> =-|.NOT.

Обозначение альтернативного множества терминалов:

L=<Буква>

B=<Бин.оп.>


КУРСОВОЙ ПРОЕКТ

Основой заданий на курсовое проектирование являются задания, используемые в ходе лабораторных работ. С одной стороны это облегчает усвоение нового материала за счет выполнения студентами курсового проектирования параллельно с прохождением лабораторных работ. С другой стороны задания на курсовое проектирование содержат более сложные языковые конструкции, приближенные к конструкциям реальных языков программирования и проектирования высокого уровня.

В начале курсового проектирования студент должен модифицировать исходное описание языка (БНФ), выданное ему в качестве задания на лабораторные работы, добавив в него одну из конструкций языка высокого уровня (см. таблицу Б.1) в соответствии со своим вариантом.


Таблица Б.1

№ варианта Конструкция языка
1. IF <Выражение> THEN <Список операторов> {ELSE <Список операторов >}
  ENDIF
2. FOR <Присваивание> TO <Выражение> DO <Список операторов>
  ENDFOR
3. WHILE <Выражение> DO <Список операторов> ENDWHILE
4. DO <Список операторов> WHILE <Выражение>
5. CASE <Идентификатор> OF <Константа>: <Список операторов> {<Список альтернатив>} ENDCASE
6. GO TO <метка>
  IF (<Выражение>) <Оператор>
7. {ELSE <Оператор >}
8. FOR <Присваивание> TO <Выражение> <Оператор>
9. WHILE (<Выражение>) <Оператор>
10. CASE <Идентификатор> OF <Константа>: <Список операторов> ENDCASE
  UNTIL <Выражение> DO <Список операторов> ENDUNTIL
  DO <Список операторов> UNTIL <Выражение>
  Оператор Repeat определяет повторное выполнение последовательности операторов пока условие, заданное логическим выражением, не удовлетворено. Последовательность операторов выполняется по крайней мере один раз. REPEAT ПоследовательностьОператоров UNTIL Логическое выражение.  
  Оператор Loop определяет повторное выполнение последовательности операторов. Он завершается после выполнения оператора выхода внутри этой последовательности. LOOP ПоследовательностьОператоров IF Логическое выражение THEN EXIT END ENDLOOP  
  CASE Выражение OF Вариант: Оператор END CASE ch OF "A": а=1 "0": а=2 ENDCASE  

В вариантах 7-9 <Оператор> может быть простым или составным. Конструкции, ограничивающие составной оператор (begin – end, пара фигурных скобок и пр.) выбираются студентом.

Количество возможных сочетаний вариантов заданий для лабораторных работ и вариантов языковых конструкций достаточно велико, чтобы обеспечить неповторяющимися заданиями на курсовое проектирование одновременно несколько групп студентов. Для вариантов 8-9 заданий на лабораторные работы не рекомендуется добавлять конструкции 2-4 и 8-9 при выполнении курсового проекта, т.к. составление «разумных» программ с циклами в языке, где имеются только логические операции и типы данных едва ли возможно.

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

Основными техническими требованиями к курсовому проекту являются:

1. Язык является расширением варианта языка для лабораторных работ, включающим одну из языковых конструкций высокого уровня.

2. Транслятор реализуется по трехпроходной схеме.

3. Исходными данными для транслятора является текст программы на заданном языке.

4. Результатом работы транслятора должен быть файл, содержащий микрокод в заданной системе команд, либо текст программы на языке Ассемблера.

5. Для разработки транслятора рекомендуется применять язык программирования С#.

6. При написании транслятора использовать метод рекурсивного спуска (нисходящего разбора).

Пояснительная записка к курсовому проекту должна включать:

1. Описание синтаксиса реализуемого языка в форме Бэкуса-Наура.

2. LL(1)-грамматику языка.

3. Синтаксический граф языка.

4. Описание разработанного программного обеспечения, включающее:

-краткое описание лексического анализатора;

-классы лексем различаемые лексическим анализатором;

-примеры входного и выходного фалов для лексического анализатора;

-краткое описание синтаксического анализатора (на уровне основных процедур и функций);

-тестовые примеры обнаружения ошибок синтаксическим анализатором, а также пример работы без синтаксических ошибок;

-краткое описание программы формирования постфиксной записи;

-пример работы программы формирования постфиксной записи (входной файл лексем и выходной файл с постфиксной записью);

-краткое описание программы генерации кода;

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

5. Приложение (распечатки разработанного программного обеспечения).

Тестовый пример, демонстрирующий правильность работы компилятора при корректном входном коде должен обязательно включать (кроме варианта с конструкцией GO TO) следующие элементы:

• оператор или группу операторов присваивания;

• конструкцию языка высокого уровня, содержащую вложенную конструкцию языка высокого уровня;

• конструкцию языка высокого уровня, внешнюю по отношению к предыдущим;

• оператор или группу операторов присваивания.

В случае оператора GO TO, помимо операторов присваивания, должно содержаться несколько переходов как вперед, так и назад.



ЛИТЕРАТУРА

1. И.Г. Кревский, М.Н. Селиверстов, К.В. Григорьева ФОРМАЛЬНЫЕ ЯЗЫКИ, ГРАММАТИКИ И ОСНОВЫ ПОСТРОЕНИЯ ТРАНСЛЯТОРОВ Учебное пособие (под ред. д.т.н., профессора А.М. Бершадского) Пенза 2003

2. Свердлов С. 3. Языки программирования и методы трансляции: Учебное пособие. — СПб.: Питер, 2007. — 638 с: ил.


mov AX, a

mov BX, b

COMP:

cmp AX, BX

jle NEXT

inc AX

NEXT:

inc BX

mov BX,0

mov CX,5

M:

inc BX

loop M


Соглашения по оформлению кода

Стиль кода

Оформление

1.1.1. Используйте табуляцию, а не пробелы для отступов. В средах типа VS лучше использовать режим табуляции. Его можно настроить в диалоге Options -> Text Editor -> Ваш_любимый_язык ->Tabs: Indenting = Smart, Tabs = Keep Tabs. В общем, это настройки по умолчанию для многих языков.

1.1.2. При форматировании текста (кроме отступа в начале строки) используйте пробелы. Для этого удобно использовать режим Virtual Space, который в VS 2002 настраивается в Options -> Text Editor -> Ваш_любимый_язык -> General.

1.1.3. Избегайте строк длиннее 78 символов, переносите инструкцию на другую строку при необходимости.

1.1.4. При переносе части кода инструкций и описаний на другую строку вторая и последующая строки должны быть отбиты вправо на один отступ (табуляцию).

1.1.5. Оставляйте запятую на предыдущей строке так же, как вы это делаете в обычных языках (русском, например).

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

1.1.7. Не размещайте несколько инструкций на одной строке. Каждая инструкция должна начинаться с новой строки.

Примеры:

longMethodCall(expr1, expr2, expr3, expr4, expr5);   var1 = a * b / (c - g + f) + 4 * z;   var2 = (a * (b * (c + d) + e * (f / z)) + 4);

Пустые строки

1.2.1. Используйте две пустые строки между логическими секциями в исходном файле.

1.2.2. Используйте две пустые строки между объявлениями классов и интерфейсов.

1.2.3. Используйте одну пустую строку между методами.

1.2.4. Если переменные в методе объявляются отдельным блоком, используйте одну пустую строку между их объявлением и инструкцией, идущей за этим блоком.

1.2.5. Используйте одну пустую строку между логическими частями в методе.

Пробелы в строке

1.3.1. После запятой должен быть пробел. После точки с запятой, если она не последняя в строке (напр. в инструкции for), должен быть пробел. Перед запятой или точкой с запятой пробелы не ставятся.

1.3.2. Все операторы должны быть отделены пробелом от операндов с обеих сторон.

1.3.3. Логически связный блок регулярной структуры желательно форматировать в виде таблицы. При этом для выравнивания в таблице следует использовать пробелы, но не табуляцию. Среды типа VS автоматизируют процесс форматирования, вставляя пробелы или табуляции в соответствии с пользовательскими настройками. Будьте внимательны и проверяйте конечный результат, включая неотображаемые символы (для VS 2002 и старше – меню Edit->Advanced->View White Space).

ПРИМЕЧАНИЕ Для упрощения работы можно использовать следующий трюк. Таблицу можно сформировать с помощью табуляции, выделить область прямоугольным выделением (Alt + курсор мыши вправо), а затем применить к этой области Edit->Advanced->Untabify Selection.

Примеры:

TestMethod(a, b, c); int Bar { get; set; }   a=b; // неверно a = b; // верно for (int i=0; i<10; ++i) // неверно { } for(int i = 0;i< 10;++i) // неверно   for (int i = 0; i < 10; ++i) // верно { }   if(a==b){} // неверно   if (a == b) // верно { }   // табличное форматирование string name = "Mr. Ed"; int myValue = 5; Test aTest = Test.TestYou;

Локальные переменные

1.4.1. Объявляйте переменные непосредственно перед их использованием.

1.4.2. Счетчики в циклах традиционно называют i, j, k, l, m, n.

1.4.3. Для временных локальных переменных, используемых в коротких участках кода, можно давать имена, состоящие из начальных букв слов имени типа.

1.4.4. Не объявляйте более одной переменной в одной инструкции.

1.4.5. Имена скрытых (protected, protected internal и private) переменных-членов класса и статических переменных начинайте с одиночного символа подчеркивания.

1.4.6. Имена публичных (internal и public) переменных должны быть в стиле Паскаль и не иметь подчеркивания в качестве префикса.

1.4.7. Комментируйте объявления так, чтобы были понятны назначение и способы использования переменной.

1.4.8. Инициализируйте переменные при объявлении, если это возможно.

Пример:

class Class1 { private int _totalLineCount = 0;   void SomeFunction(int startValue) { int lineCount = startValue;   using (StreamReader sr = File.OpenText(@"c:\MyFile.txt")) { while (sr.ReadLine()!= null) lineCount++; }   _totalLineCount = lineCount; } }

Комментарии

1.5.1. Не используйте многострочные (/*...*/) комментарии для описания классов и методов, используйте для этих целей XML documentation-комментарии. Многострочные комментарии не могут быть вложенными, поэтому их использование может создать проблемы.

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

1.5.3. Комментируйте объявления переменных, по возможности используя XML-комментарии. Если язык не поддерживает XML-комментариев, можно использовать однострочные комментарии на той же строке, как это показано ниже.

1.5.4. Отделяйте текст комментария одним пробелом «// Текст комментария.».

1.5.5. Комментируя код, старайтесь объяснять, что он делает, а не какая операция производится. Так, инструкции if соответствует выражение «если... то...», причем часть, идущая за «то», является кодом, который будет выполняться, если выражение в if будет верным. Таким образом, для конструкции «if (somePath && File.Exists(somePath))», нужно написать комментарий «// Если выбранный файл существует, то...», а не «// Производим проверку на наличие файла и, если он имеется, удаляем его». Часть предложения, идущую за «то», вписывайте непосредственно перед выполнением конкретных действий. Для инструкций, осуществляющих действия, пишите «// Производим...» или «// Делаем...», где вместо троеточия вписывайте описания действий. Описывая действия, старайтесь описывать суть происходящего, а не то, что делают те или иные операторы. Так, совершенно бессмысленны комментарии вроде «Присваиваем переменной a значение b» или «вызываем метод f».

1.5.6. Помните, что экономить на комментариях нельзя. Однако не стоит также формально подходить к процессу создания комментариев. Задача комментария – упростить понимание кода. Есть немало случаев, когда сам код отличным образом себя документирует.

Примеры:

/// <summary>indentation level</summary> int level; int size; // size of table   // Line 1 // ArrayList list = new ArrayList(10);   // Line 1 // Line 2 // for (int i = 0; i < list.Count; i++) ...

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: