Учебный транслятор
Методы грамматического разбора. Разработка структуры учебного транслятора на базовом языке программирования Object Pascal в среде объектно-ориентированного визуального программирования Borland DELPHI 6.0 с использованием операционной системы Windows XP.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 12.05.2013 |
Размер файла | 493,8 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Министерство образования и науки Российской Федерации
ПЕНЗЕНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
Кафедра «Математическое обеспечение и применение ЭВМ»
Пояснительная записка
к курсовой работе по дисциплине
«Теория языков программирования и методы трансляции»
на тему:»Учебный транслятор»
Пенза 2004г.
ЗАДАНИЕ
на курсовое проектирование по курсу
«Теория языков программирования и методы трансляции»
Тема проекта “Учебный транслятор”
Исходные данные (технические требования) на проектирование
Разработать учебный транслятор в форме интерпретатора с языка, определенного соответствующей формальной грамматикой.
Разработка должна проводиться на базовом языке программирования Object Pascal в среде объектно-ориентированного визуального программирования Borland DELPHI 6.0. Осуществить функциональное тестирование разработанного транслятора.
Разработку провести с использованием операционной системы Windows 98 и выше на ЭВМ, совместимых с IBM PC Intel Pentium II и выше.
Вариант № 2
Тип переменных |
Вид <Ун. оп.> |
Вид <Бин. оп.> |
Вид <конст.> |
Максимальная длина идентификатора |
|
LOGICAL |
.NOT |
.AND.| .OR. | .IMP. |
0|1 |
12 |
Операторы |
Распознаватель |
|
READ, WHILE, WRITE |
Детерминированный нисходящий Распознаватель (магазинный авто-мат) для грамматики типа LL(1) |
Реферат
Целью курсового проекта является разработка учебного транслятора с заданного языка.
Разработка проводилась на базовом языке программирования Object Pascal в среде объектно-ориентированного визуального программирования Borland DELPHI 6.0 с использованием операционной системы Windows XP на персональном компьютере IBM PC с процессором Intel Pentium III.
Осуществлено функциональное тестирование разработанного транслятора, которое показало корректность его работы.
Личный вклад заключается в разработке лексического и синтаксического анализаторов.
Введение
В настоящее время программист формулирует и решает различные задачи на языках программирования высокого уровня и использует низкоуровневый язык ассемблера лишь в исключительных случаях. Как известно, алгоритмические языки становятся доступными программисту лишь после создания трансляторов с этих языков.
Разработка каждого конкретного транслятора зависит от специфических особенностей того или иного языка - назначение, структура, семантическая сложность, методы реализации.
Языки программирования предназначены для решения задач в различных предметных областях, что определяет специфику их организации и различия по назначению. В качестве примера можно привести такие языки как Фортран, применяемый для научных расчетов, C, ориентированный на системное программирование, Prolog, эффективно описывающий задачи логического вывода. Каждая из предметных областей выдвигает свои требования к организации языка. Поэтому можно отметить разнообразие форм представления операторов и выражений, различие в наборе базовых операций и типов данных, а также снижение эффективности программирования при решении задач, не связанных с данной предметной областью. Языковые различия отражаются и в структуре трансляторов. Лисп и Пролог чаще всего выполняются в режиме интерпретации из-за того, что используют динамическое формирование типов данных в ходе вычислений. Для трансляторов с языка Фортран характерна агрессивная оптимизация результирующего машинного кода, которая становится возможной благодаря относительно простой семантике конструкций языка - в частности, благодаря отсутствию механизмов альтернативного именования переменных через указатели или ссылки. Наличие же указателей в языке C предъявляет специфические требования к динамическому распределению памяти.
Структура языка характеризует иерархические отношения между его понятиями, которые описываются синтаксическими правилами. Языки программирования могут сильно отличаться друг от друга по организации отдельных понятий и по отношениям между ними. Язык программирования PL/1 допускает произвольное вложение процедур и функций, тогда как в C все функции должны находиться на внешнем уровне вложенности. Язык C++ допускает описание переменных в любой точке программы перед первым ее использованием, а в Паскале переменные должны быть определены в специальной области описания. Еще дальше в этом вопросе идет PL/1, который допускает описание переменной после ее использования. Или описание можно вообще опустить и руководствоваться правилами, принятыми по умолчанию. В зависимости от принятого решения, транслятор может анализировать программу за один или несколько проходов, что влияет на скорость трансляции.
Семантика языков программирования имеет очень широкий диапазон изменений. Они отличаются не только по особенностям реализации отдельных операций, но и по парадигмам программирования, определяющим принципиальные различия в методах разработки программ. Специфика реализации операций может касаться как структуры обрабатываемых данных, так и правил обработки одних и тех же типов данных. Такие языки, как PL/1 и APL поддерживают выполнение матричных и векторных операций. Большинство же языков работают в основном со скалярами, предоставляя для обработки массивов процедуры и функции, написанные программистами. Но даже при выполнении операции сложения двух целых чисел такие языки, как C и Паскаль могут вести себя по-разному.
Наряду с традиционным процедурным программированием, называемым также императивным, существуют такие парадигмы как функциональное программирование, логическое программирование и объектно-ориентированное программирование. Структура понятий и объектов языков сильно зависит от избранной парадигмы, что также влияет на реализацию транслятора.
Даже один и тот же язык может быть реализован нескольким способами. Это связано с тем, что теория формальных грамматик допускает различные методы разбора одних и тех же предложений. В соответствии с этим трансляторы разными способами могут получать один и тот же результат (объектную программу) по первоначальному исходному тексту.
Вместе с тем, все языки программирования обладают рядом общих характеристик и параметров. Эта общность определяет и схожие для всех языков принципы организации трансляторов.
Языки программирования предназначены для облегчения программирования. Поэтому их операторы и структуры данных более мощные, чем в машинных языках.
Для повышения наглядности программ вместо числовых кодов используются символические или графические представления конструкций языка, более удобные для их восприятия человеком.
Для любого языка определяется:
· Множество символов, которые можно использовать для записи правильных программ (алфавит), основные элементы.
· Множество правильных программ (синтаксис).
· "Смысл" каждой правильной программы (семантика).
Независимо от специфики языка любой транслятор можно считать функциональным преобразователем F, обеспечивающим однозначное отображение X в Y, где X - программа на исходном языке, Y - программа на выходном языке. Поэтому сам процесс трансляции формально можно представить достаточно просто и понятно: Y = F(X).
Формально каждая правильная программа X - это цепочка символов из некоторого алфавита A, преобразуемая в соответствующую ей цепочку Y, составленную из символов алфавита B.
Язык программирования, как и любая сложная система, определяется через иерархию понятий, задающую взаимосвязи между его элементами. Эти понятия связаны между собой в соответствии с синтаксическими правилами. Каждая из программ, построенная по этим правилам, имеет соответствующую иерархическую структуру.
В связи с этим для всех языков и их программ можно дополнительно выделить следующие общие черты: каждый язык должен содержать правила, позволяющие порождать программы, соответствующие этому языку или распознавать соответствие между написанными программами и заданным языком.
Другой характерной особенностью всех языков является их семантика. Она определяет смысл операций языка, корректность операндов. Цепочки, имеющие одинаковую синтаксическую структуру в различных языках программирования, могут различаться по семантике (что, например, наблюдается в C++, Pascal, Basic). Знание семантики языка позволяет отделить ее от его синтаксиса и использовать для преобразования в другой язык (осуществить генерацию кода).
Целью данной работы является разработка учебного транслятора с заданного языка.
1. Методы грамматического разбора
1.1 Разбор сверху - вниз
1.1.1 LL(k) - языки и грамматики
Моделирование работы недетерминированных магазинных распознавателей связано с поиском последовательности переходов из начального в одно из конечных состояний. Поиск состоит из отдельных шагов, каждый из которых может окончиться неудачно и привести к возврату в исходное состояние для выполнения следующего шага. Такой поиск с возвратом связан со значительными затратами времени, поэтому на практике используют более экономичные детерминированные распознаватели, работающие без возвратов. Эти распознаватели допускают только ограниченные классы КС-языков, которые однако отражают все синтаксические черты языков программирования. Распознаватели можно разделить на две категории: нисходящие и восходящие. Каждая категория характеризуется порядком, в котором располагаются правила в дереве вывода. Нисходящие распознаватели обрабатывают правила сверху вниз, верхние правила раньше нижних, в то время как восходящие анализаторы используют нижние правила раньше тех, что расположены выше.
Чтобы показать возможности детерминированных автоматов и способы их построения, в настоящем разделе рассматриваются нисходящие распознаватели, допускающие языки, порождаемые грамматиками вида LL(K).
Определение. В общем случае грамматика относится к классу LL(K) грамматик, если для нее можно построить нисходящий детерминированный распознаватель, учитывающий K входных символов, расположенных справа от текущей входной позиции.
Название LL произошло от слова Left, поскольку анализатор просматривает входную цепочку слева-направо, и слова Leftmost, поскольку он обнаруживает появление правила по одному или группе символов, образующих левый край цепочки. На практике наибольшее применение имеет класс LL(1) грамматик, для которых детерминированный распознаватель работает по дному входному символу, расположенному в текущей позиции. В качестве первого шага изучения нисходящих распознавателей рассмотрим их построение для одного из подклассов LL(1) грамматик.
1.1.2 Метод рекурсивного спуска
Метод рекурсивного спуска - хорошо известный и легко реализуемый детерминированный метод разбора сверху вниз. Сего помощью на основании соответствующей грамматики можно написать синтаксический анализатор, причем также быстро как мы можем вообще писать. Для разбора предложений языка может понадобиться много рекурсивных вызовов процедур, соответствующих нетерминалам в грамматике. Если представить грамматику несколько другим путем, то рекурсию можно заменить итерацией. Замена рекурсии итерацией, возможно, делает анализатор более эффективным, а также более удобочитаемым.
Преимущества написания рекурсивного нисходящего анализатора очевидны. Основные из них - это скорость написания анализатора на основании соответствующей грамматики. Другое преимущество заключается в соответствии между грамматикой и анализатором, благодаря которому увеличивается вероятность того, что анализатор окажется правильным, или по крайней мере, того, что ошибки будут носить простой характер. Недостатки этого метода, хотя и менее очевидны, но не менее реальны. Из-за большого числа вызовов процедур во время синтаксического анализа анализатор становится относительно медленным. Кроме того, он может быть относительно большим по сравнению с анализаторами, основанных на табличных методах разбора. Несмотря на то, что данный метод способствует включению в анализатор действий по генерации кода, это неизбежно ведет к смешиванию различных фаз компиляции. Последнее снижает надежность компиляторов или усложняет обращение с ними.
2. Разработка транслятора
2.1 Анализ требований
Необходимо разработать транслятор с заданного языка с использованием детерминированного нисходящего распознавателя (магазины автомат) для грамматики типа LL(1), осуществить программную реализацию и тестирование. Возможность построения для LL(1) грамматики детерминированного автомата определяет значение этих грамматик для практических применений. Однако, при построении грамматики для заданного языка не всегда удается получить грамматику, принадлежащую классу LL(1). Это может случиться потому, что неудачно выбраны правила грамматики, или потому, что для заданного языка принципиально нельзя построить LL(1) грамматику. В первом случае полученную грамматику можно попытаться преобразовать таким образом, чтобы она удовлетворяла условиям LL(1) грамматики. Известно несколько приемов преобразований, которые в некоторых случаях, но не всегда, позволяют получить грамматику требуемого вида. Первый вид преобразований заключается в исключении правил, содержащих левую рекурсию. Второй вид преобразований, который называют выделением общих частей, применяют для устранения правил с одинаковыми левыми частями, правые части которых начинаются одинаковыми последовательностями символов. Далее необходимо проверить является ли полученная грамматика LL(1) грамматикой. Затем нужно разработать лексический анализатор, на вход которого подается исходный текст транслируемой программы, а на выходе формируется последовательность лексем. Далее следует разработать синтаксический анализатор, на вход которого поступает последовательность лексем, которая подвергается соответствующему синтаксическому разбору. Основной же частью разработки синтаксического анализатора является проектирование и разработка соответствующего магазинного автомата. Затем необходимо разработать модуль интерпретации. В заключении нужно провести тестирование транслятора.
2.2 Проектирование
Введем обозначения (см. таблицу № 1).
Таблица №1-список обозначений
Условное обозначение |
Наименование |
|
I A B C D E G J L K M N O BEGIN END VAR P |
<Программа> <Объявление переменных> <Описание вычислений> <Список присваиваний> <Список переменных> <Идентификатор> <Присваивание> <Выражение> <Унарная операция> <Подвыражение> <Операнд> <Бинарная операция> <Константа> BEGIN END VAR <Буква> |
Итак, имеем следующее базовое описание базового языка:
VA={I,A,B,C,D,E,G,J,L,K,M,N,O,P}
VT={=,begin, end, var, not, and, or, imp, 0, 1, :, logical, do, read, (, ), while, while_end, write,a..z}
R={
IAB |
DED |
KNK |
|
AvarD:logical; |
DE |
MO |
|
BbeginCend |
EE |
ME |
|
CG |
EPE |
Nimp |
|
CGC |
GE=J; |
Nor |
|
Cread(D); |
JK |
Nand |
|
Cread(D)C; |
JLK |
O1 |
|
CwhileJdoCwhile_end; |
Lnot |
O0 |
|
CwhileJdoCwhile_endC; |
K(J) |
Pa|..|z |
|
Cwrite(D); |
KM |
||
Cwrite(D)C; |
KK |
Введем обозначения для лексем (см. Таблицу № 2).
Таблица № 2 - представление лексем
begin end var : logical ; not and or imp 1 0 read write ( ) while do while_end <идентификатор> = |
20 21 22 37 23 38 24 25 26 27 1 0 28 29 30 31 32 33 34 35 36 |
Устраним прямую левую рекурсию:
До устранения левой рекурсии |
После устранения левой рекурсии |
|
K(J) KM KK KNK |
K'(J) K'(J)K' K(J) K(J)K' KM KMK' KNK KNKK' K'M K'MK' K'NK K'NKK' |
|
EE EPE |
EPE EPEE' E'PE E'PEE' |
После устранения прямой левой рекурсии получим следующую грамматику:
VA={I,A,B,C,D,E,E',G,J,L,K,K',M,N,O,P}
VT={=,begin, end, var, not, and, or, imp, 0, 1, :, logical, do, read, (, ), while, while_end, write,a..z}
R'={
IAB |
DED |
KNK |
K(J)K' |
|
AvarD:logical; |
DE |
K(J) |
ME |
|
BbeginCend |
EPE |
KM |
MO |
|
CG |
E'PE |
KMK' |
Nor |
|
CGC |
EPEE' |
KNKK' |
Nand |
|
Cread(D) |
E'PEE' |
K'(J) |
Nimp |
|
Cread(D)C; |
GE=J; |
K'(J)K' |
O0 |
|
CwhileJdoCwhile_end; |
JLK |
K'M |
O1 |
|
CwhileJdoCwhile_endC; |
JK |
K'MK' |
Pa|..|z |
|
Cwrite(D); |
Lnot |
K'NK |
||
Cwrite(D)C; |
KK |
K'NKK' |
Далее следует процесс факторизации.
До факторизации |
После факторизации |
|
DE DED |
DED' D'D D'e |
|
CG CGC Cread(D); Cread(D)C; Cwrite(D); Cwrite(D)C; CwhileJdoCwhile_end; CwhileJdoCwhile_endC; |
CGC' C'C C'e Cread(D)C'; Cwrite(D)C'; CwhileJdoCwhile_endC'; |
|
K(J) K(J)K' KM KMK' KNK KNKK' |
K(J)K'' K''K' KMK'' KNKK'' K''e |
|
K'(J) K'(J)K' K'M K'MK' K'NK K'NKK' |
K'(J)K'' K'MK'' K'NKK'' |
|
EPE EPEE' |
EPEE'' E''E' E''e |
|
E'PE E'PEE' |
E'PEE'' |
После факторизации получим следующую грамматику:
VA={I,A,B,C,D,E,E', E''G,J,L,K,K'', K',M,N,O,P}
VT={=,begin, end, var, not, and, or, imp, 0, 1, :, logical, do, read, (, ), while, while_end, write,a..z}
IAB |
D'e |
K(J)K'' |
O0 |
|
AvarD:logical; |
EPEE'' |
K'(J)K'' |
O1 |
|
BbeginCend |
E'PEE'' |
K''e |
P(a|..|z)* |
|
C'C |
E''E' |
K'MK'' |
||
CGC' |
E''e |
K'NKK'' |
||
CwhileJdoCwhile_end;C' |
GE=J; |
KMK'' |
||
Cread(D);C' |
JLK |
ME |
||
C'e |
JK |
MO |
||
Cwrite(D);C' |
Lnot |
Nor |
||
DED' |
KNKK'' |
Nand |
||
D'D |
K''K' |
Nimp |
Проверим, является ли данная грамматика LL(1) грамматикой:
a) Для D'
ПЕРВ(D)e=0
Для C
{read}{write}{if}{(a||z)*}=0
Для C'
ПЕРВ(C) e=0
Для J
ПЕРВ(L) ПЕРВ(K)={not}{(0,1,(a||z)*,and,or,equ)}=0
Для K и K'
ПЕРВ(M) {(}ПЕРВ(N)={0,1,(a||z)*} {(}{and,or,equ }=0
Для K''
ПЕРВ(K') e=0
Для N
{or}{and}{ equ }=0
Для M
ПЕРВ(Е) ПЕРВ(О)={(a||z)*} {1,0}=0
Для О
{1}{0}=0
Для Е''
ПЕРВ(E') e=0
b) Для D'
ПЕРВ(D')=ПЕРВ(D)=ПЕРВ(E)={(a||z)*}
СЛЕД(D')=СЛЕД(O)={)}
СЛЕД(D') ПЕРВ(D')=0
Для C'
ПЕРВ(C')=ПЕРВ(C)={(a||z)*,read,write,if}
СЛЕД(C')=СЛЕД(C)={e}
ПЕРВ(C') СЛЕД(C')=0
Для K''
ПЕРВ(K'')=ПЕРВ(K')={0,1,(a||z)*,(,and,or, equ }
СЛЕД(K'')=СЛЕД(K)СЛЕД(K')={e}
ПЕРВ(K'') СЛЕД(K'')=0
Для E''
ПЕРВ(E'')=ПЕРВ(E')={(a||z)*}
СЛЕД(E'')=СЛЕД(E')СЛЕД(E)={e}
ПЕРВ(E'') СЛЕД(E'')=0
Данная грамматика действительно является LL(1) грамматикой.
Построим детерминированный нисходящий распознаватель:
А) 1.(s0, begin, B)=( s0,end 'C)
2. (s0, var, A)= (s0, ;logical:D)
3. (s0, read, C)= (s0, C';)D( )
4. (s0, write, C)= (s0, C';)D( )
5. (s0, while, C)= (s0, 'C ; While_end C do J)
6. (s0, not, L)=(s0, e)
7. (s0, and, N)=(s0, e)
8. (s0, or, N)=(s0, e)
9. (s0, imp, N)=(s0, e)
10. (s0, 1, O)=(s0, e)
11. (s0, 0, O)=(s0, e)
12. (s0, (a||z)*, P)=(s0, e)
13. (s0, (, K)=(s0, K'')J)
14. (s0, (, K')=(s0, K'')J)
B) 1.(s0, var, I)=(s0, BA)
2.(s0, (a||z)*, D)=(s0, D'E)
3.(s0, (a||z)*, D')=(s0, D)
4.(s0, (a||z)*, C)=(s0, C'G)
5.(s0, (a||z)*, C')=(s0, C)
6.(s0, read, C')=(s0, C)
7.(s0, write, C')=(s0, C)
8.(s0, while, C')=(s0, C)
9.(s0, (a||z)*, G)=(s0, ;J=E)
10.(s0, not, J)=(s0, KL)
11.(s0, (, J)=(s0, K)
12.(s0, (a||z)*, J)=(s0, K)
13.(s0, 0, J)=(s0, K)
14.(s0, 1, J)=(s0, K)
15.(s0, and, J)=(s0, K)
16.(s0, or, J)=(s0, K)
17.(s0, imp, J)=(s0, K)
18.(s0, (a||z)*, K)=(s0, K''M)
19.(s0, 0, K)=(s0, K''M)
20.(s0, 1, K)=(s0, K''M)
21.(s0, and, K)=(s0, K''KN)
22.(s0, or, K)=(s0, K''KN)
23.(s0, imp, K)=(s0, K''KN)
24.(s0, (, K'')=(s0, K')
25.(s0, (a||z)*, K'')=(s0, K')
26.(s0, 0, K'')=(s0, K')
27.(s0, 1, K'')=(s0, K')
28.(s0, and, K'')=(s0, K')
29.(s0, or, K'')=(s0, K')
30.(s0, imp, K'')=(s0, K')
31.(s0, (a||z)*, K')=(s0, K''M)
32.(s0, 0, K')=(s0, K''M)
33.(s0, 1, K')=(s0, K''M)
34.(s0, and, K')=(s0, K''KN)
35.(s0, or, K')=(s0, K''KN)
36.(s0, imp, K')=(s0, K''KN)
37.(s0, (a||z)*, M)=(s0, E)
38.(s0, 0, M)=(s0, O)
39.(s0, 1, M)=(s0, O)
40.(s0, (a||z)*, E)=(s0, E''EP)
41.(s0, (a||z)*, E')=(s0, E''EP)
C) 1.(s0, ), D')=(s0, e)
2.(s0, e, C')=(s0, e)
3.(s0, e, E'')=(s0, e)
4.(s0, e, K'')=(s0, e)
5.(s0, :, D')=(s0, e)
6.(s0, ;, K'')=(s0, e)
7.(s0, ), K'')=(s0, e)
8.(s0, do, K'')=(s0, e)
9.(s0, end, K'')=(s0, e)
10.(s0, while_end, C')=(s0, e)
D) 1. (s0, end, end)=(s0, e)
2. (s0, :, :)=(s0, e)
3. (s0, logical , logical)=(s0, e)
4. (s0, do, do)=(s0, e)
5. (s0, while_end, while_end)=(s0, e)
6. (s0, ), ))=(s0, e)
7. (s0, ;, ;)=(s0, e)
8. (s0, =, =)=(s0, e)
2.3 Кодирование
В процедуре TForm1.FormCreate(Sender: TObject) задаются функции переходов магазинного автомата. В процедуре TForm1.analyze1Click(Sender: TObject) реализованы синтаксический и лексический анализаторы. Процедура postfix формирует список, представляющий из себя постфиксную польскую запись вычисляемого выражения, а функция cntr:byte вычисляет значение выражения по данному списку.
Процедура TForm1.Make1Click(Sender: TObject) выполняет непосредственную интерпретацию. Процедура TForm1.Memo3KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState) отвечает за ввод данных пользователем при выполнении программы. Также программа предоставляет возможность просмотреть функции, использованные при синтаксическом анализе, увидеть значение всех переменных после выполнения программ, просмотреть представления лексем. Текст программы приведен в приложении А.
2.3.1 Разработка анализатора
При разработке анализатора была использована следующая схема
Рисунок 1 - Схема работы анализатора
Анализатор состоит из двух частей:
- П1 - блок лексического анализатора
- П2 - блок синтаксического анализатора.
Исходный текст, подаваемый на вход П1, подвергается лексическому разбору, и на выходе из П1 формируется список лексем. Полученная последовательность лексем подается на вход П2. Синтаксический анализатор по полученному списку лексем проверяет корректно ли составлена программа и нет ли в исходном тексте синтаксических ошибок.
Для создания лексического анализатора была реализована следующие списочные структуры:
Vrb=^VarList; - список идентификаторов
VarList=record
id:string;
value:byte;
right:Vrb;
end;
Lex=^Lexem; - список лексем
Lexem=record
id:byte;
up:Vrb;
right:Lex;
end;
Mag=^Magazin; - список используемый при построении магазина
Magazin=record
id:string;
mleft:Mag;
end;
2.3.1 Лексический анализатор
Предназначен для разбора лексем транслируемой программы. На вход лексического анализатора подается исходный код программы, выходными данными является список лексем.
Все лексемы можно разделить на зарезервированные лексемы и лексемы-идентификаторы (таблица № 2). Получив на вход исходный текст, лексический анализатор обращается поочередно к каждой строке. При разборе каждой строки выделяются отдельные лексемы, а соответствующие им номера заносятся в созданный список. Если текущая лексема не равна ни одной зарезервированной, она является идентификатором (номер, соответствующий идентификатору - 35). Лексема такого рода проверяется на длину, она не должна превышать 12, и на то, чтобы в имени идентификатора содержались только буквы. Если все требования выполняются, номер лексемы добавляется к списку. Так как номер, соответствующий идентификатору один, параллельно основному списку создается список непосредственно самих идентификаторов. В результате работы лексического анализатора на выходе получим следующую списочную структуру
object pascal грамматический транслятор
Рисунок № 2 - схема структуры на выходе лексического анализатора
В тексте программы идентификаторы встречаются в двух местах: объявление переменных и основной блок программы. Именно поэтому и была организована структура, представленная на рисунке №2. Идентификатор Ид.2 встречается два раза, а Ид.1 один раз. Поэтому на второй идентификатор ссылаются две лексемы, а на первый одна.
2.3.2 Синтаксический анализатор
Работа синтаксического анализатора заключается в грамматическом разборе, поиске синтаксических ошибок и выдаче сообщений о них. Если программа составлена корректно, то управление передается интерпретатору, если же в тексте найдены синтаксические ошибки, выполнение программы невозможно. Для синтаксического анализатора необходимы функции переходов, которые задаются в процедуре создания формы TForm1.FormCreate(Sender: TObject).
2.4 Тестирование
При тестировании программы применялся метод функционального тестирования, т. е. тестировались только функции программы, и не рассматривалось внутреннее ее содержание. В первом тесте был набран текст программы, соответствующий заданной грамматике. Лексический и синтаксический анализаторы ошибок не обнаружили (см. рисунок 1).
Далее программа была запущена на выполнение. Результат на рисунке 2.
Также в этом тесте были просмотрены таблица со значениями переменных (рисунок 3), таблица использованных функций переходов (рисунок 4) и таблица представления лексем (рисунок 5).
Во втором тесте введенная программа противоречила заданному языку и лексический анализатор выдал ошибку (рисунок 6).
В третьем тесте в веденном тексте программы не были закрыты операторные скобки цикла while и синтаксический анализатор выдал ошибку.
Заключение
В результате выполнения курсового проектирования был разработан учебный транслятор с заданного языка.
Разработка проводилась на базовом языке программирования Object Pascal в среде объектно-ориентированного визуального программирования Borland Delphi 6.0 .
Разработка проведена с использованием операционной системы Windows 2000 на персональном компьютере IBM PC с процессором Intel Pentium III.
Осуществлено функциональное тестирование разработанного транслятора, которое показало корректность его работы.
Личный вклад автора в общую разработку учебного транслятора заключается в программной реализации лексического и синтаксического анализатора.
Список использованных источников
1. Хантер Р. Проектирование и конструирование компиляторов. - М.: Финансы и статистика, 1984. - 232 с.
Приложение А
Листинг программного текста транслятора
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Menus;
type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
Memo1: TMemo;
Label1: TLabel;
MainMenu1: TMainMenu;
Run1: TMenuItem;
analyze1: TMenuItem;
Make1: TMenuItem;
View1: TMenuItem;
Valuesofvariables1: TMenuItem;
Functionsoftransition1: TMenuItem;
ableofdisignations1: TMenuItem;
Label2: TLabel;
Memo3: TMemo;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure analyze1Click(Sender: TObject);
procedure Functionsoftransition1Click(Sender: TObject);
procedure Make1Click(Sender: TObject);
procedure Memo3KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure Memo1Change(Sender: TObject);
procedure ableofdisignations1Click(Sender: TObject);
procedure Valuesofvariables1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Vrb=^VarList;
VarList=record
id:string;
value:byte;
right:Vrb;
end;
Lex=^Lexem;
Lexem=record
id:byte;
up:Vrb;
right:Lex;
end;
Mag=^Magazin;
Magazin=record
id:string;
mleft:Mag;
end;
whl=^ptrWh;
ptrWh=record
beg:Lex;
wend:Lex;
mleft:whl;
end;
procedure ClrLst;
procedure postfix;
const count=71;
var
Form1: TForm1;
kon,curr,mleft,vir1,vir2,vir3,ptr:Lex;
vkon,vcurr,vleft:Vrb;
mkon,mcurr,mright:Mag;
cwhl,kwhl,pwhl:whl;
func:array [1..count,1..4]of string;
make:boolean;
implementation
{$R *.DFM}
uses unit2;
procedure ClrLst;
begin
Form2.Memo1.Lines.Clear;
curr:=mleft;
while curr<>nil do
begin
kon:=curr^.right;
Dispose(curr);
curr:=kon;
end;
vcurr:=vleft;
while vcurr<>nil do
begin
vkon:=vcurr^.right;
Dispose(vcurr);
vcurr:=vkon;
end;
mcurr:=mright;
while mcurr<>nil do
begin
mright:=mcurr^.mleft;
Dispose(mcurr);
mcurr:=mright;
end;
mleft:=nil;
vleft:=nil;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ClrLst;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
mleft:=nil;
vleft:=nil;
mright:=nil;
ptr:=nil;
pwhl:=nil;
Form1.Make1.Enabled:=false;
Form1.Functionsoftransition1.Enabled:=false;
Form1.Valuesofvariables1.Enabled:=false;
make:=false;
func[1,1]:='20';func[1,2]:='B';func[1,3]:='21 H';func[1,4]:='+';
func[2,1]:='22';func[2,2]:='A';func[2,3]:='38 23 37 D';func[2,4]:='+';
func[3,1]:='28';func[3,2]:='C';func[3,3]:='H 38 31 D 30';func[3,4]:='+';
func[4,1]:='29';func[4,2]:='C';func[4,3]:='H 38 31 D 30';func[4,4]:='+';
func[5,1]:='32';func[5,2]:='C';func[5,3]:='H 38 34 C 33 J';func[5,4]:='+';
func[6,1]:='24';func[6,2]:='L';func[6,3]:='';func[6,4]:='+';
func[7,1]:='25';func[7,2]:='N';func[7,3]:='';func[7,4]:='+';
func[8,1]:='26';func[8,2]:='N';func[8,3]:='';func[8,4]:='+';
func[9,1]:='27';func[9,2]:='N';func[9,3]:='';func[9,4]:='+';
func[10,1]:='1';func[10,2]:='O';func[10,3]:='';func[10,4]:='+';
func[11,1]:='0';func[11,2]:='O';func[11,3]:='';func[11,4]:='+';
func[12,1]:='35';func[12,2]:='E';func[12,3]:='';func[12,4]:='+';
func[13,1]:='30';func[13,2]:='K';func[13,3]:='R 31 J';func[13,4]:='+';
func[14,1]:='30';func[14,2]:='Q';func[14,3]:='R 31 J';func[14,4]:='+';
func[15,1]:='22';func[15,2]:='I';func[15,3]:='B A';func[15,4]:='-';
func[16,1]:='35';func[16,2]:='D';func[16,3]:='F E';func[16,4]:='-';
func[17,1]:='35';func[17,2]:='F';func[17,3]:='D';func[17,4]:='-';
func[18,1]:='35';func[18,2]:='C';func[18,3]:='H G';func[18,4]:='-';
func[19,1]:='35';func[19,2]:='H';func[19,3]:='C';func[19,4]:='-';
func[20,1]:='28';func[20,2]:='H';func[20,3]:='C';func[20,4]:='-';
func[21,1]:='29';func[21,2]:='H';func[21,3]:='C';func[21,4]:='-';
func[22,1]:='32';func[22,2]:='H';func[22,3]:='C';func[22,4]:='-';
func[23,1]:='35';func[23,2]:='G';func[23,3]:='38 J 36 E';func[23,4]:='-';
func[24,1]:='24';func[24,2]:='J';func[24,3]:='K L';func[24,4]:='-';
func[25,1]:='30';func[25,2]:='J';func[25,3]:='K';func[25,4]:='-';
func[26,1]:='35';func[26,2]:='J';func[26,3]:='K';func[26,4]:='-';
func[27,1]:='25';func[27,2]:='J';func[27,3]:='K';func[27,4]:='-';
func[28,1]:='26';func[28,2]:='J';func[28,3]:='K';func[28,4]:='-';
func[29,1]:='27';func[29,2]:='J';func[29,3]:='K';func[29,4]:='-';
func[30,1]:='1';func[30,2]:='J';func[30,3]:='K';func[30,4]:='-';
func[31,1]:='0';func[31,2]:='J';func[31,3]:='K';func[31,4]:='-';
func[32,1]:='1';func[32,2]:='K';func[32,3]:='R M';func[32,4]:='-';
func[33,1]:='0';func[33,2]:='K';func[33,3]:='R M';func[33,4]:='-';
func[34,1]:='35';func[34,2]:='K';func[34,3]:='R M';func[34,4]:='-';
func[35,1]:='25';func[35,2]:='K';func[35,3]:='R K N';func[35,4]:='-';
func[36,1]:='26';func[36,2]:='K';func[36,3]:='R K N';func[36,4]:='-';
func[37,1]:='27';func[37,2]:='K';func[37,3]:='R K N';func[37,4]:='-';
func[38,1]:='30';func[38,2]:='R';func[38,3]:='Q';func[38,4]:='-';
func[39,1]:='35';func[39,2]:='R';func[39,3]:='Q';func[39,4]:='-';
func[40,1]:='0';func[40,2]:='R';func[40,3]:='Q';func[40,4]:='-';
func[41,1]:='1';func[41,2]:='R';func[41,3]:='Q';func[41,4]:='-';
func[42,1]:='25';func[42,2]:='R';func[42,3]:='Q';func[42,4]:='-';
func[43,1]:='26';func[43,2]:='R';func[43,3]:='Q';func[43,4]:='-';
func[44,1]:='27';func[44,2]:='R';func[44,3]:='Q';func[44,4]:='-';
func[45,1]:='35';func[45,2]:='Q';func[45,3]:='R M';func[45,4]:='-';
func[46,1]:='0';func[46,2]:='Q';func[46,3]:='R M';func[46,4]:='-';
func[47,1]:='1';func[47,2]:='Q';func[47,3]:='R M';func[47,4]:='-';
func[48,1]:='25';func[48,2]:='Q';func[48,3]:='R K N';func[48,4]:='-';
func[49,1]:='26';func[49,2]:='Q';func[49,3]:='R K N';func[49,4]:='-';
func[50,1]:='27';func[50,2]:='Q';func[50,3]:='R K N';func[50,4]:='-';
func[51,1]:='1';func[51,2]:='M';func[51,3]:='O';func[51,4]:='-';
func[52,1]:='0';func[52,2]:='M';func[52,3]:='O';func[52,4]:='-';
func[53,1]:='35';func[53,2]:='M';func[53,3]:='E';func[53,4]:='-';
func[54,1]:='31';func[54,2]:='F';func[54,3]:='';func[54,4]:='-';
func[55,1]:='';func[55,2]:='H';func[55,3]:='';func[55,4]:='-';
func[56,1]:='';func[56,2]:='R';func[56,3]:='';func[56,4]:='-';
func[57,1]:='21';func[57,2]:='21';func[57,3]:='';func[57,4]:='+';
func[58,1]:='37';func[58,2]:='37';func[58,3]:='';func[58,4]:='+';
func[59,1]:='23';func[59,2]:='23';func[59,3]:='';func[59,4]:='+';
func[60,1]:='33';func[60,2]:='33';func[60,3]:='';func[60,4]:='+';
func[61,1]:='34';func[61,2]:='34';func[61,3]:='';func[61,4]:='+';
func[62,1]:='31';func[62,2]:='31';func[62,3]:='';func[62,4]:='+';
func[63,1]:='38';func[63,2]:='38';func[63,3]:='';func[63,4]:='+';
func[64,1]:='36';func[64,2]:='36';func[64,3]:='';func[64,4]:='+';
func[65,1]:='37';func[65,2]:='F';func[65,3]:='';func[65,4]:='-';
func[66,1]:='38';func[66,2]:='R';func[66,3]:='';func[66,4]:='-';
func[67,1]:='31';func[67,2]:='R';func[67,3]:='';func[67,4]:='-';
func[68,1]:='33';func[68,2]:='R';func[68,3]:='';func[68,4]:='-';
func[69,1]:='30';func[69,2]:='30';func[69,3]:='';func[69,4]:='+';
func[70,1]:='21';func[70,2]:='H';func[70,3]:='';func[70,4]:='-';
func[71,1]:='34';func[71,2]:='H';func[71,3]:='';func[71,4]:='-';
end;
procedure TForm1.analyze1Click(Sender: TObject);
var
i,k,l,m,j,o,p:integer;
str1,str2:string;
vr,fnd:boolean;
begin
ClrLst;
//Лексический анализатор
vr:=true;
k:=Memo1.Lines.Count;
for i:=0 to k-1 do
begin
str1:=Memo1.Lines[i];
j:=Length(str1);
Delete(str2,1,Length(str2));
for l:=1 to j do
begin
if str1[l]<>' ' then
str2:=str2+str1[l];
if ((str1[l]=' ') or (l=j)) and (str2<>'') then
begin
if str2='begin' then
begin
m:=20;
vr:=false;
end
else if str2='end' then m:=21
else if str2='var' then m:=22
else if str2='logical' then m:=23
else if str2='not' then m:=24
else if str2='and' then m:=25
else if str2='or' then m:=26
else if str2='imp' then m:=27
else if str2='1' then m:=1
else if str2='0' then m:=0
else if str2='read' then m:=28
else if str2='write' then m:=29
else if str2='(' then m:=30
else if str2=')' then m:=31
else if str2='while' then m:=32
else if str2='do' then m:=33
else if str2='while_end' then m:=34
else if str2='=' then m:=36
else if str2=':' then m:=37
else if str2=';' then m:=38
else
begin
if Length(str2)>12 then
begin
ShowMessage('Слишком длинный идентификатор '+str2);
ClrLst;
exit;
end;
p:=Length(str2);
for o:=1 to p do
if ((ord(str2[o])<65)or(ord(str2[o])>90))and((ord(str2[o])<97)or(ord(str2[o])>122)) then
begin
ShowMessage('Наименование идентификатора должно содержать только буквы');
ClrLst;
exit;
end;
m:=35;
end;
if (m=35) and (vr) then
begin
new(vcurr);
vcurr^.id:=str2;
vcurr^.value:=0;
vcurr^.right:=nil;
if vleft=nil then vleft:=vcurr
else
begin
vkon:=vleft;
while vkon^.right<>nil do
vkon:=vkon^.right;
vkon^.right:=vcurr;
end;
new(curr);
curr^.id:=m;
curr^.up:=vcurr;
curr^.right:=nil;
if mleft=nil then mleft:=curr
else
begin
kon:=mleft;
while kon^.right<>nil do
kon:=kon^.right;
kon^.right:=curr;
end;
end
else if (m=35) and (not vr) then
begin
fnd:=false;
vcurr:=vleft;
while vcurr<>nil do
begin
if vcurr^.id=str2 then
begin
fnd:=true;
break;
end;
vcurr:=vcurr^.right;
end;
if fnd then
begin
new(curr);
curr^.id:=m;
curr.up:=vcurr;
curr^.right:=nil;
if mleft=nil then mleft:=curr
else
begin
kon:=mleft;
while kon^.right<>nil do
kon:=kon^.right;
kon^.right:=curr;
end;
end
else
begin
ShowMessage('Неизвестный идентификатор '+str2);
ClrLst;
exit;
end;
end
else
begin
new(curr);
curr^.id:=m;
curr.up:=nil;
curr^.right:=nil;
if mleft=nil then mleft:=curr
else
begin
kon:=mleft;
while kon^.right<>nil do
kon:=kon^.right;
kon^.right:=curr;
end;
end;
Delete(str2,1,Length(str2));
end;
end;
end;
//Синтаксический анализатор
curr:=mleft;
new(mright);
mright^.id:='I';
mright^.mleft:=nil;
while true do
begin
for i:=1 to count do
begin
if (curr=nil)and (func[i,1]='')and (func[i,2]=mright^.id) then
begin Form2.Memo1.Lines.Add('(s0,'+func[i,1]+','+func[i,2]+')=(s0,'+func[i,3]+')');
mcurr:=mright;
mright:=mright^.mleft;
Dispose(mcurr);
break;
end
else if (func[i,1]=IntToStr(curr^.id))and(func[i,2]=mright^.id) then
begin
k:=length(func[i,3]);
str1:=func[i,3]; Form2.Memo1.Lines.Add('(s0,'+func[i,1]+','+func[i,2]+')=(s0,'+func[i,3]+')');
mkon:=mright;
Delete(str2,1,Length(str2));
if k>0 then
for j:=1 to k do
begin
if str1[j]<>' ' then
str2:=str2+str1[j];
if ((str1[j]=' ') or (j=k)) and (str2<>'') then
begin
mcurr:=mright;
new(mright);
mright^.id:=str2;
mright^.mleft:=mcurr;
Delete(str2,1,Length(str2));
end;
end;
if mkon=mright then
begin
mright:=mright^.mleft;
Dispose(mkon);
end
else
begin
mcurr:=mright;
while mcurr^.mleft<>mkon do
mcurr:=mcurr^.mleft;
mcurr^.mleft:=mkon^.mleft;
Dispose(mkon);
end;
if func[i,4]='+' then
curr:=curr^.right;
break;
end;
end;
if (curr=nil)and(mright=nil) then
begin
ShowMessage('Синтаксических и лексических ошибок в тексте программы не найдено');
Form1.Make1.Enabled:=true;
Form1.Functionsoftransition1.Enabled:=true;
Form1.Valuesofvariables1.Enabled:=false;
break;
end;
if i>count then
begin
ShowMessage('В тексте программы найдена ошибка');
break;
end;
end;
end;
procedure TForm1.Functionsoftransition1Click(Sender: TObject);
begin
Form2.Memo1.Visible:=true;
Form2.Memo2.Visible:=false;
Form2.StringGrid1.Visible:=false;
Form2.Show;
end;
procedure postfix;
var
lex1,lex2:Lex;
begin
while (vir2^.id<>38) and (vir2^.id<>33) do
begin
if vir2^.id=31 then
exit;
if (vir2^.id=35)or(vir2^.id=0)or(vir2^.id=1) then
begin
new(vir1);
vir1^.id:=vir2^.id;
vir1^.up:=vir2^.up;
if ptr=nil then
ptr:=vir1
else
vir3^.right:=vir1;
vir1^.right:=nil;
vir3:=vir1;
end;
if (vir2^.id=25) or (vir2^.id=26) or (vir2^.id=27)or (vir2^.id=24) then
begin
lex1:=vir2;
lex2:=vir2^.right;
if (lex2^.id=35)or(lex2^.id=0)or(lex2^.id=1) then
begin
new(vir1);
vir1^.id:=lex2^.id;
vir1^.up:=lex2^.up;
if ptr=nil then
ptr:=vir1
else
vir3^.right:=vir1;
vir1^.right:=nil;
vir3:=vir1;
new(vir1);
vir1^.id:=vir2^.id;
vir1^.up:=vir2^.up;
vir3^.right:=vir1;
vir1^.right:=nil;
vir3:=vir1;
vir2:=vir2^.right;
end
else if lex2^.id=30 then
begin
vir2:=lex2^.right;
postfix;
new(vir1);
vir1^.id:=lex2^.id;
vir1^.up:=lex2^.up;
vir1^.right:=nil;
vir3^.right:=vir1;
vir3:=vir1;
end;
end;
if lex2^.id=30 then
begin
vir2:=lex2^.right;
postfix;
new(vir1);
vir1^.id:=lex2^.id;
vir1^.up:=lex2^.up;
vir1^.right:=nil;
vir3^.right:=vir1;
vir3:=vir1;
end;
vir2:=vir2^.right;
end;
end;
function cntr:byte;
var
lex1,lex2:Lex;
v3,v2:byte;
begin
vir1:=ptr;
while (vir1<>ptr) or (vir1^.right<>nil) do
begin
if (vir1^.id=35) or (vir1^.id=0) or (vir1^.id=1) then vir1:=vir1^.right;
if (vir1^.id=25) or (vir1^.id=26) or (vir1^.id=27) then
begin
vir2:=ptr;
while vir2^.right<>vir1 do
vir2:=vir2^.right;
vir3:=ptr;
while vir3^.right<>vir2 do
vir3:=vir3^.right;
new(lex1);
lex1^.right:=vir1^.right;
lex1^.up:=nil;
if vir2^.id=0 then v2:=0
else if vir2^.id=1 then v2:=1
else
begin
vcurr:=vir2^.up;
v2:=vcurr^.value;
end;
if vir3^.id=0 then v3:=0
else if vir3^.id=1 then v3:=1
else
begin
vcurr:=vir3^.up;
v3:=vcurr^.value;
end;
if vir1^.id=25 then
if (v2=0) or (v3=0) then lex1^.id:=0
else lex1^.id:=1;
if vir1^.id=26 then
if (v2=1) or (v3=1) then lex1^.id:=1
else lex1^.id:=0;
if vir1^.id=27 then
if (v2=0) or (v3=1) then lex1^.id:=0
else lex1^.id:=1;
if vir3=ptr then ptr:=lex1
else
begin
lex2:=ptr;
while lex2^.right<>vir3 do
lex2:=lex2^.right;
lex2^.right:=lex1;
end;
Dispose(vir1);
Dispose(vir2);
Dispose(vir3);
vir1:=lex1;
end;
if vir1^.id=24 then
begin
vir2:=ptr;
while vir2^.right<>vir1 do
vir2:=vir2^.right;
new(lex1);
lex1^.right:=vir1^.right;
lex1^.up:=nil;
if vir2^.id=0 then v2:=0
else if vir2^.id=1 then v2:=1
else
begin
vcurr:=vir2^.up;
v2:=vcurr^.value;
end;
if v2=1 then lex1^.id:=0
else lex1^.id:=1;
if vir2=ptr then ptr:=lex1
else
begin
lex2:=ptr;
while lex2^.right<>vir2 do
lex2:=lex2^.right;
lex2^.right:=lex1;
end;
Dispose(vir1);
Dispose(vir2);
vir1:=lex1;
end;
end;
if vir1^.id=0 then cntr:=0
else if vir1^.id=1 then cntr:=1
else
begin
vcurr:=vir1^.up;
cntr:=vcurr^.value;
end;
ptr:=nil;
Dispose(vir1);
end;
procedure TForm1.Make1Click(Sender: TObject);
var
value,cicl:byte;
begin
if not make then
begin
curr:=mleft;
make:=true;
Memo1.Enabled:=false;
end;
while curr<>nil do
begin
if curr^.id=28 then
begin
curr:=curr^.right;
curr:=curr^.right;
Memo3.SetFocus;
exit;
end;
if curr^.id=29 then
begin
curr:=curr^.right;
curr:=curr^.right;
while curr^.id=35 do
begin
vcurr:=curr^.up;
Memo3.Lines.Add(IntToStr(vcurr^.value)+' ');
curr:=curr^.right;
end;
end;
if curr^.id=32 then
begin
vir2:=curr^.right;
postfix;
value:=cntr;
cicl:=1;
if value=1 then
begin
new(cwhl);
cwhl^.beg:=curr^.right;
while (curr^.id<>34)or(cicl<>2)do
begin
if curr^.id=32 then cicl:=cicl+1;
if curr^.id=34 then cicl:=cicl-1;
curr:=curr^.right;
end;
cwhl^.wend:=curr^.right;
curr:=cwhl^.beg;
cwhl^.mleft:=pwhl;
pwhl:=cwhl;
end
else
begin
cicl:=1;
while (curr^.id<>34)or(cicl<>2)do
begin
if curr^.id=32 then cicl:=cicl+1;
if curr^.id=34 then cicl:=cicl-1;
curr:=curr^.right;
end;
curr:=curr^.right;
end;
end;
if curr^.id=34 then
begin
vir2:=pwhl^.beg;
postfix;
value:=cntr;
if value=1 then
curr:=pwhl^.beg
else
begin
curr:=pwhl^.wend;
cwhl:=pwhl;
pwhl:=pwhl^.mleft;
Dispose(cwhl);
end;
end;
if curr^.id=36 then
begin
vir2:=curr^.right;
postfix;
value:=cntr;
kon:=mleft;
While kon^.right<>curr do
kon:=kon^.right;
vcurr:=kon^.up;
vcurr^.value:=value;
end;
curr:=curr^.right;
end;
make:=false;
Memo1.Enabled:=true;
Form1.Valuesofvariables1.Enabled:=true;
end;
procedure TForm1.Memo3KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
str1,str2:string;
j,l:integer;
begin
if (key=13)and(make) then
begin
str1:=Memo3.Lines.Strings[Memo3.Lines.Count-1];
j:=Length(str1);
Delete(str2,1,Length(str2));
for l:=1 to j do
begin
if str1[l]<>' ' then
str2:=str2+str1[l];
if ((str1[l]=' ') or (l=j)) and (str2<>'')and((str2='0')or(str2='1')) then
begin
vcurr:=curr^.up;
vcurr^.value:=StrToInt(str2);
curr:=curr^.right;
if curr^.id<>35 then
begin
TForm1.Make1Click(Sender);
exit;
end;
end
else if(str2<>'0')and(str2<>'1') then
begin
ShowMessage('Вводимые числа должны быть 0 или 1. Выполнение программы остановено.');
make:=false;
Memo1.Enabled:=true;
exit;
end;
end;
Memo3.SetFocus;
end;
end;
procedure TForm1.Memo1Change(Sender: TObject);
begin
Form1.Valuesofvariables1.Enabled:=false;
Form1.Functionsoftransition1.Enabled:=false;
end;
procedure TForm1.ableofdisignations1Click(Sender: TObject);
begin
Form2.Memo1.Visible:=false;
Form2.Memo2.Visible:=false;
Form2.StringGrid1.Visible:=true;
Form2.Show;
end;
procedure TForm1.Valuesofvariables1Click(Sender: TObject);
begin
Form2.Memo1.Visible:=false;
Form2.Memo2.Visible:=true;
Form2.StringGrid1.Visible:=false;
vcurr:=vleft;
Form2.Memo2.Lines.Clear;
Form2.Memo2.Lines.Add('Значение Идентификатор');
while vcurr<>nil do
begin
Form2.Memo2.Lines.Add(IntToStr(vcurr^.value)+' '+vcurr^.id);
vcurr:=vcurr^.right;
end;
Form2.Show;
end;
end.
Приложение Б
Результаты тестирования
Рисунок 1
Рисунок 2
Рисунок 3
Рисунок 4
Рисунок 5
Рисунок 6
Рисунок 7
Размещено на Allbest.ru
Подобные документы
Разработка учебного транслятора на языке программирования C# в среде объектно-ориентированного программирования Visual Studio 2012. Выделение лексем и построение цепочки символов на этапе синтаксического анализа. Функциональное тестирование программы.
курсовая работа [406,8 K], добавлен 07.08.2013Создание Windows-приложения на алгоритмическом языке Object Pascal в среде визуального программирования Delphi, которое, как планируется, будет обеспечивать решение специализированных задач по формированию, обработке на ЭВМ и выводу информации.
курсовая работа [967,6 K], добавлен 20.05.2008Основные понятия и структура обработчика на языке Pascal. Элективные курсы по информатике в системе профильного обучения. Элективный курс "Программирование в среде Delphi". Методические материалы по изучению программирования на языке Object Pascal.
методичка [55,4 K], добавлен 08.12.2010Описания объектов, свойств, методов, формы и основных модулей текста программы в среде Delphi. Создание Windows-приложения на алгоритмическом языке Object Pascal в среде визуального программирования. Анализ результатов тестирования программного продукта.
курсовая работа [2,4 M], добавлен 27.08.2012Разработка Windows-приложений с использованием библиотеки MFC. Базовый набор классов, написанных на языке С++ и предназначенных для упрощения процесса программирования под Windows. Фундаментальные идеи объектно-ориентированного программирования.
курсовая работа [348,1 K], добавлен 02.07.2011Принципы разработки алгоритмов и программ на основе процедурного подхода и на основе объектно-ориентированного подхода. Реализация программы Borland Pascal 7.0, ее интерфейс. Разработка простой программы в среде визуального программирования Delphi.
отчет по практике [934,7 K], добавлен 25.03.2012Особенности разработки приложений для операционной системы с помощью императивного, структурированного, объектно-ориентированного языка программирования Delphi. Формальное начало программы. Выделение конца программного блока. Листинг и описание программы.
курсовая работа [1,2 M], добавлен 04.08.2014Методы грамматического разбора при разработке учебного транслятора. Проектирование лексического анализатора и магазинного автомата. Программная реализация синтаксического анализатора текстового языка высокого уровня. Разработка модуля интерпретации.
курсовая работа [697,2 K], добавлен 06.01.2013Понятие объектно-ориентированного программирования, характеристика используемых языков. Практическая разработка средств объектно-ориентированного программирования в задачах защиты информации: программная реализация на языке С++, а также Turbo Pascal.
курсовая работа [275,9 K], добавлен 22.12.2011Обзор основных используемых языков программирования (С++, Java, Pascal). Анализ существующих методов шифрования паролей. Основные понятия объектно-ориентированного программирования. Реализация приложения для генерирования паролей на языке Object Pascal.
курсовая работа [822,4 K], добавлен 07.07.2012