Условные операторы и описание простых типов языка Си. Предиктивный анализатор - Программирование, компьютеры и кибернетика курсовая работа

Условные операторы и описание простых типов языка Си. Предиктивный анализатор - Программирование, компьютеры и кибернетика курсовая работа




































Главная

Программирование, компьютеры и кибернетика
Условные операторы и описание простых типов языка Си. Предиктивный анализатор

Конструкции условных операторов if-else и простые типы языка Си. Общая схема работы компилятора. Алгоритм построения дерева разбора, строки вывода синтаксического разбора. Построение обратной польской записи как формы внутреннего представления программы.


посмотреть текст работы


скачать работу можно здесь


полная информация о работе


весь список подобных работ


Нужна помощь с учёбой? Наши эксперты готовы помочь!
Нажимая на кнопку, вы соглашаетесь с
политикой обработки персональных данных

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

- овладение и закрепление навыков построения лексического анализатора;
- овладение и закрепление навыков построения синтаксического анализатора;
- исследование принципов работы компилятора на каждом этапе обработки входной последовательности;
- овладение и закрепление навыков оформления документации;
- овладение и закрепление навыков трансляции в форму внутреннего представления: обратную польскую запись.
МП-автомат - автомат с магазинной памятью
Данный документ содержит описание и характеристику программы, написанной на основе задания на курсовую работу по теме «Условные операторы описание простых типов языка Си. Предиктивный анализатор».
В расчётно-пояснительной записке описывается функциональное назначение разработанной программы, приводится её логическая структура и используемые технические средства.
В приложении 1 приведено техническое задание на курсовую работу.
В приложении 2 содержатся блок-схемы алгоритмов программы.
Приложение 3 представляет собой руководство пользователя.
Приложение 4 содержит граф конечного автомата
Приложение 5 содержит листинг программы.
Данный программный продукт является программной реализацией компонентов транслятора (таких как лексический и синтаксический анализ) для некоторых конструкций языка программирования Си.
Использование этого программного средства направлено на:
- изучение принципов работы лексического анализатора,
- изучение принципов работы синтаксического анализатора,
- анализ принадлежности входных строк искомой грамматике,
- трансляцию заданной инструкции в форму внутреннего представления,
- оценку и исправление возможных ошибок,
в рамках учебного курса по дисциплине «Теория языков программирования и методов трансляции».
Программный продукт предназначен для анализа входной последовательности символов на соответствие грамматике, указанной в техническом задании
? считать введенную пользователем конструкцию языка и провести лексический анализ этой конструкции, результатом которого является псевдокод;
? на основе построенной грамматики провести синтаксический анализ, результатом которого являются цепочка вывода и дерево вывода;
? транслировать инструкции в одну из форм внутреннего представления: обратную польскую запись.
Для работы программы необходима операционная система Windows 9x / Me / NT /XR. Программа также предусматривает работу с нестандартным компонентом dxOrgChart (производится вывод деревьев в удобной для просмотра форме), для чего потребуется установить в Delphi палитру компонентов ExpressOrgChart.
Основными задачами, решение которых может быть произведено с помощью разработанной программной системы, являются:
· Перевод исходной программы на внутренний язык компилятора, т. е. лексическая обработка;
· Синтаксический анализ входной последовательности на соответствие грамматике;
· Построение дерева разбора, строки вывода синтаксического разбора;
· Построение обратной польской записи как формы внутреннего представления программы.
1.2.1 Общая схема работы компилятора
Компиляторы составляют существенную часть программного обеспечения ЭВМ. Это связано с тем, что ЯВУ стали основными средствами разработки программ.
Общая схема работы компилятора показана на рис.1, из неё видно, что процесс компиляции состоит из двух основных этапов - анализа и синтеза.
Рис.1 Общая схема работы компилятора
На этапе анализа выполняется распознавание текста исходной программы, создание и заполнение таблиц идентификаторов. Результатом его работы служит некое внутреннее представление программы, понятное компилятору.
На этапе синтеза на основании внутреннего представления программы и информации, содержащейся в таблице (таблицах) идентификаторов, порождается текст результирующей программы. Результатом этого этапа является объектный код.
Кроме того, в составе компилятора присутствует часть, ответственная за анализ и исправление ошибок, которая при наличии ошибки в тексте исходной программы должна максимально полно информировать пользователя о типе ошибки и месте её возникновения. В лучшем случае компилятор может предложить вариант исправления ошибки.
Эти этапы, в свою очередь, состоят из более мелких этапов, называемых фазами компиляции.
Состав фаз компиляции приведён в самом общем виде, их конкретная реализация и процесс взаимодействия могут, конечно, различаться в зависимости от версии компилятора. Однако в том или ином виде все представленные фазы практически всегда присутствуют в каждом конкретном компиляторе.
Это основная часть компилятора, которая читает литеры программы на исходном языке и строит из них слова (лексемы) исходного языка. На вход лексического анализатора поступает текст исходной программы, а выходная информация передаётся для дальнейшей обработки компилятором на этапе синтаксического разбора.
Это основная часть компилятора на этапе анализа. Она выполняет выделение синтаксических конструкций в тексте исходной программы, обработанной лексическим анализатором. На этой же фазе компиляции проверяется синтаксическая правильность программы.
Это часть компилятора, проверяющая правильность текста исходной программы с точки зрения семантики входного языка. Также семантический анализ должен выполнять преобразования текста, требуемые семантикой входного языка (такие, как добавление функций неявного преобразования типов). В различных реализациях компиляторов семантический анализ может частично входить в фазу синтаксического разбора, частично - в фазу подготовки к генерации кода.
Это фаза, на которой компилятором выполняются предварительные действия, непосредственно связанные с синтезом текста результирующей программы, но ещё не ведущие к порождению текста на выходном языке. Обычно в эту фазу входят действия, связанные с идентификацией элементов языка, распределением памяти и т.п.
Это фаза, непосредственно связанная с порождением команд, составляющих предложения выходного языка и в целом текст результирующей программы. Это основная фаза на этапе синтеза результирующей программы. Кроме того, генерация обычно включает в себя также оптимизацию - процесс, связанный с обработкой уже порождённого текста. Иногда оптимизацию выделяют в отдельную фазу компиляции, так как она оказывает существенное влияние на качество и эффективность результирующей программы.
Таблицы идентификаторов - это специальным образом организованные наборов данных, служащие для хранения информации об элементах исходной программы, которые затем используются для порождения текста результирующей программы. Таблицы идентификаторов в конкретной реализации может быть одна или несколько.
Предметной областью являются конструкции условных операторов if-else и ?: и простые типы языка Си.
Данные операторы имеют следующий вид:
4) условие ? оператор_1 : оператор_2;
Простые типы в языке Си объявляются так:
тип переменная_1, переменная_2, … переменная_n;
Рассмотрим элементы этих конструкций. Можно выделить следующие зарезервированные слова: if, else, ?, :.. После if находится выражение условие. Это выражение должно быть логического типа, т.е однозначно определяться как «истина» или «ложь». Если логическое выражение принимает значение «истина», то выполняется оператор оператор_1. Иначе, если есть зарезервированное слово else, то выполняется оператор оператор_2. В конструкции с оператором ?: перед зарезервированным словом ? находится выражение условие, которое также должно быть логического типа. Если это выражение принимает значение «истина», то выполняется оператор оператор_1. Иначе, если есть зарезервированное слово :, то выполняется оператор оператор_2. В описании переменных переменная_1, переменная_2, … переменная_n - список переменных в которых имена переменных разделены запятыми, тип - задает тип переменных из данного списка и является идентификатором типа.
1.2.3 Фаза компиляции «Лексический анализатор»
Лексический анализатор - это часть компилятора, которая читает исходную программу и выделяет в её тексте лексемы входного языка. На вход лексического анализатора поступает текст исходной программы, а выходная информация передаётся для дальнейшей обработки компилятором на этапе синтаксического анализа и разбора.
Под лексемой понимают структурную единицу языка, состоящую из элементарных символов языка и не содержащую в своём составе других структурных единиц языка.
Этапы работы лексического анализатора:
1. Первоначально в тексте исходной программы лексический анализатор выделяет последовательность символов, которая по его предположению должна быть словом в программе, т. е. лексемой. Это наиболее ответственная часть работы лексического анализатора. Она реализована с использование того факта, что слова в программе отделяются друг от друга пробелами.
2. После этого проводится идентификация лексемы. Она выполняется путём сравнения лексемы с эталонным значением. Сначала проверяется, не относится ли лексема к классу операторов. Если нет, то идёт проверка на то, не является ли лексема разделителем. Далее последовательно проверяется принадлежность лексемы к классам идентификаторы и ключевые слова.
3. После проведения успешной идентификации лексемы формируется её образ - дескрипторный код, он помещается в выходной поток лексического анализатора. В случае неуспешной идентификации формируются сообщения об ошибках в написании слов программы.
В рамках задания на курсовую работу представлены следующие классы лексем (Таблицы 1-4):
Табл. 3 Класс лексем «Идентификаторы»
Табл. 4 Класс лексем «Ключевые слова»:
Рассмотрим работу лексического анализатора (ЛА) на примере:
На вход ЛА подаются следующие входные данные:
ЛА читает текст исходной программы и выделяет в её тексте лексемы входного языка.
Таким образом, на выходе лексического анализатора мы имеем следующую цепочку:
Эта цепочка подается на вход синтаксического анализатора (СА).
1.2.4 Фаза компиляции «Синтаксический анализатор»
Синтаксический анализатор - это часть компилятора, которая отвечает за выявление основных синтаксических конструкций входного языка. В задачу синтаксического анализа входит: найти и выделить основные синтаксические конструкции в тексте входной программы, установить тип и проверить правильность каждой синтаксической конструкции и, наконец, представить синтаксические конструкции в виде, удобном для дальнейшей генерации текста результирующей программы.
В основе синтаксического анализатора лежит распознаватель текста входной программы на основе грамматики входного языка. Распознаватель даёт ответ на вопрос о том, принадлежит ли цепочка входных символов заданному языку.
Выходом лексического анализатора является таблица лексем (или цепочка лексем). Эта таблица подается на вход синтаксического анализатора, который исследует только один компонент каждой лексемы - её тип.
Синтаксический анализ (или разбор) - это процесс, в котором исследуется таблица лексем и устанавливается, удовлетворяет ли она структурным условиям, явно сформулированным в определении синтаксиса языка.
Согласно индивидуальному заданию рассмотрим LL-метод (предиктивный анализатор).
Логическим продолжением идеи, положенной в основу метода рекурсивного спуска, является предложение использовать для выбора одной из множества альтернатив не один, а несколько символов входной цепочки.
Существует класс грамматик, основанный именно на этом принципе -- выборе одной альтернативы из множества возможных на основе нескольких очередных символов в цепочке. Это так называемые LL(k)-грамматики. Грамматика обладает свойством LL(k), k > 0, если на каждом шаге вывода для однозначного выбора очередной альтернативы МП-автомату достаточно знать символ на верхушке стека и рассмотреть первые k символов от текущего положения считывающей головки во входной цепочке символов. Грамматика называется LL(k)-грамматикой, если она обладает свойством LL(k) для некоторого k > 0. Название «LL(k) » несет определенный смысл. Первая литера «L» происходит от слова «left» и означает, что входная цепочка символов читается в направлении слева направо. Вторая литера «L» также происходит от слова «left» и означает, что при работе распознавателя используется левосторонний вывод. Вместо «k» в названии класса грамматики стоит некоторое число, которое показывает, сколько символов надо рассмотреть, чтобы однозначно выбрать одну из множества альтернатив.
В совокупности все LL(k)-грамматики для всех k>0 образуют класс LL-грамматик.
Алгоритм разбора входных цепочек для LL(k)-грамматик носит название «k-предсказывающего алгоритма».
Требование k > 0, безусловно, является разумным -- для принятия решения о выборе той или иной альтернативы МП-автомату надо рассмотреть хотя бы один символ входной цепочки. Если представить себе LL-грамматику с k = 0, то в такой грамматике вывод совсем не будет зависеть от входной цепочки. В принципе такая грамматика возможна, но в ней будет всего одна единственная цепочка вывода. Поэтому практическое применение языка, заданного такого рода грамматикой, представляется весьма сомнительным.
Для LL(k)-грамматик известны следующие полезные свойства:
· всякая LL(k)-грамматика для любого k>0 является однозначной;
· существует алгоритм, позволяющий проверить, является ли заданная грамматика LL(k)-грамматикой для строго определенного числа k.
Есть, однако, неразрешимые проблемы для произвольных КС-грамматик:
· не существует алгоритма, который бы мог проверить, является ли заданная КС-грамматика LL(k)-грамматикой для некоторого произвольного числа k;
· не существует алгоритма, который бы мог преобразовать произвольную КС-грамматику к виду LL(k)- грамматики для некоторого k (или доказать, что преобразование невозможно).
Для LL(1)-грамматики, очевидно, для каждого нетерминального символа не может быть двух правил, начинающихся с одного и того же терминального символа. Поскольку все LL(k)-грамматики используют левосторонний нисходящий распознаватель, основанный на алгоритме с подбором альтернатив, очевидно, что они не могут допускать левую рекурсию. Поэтому никакая леворекурсивная грамматика не может быть LL-грамматикой. Следовательно, первым делом при попытке преобразовать грамматику к виду LL-грамматики необходимо, устранить в ней левую.
Класс LL-грамматик широк, но все же он недостаточен для того, чтобы покрыть все возможные синтаксические конструкции в языках программирования (к ним относим все детерминированные КС-языки). Известно, что существуют детерминированные КС-языки, которые не могут быть заданы LL(к)-грамматикой ни для каких k. Однако LL-грамматики удобны для использования, поскольку позволяют построить распознаватели с линейными характеристиками (линейной зависимостью требуемых для работы алгоритма распознавания вычислительных ресурсов от длины входной цепочки символов).
Для построения LL(1)-анализатора понадобятся специальные множества FIRST и FOLLOW .
Множество FIRST находится по правилам:
1) Если X - терминал, то FIRST(X) = {X};
2) Если имеется продукция вида Х > е, добавляем е к FIRST(X);
3) Если Х - нетерминал и имеется продукция Х > Y1Y2…Yk, то поместим а в FIRST(Х), если для некоторого i а FIRST(Yi) и е входит во все множества FIRST(Y1)… FIRST(Yi-1), т.е. Y1 --- Yi-1 > е. Если е имеется во всех FIRST(Yi), i=1...k, то добавляем е к FIRST(Х).
Множество FOLLOW находится по правилам:
1) Поместим $ в FOLLOW(S), где S - стартовый символ, а $ - правый ограничитель входного потока.
2) Если имеется продукция А>бВв, то все элементы множества FIRST(в), кроме , помещаются во множество FOLLOW(В).
3) Если имеется продукция А>бВ или А>бВв, где FIRST(в) содержит (т.е. в), то все элементы из множества FOLLOW(A) помещаются во множество FOLLOW(В).
Согласно правилам грамматики и построенным множествам FIRST и FOLLOW строим таблицу предиктивного анализа по существующему алгоритму:
1) Для каждой продукции грамматики А> выполняем шаги 2. и 3.
2) Для каждого терминала а из FIRST() добавляем А> в ячейку М[А,а].
3) Если в FIRST() входит , для каждого терминала b из FOLLOW(A) добавим А> в ячейку М[A,b]. Если входит в FIRST(), а $ - в FOLLOW(A), добавим А> в ячейку M[A,$].
4) Сделаем каждую неопределенную ячейку таблицы М указывающей на ошибку.
Проделаем данные построения для заданной грамматики.
TV=( `d', `t', `n', `i', `e', `f', `l', `r', `a', `;', `,', `{', `}', `(', `)', `<', `>', `=', `+', `-', `*', `/')
NV=(S, B, E, C, H, A, D, F, K, J, I, W, Z, M, N)
Запись правил грамматики G в форме Бэкуса-Наура:
<Старт>-><описание типа>{<тело программы>}
<тело программы>->$|<тело программы2>|i<операнды после if>
<описание типа>->$|t<переменные>;<описание типа>
< переменные >->d<список переменных>
< список переменных >->$|,< переменные >
< тело программы2>->t< переменные >;<описание типа>|{< тело программы >}|d=<выражение>;< тело программы >|<оператор ?:>
< операция else >->$|e< тело программы >
< операция :>->$|l< тело программы >
<выражение>-><идентификатор ><операция>
<операция>->$|< арифметические операции >< идентификатор >
<операнды после if>->(<идентификатор><операции отношения><идентификатор >)< тело программы ><операция else>|< идентификатор >< операции отношения >< идентификатор >< тело программы >< операция else >
< оператор ?:>->(< идентификатор >< операции отношения >< идентификатор >)f< тело программы ><операция :>|< идентификатор >< операции отношения >< идентификатор >f< тело программы >< операция :>
Запись правил грамматики в графическом виде:
В такой форме записи каждому нетерминальному символу грамматики соответствует диаграмма, построенная в виде направленного графа. Граф имеет следующие типы вершин:
· Точка входа (не обозначается на диаграмме, из нее начинается входная дуга графа)
· Нетерминальный символ (обозначается прямоугольником, в который вписано обозначение символа)
· Цепочка терминальных символов (обозначается овалом, кругом или прямоугольником с закругленными краями, внутрь которого вписана цепочка)
· Узловая точка (обозначается закрашенным кружком)
· Точка выхода (не обозначается на диаграмме, в нее входит выходная дуга графа)
Каждая диаграмма имеет только одну точку входа и одну точку выхода, но сколько угодно вершин других типов. Вершины соединяются между собой направленными дугами графа (линиями со стрелками).
Синтаксические диаграммы для нетерминальных символов грамматики G
Рис. 2-18. Синтаксические диаграммы грамматики G
Множества FIRST и FOLLOW строятся программно (рис. 19).
Рис. 20. Таблица предиктивного анализа
Т.к. в таблице нет ячеек, где бы было более одной записи, значит эта грамматика из класса LL-грамматик.
Для построения программного анализатора, воспользуемся алгоритмом разбора[1] строки по таблице предиктивного анализа (рис. 20).
Таблично-управляемый предсказывающий анализатор имеет входной буфер, таблицу анализа и выход. Входной буфер содержит распознаваемую строку, за которой следует $ - правый концевой маркер, признак конца строки. Магазин содержит последовательность символов грамматики с $ на дне. Вначале магазин содержит начальный символ грамматики на верхушке и $ на дне. Таблица анализа - это двумерный массив M[A,a], где A -нетерминал, и a - терминал или символ $.
Анализатор управляется программой, которая работает следующим образом. Она рассматривает X - символ на верхушке магазина и a - текущий входной символ. Эти два символа определяют действие анализатора.
1. Если X=a=$, анализатор останавливается и сообщает об успешном окончании разбора.
2. Если X=a<>$, анализатор удаляет X из магазина и продвигает указатель входа на следующий входной символ.
3. Если X - нетерминал, программа заглядывает в таблицу M[X,a]. По этому входу хранится либо правило для X, либо ошибка. Если, например, M[X,a]={X->UVW}, анализатор заменяет X на верхушке магазина на WVU {на верхушке U}. Будем считать, что анализатор в качестве выхода просто печатает использованные правила вывода. Если M[X,a]=error, анализатор обращается к подпрограмме анализа ошибок.
Пример разбора входной строки, принадлежащей заданной грамматике:
Выходом лексического анализатора является следующая цепочка лексем:
Эта цепочка подается на вход синтаксического анализатора (СА), далее часть процесса синтаксического разбора представлена на рисунке 21.
Выражение «Допуск» на выходной ленте свидетельствует о том, что исходная последовательность символов принадлежит заданной грамматике.
Листинг программной реализации c пояснениями представлен в Приложении 5.
1.2.5 Алгоритм построения дерева разбора
Деревом разбора грамматики G(VT,VN,P,S) называется дерево (граф), которое соответствует некоторой цепочке вывода и удовлетворяет следующим условиям:
Каждая вершина дерева обозначается символом грамматики A (VTuVN)
· корнем дерева является вершина, обозначенная целевым символом грамматики -- S;
· листьями дерева (концевыми вершинами) являются вершины, обозначенные терминальными символами грамматики или символом пустой цепочки;
· если некоторый узел дерева обозначен нетерминальным символом А VN а связанные с ним узлы -- символами b1,b2,bn; n>0,n>=i>0: то в грамматике G(VT,VN,P,S) существует правило А-> b1,b2,bn Р.
Из определения видно, что по структуре правил дерево вывода в указанном виде всегда можно построить только для грамматик двух типов (контекстно-свободных и регулярных). Для грамматик других типов дерево вывода в таком виде можно построить не всегда (либо же оно будет иметь несколько иной вид).
Часть дерева разбора для рассмотренной выше строки представлена ниже
компилятор алгоритм польский синтаксический
Рис.П2.3 Блок-схема алгоритма предикативного синтаксического анализатора
При возможности доступа к коду программа может использоваться для изучения основ работы компилятора и реализации этапов лексического и синтаксического анализов.
Программа не требует установки. Запуск программы осуществляется открытием файла с расширением .exe. Для работы с программой необходим файл “Grammatika.txt”.
3. Описание пользовательского интерфейса
Интерфейс программы представлен на рисунке 1. Несмотря на то, что последовательность действий, отражающих работу компилятора, изменить нельзя (к следующему этапу возможно перейти только в случае выполнения всех предыдущих этапов), для понимания таблиц и выводимых сообщений требуются начальные знания работы компилятора.
1)Сообщение при нажатии на кнопку «Провести лексический анализ», если до этого не был загружен пример
2). При возникновении ошибки во время лексического анализа
3). При успешном выполнении синтаксического анализа
4). При возникновении ошибки во время синтаксического анализа
Рис. П4.1 Граф переходов конечного автомата
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, Grids, ComCtrls, dxorgchr;
procedure SpeedButton1Click(Sender: TObject);
procedure GetLexicalOutput(rez,lex_type:string);
procedure FormCreate(Sender: TObject);
procedure SpeedButton6Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
procedure SpeedButton5Click(Sender: TObject);
procedure SpeedButton9Click(Sender: TObject);
procedure SpeedButton8Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
Rule: array ['A'..'Z',1..45] of string;
First: array['A'..'Z',1..45] of mnoj; //мн-во First
Follow: array['A'..'Z',1..45] of mnoj;//мн-во Follow
masx: array [1..19] of string=('i','e','f','l','r','a',';',',','(',')','{','}','<','>','=','+','-','*','/');
masp: array [1..19] of string=('3','3','3','3','6','6','-2','1','5','5','5','5','6','6','2','8','8','9','9');
procedure TForm1.GetLexicalOutput(rez,lex_type:string);
if rez[1]=' ' then Delete(rez,1,1);
if SG2.Cells[0,i]=rez then Symbol:=SG2.Cells[1,i];
then begin Edit2.Text:=EDit2.Text+'('+'40,'+IntTostr(j-1)+')';
Edit2.Text:=EDit2.Text+'('+'40,'+IntTostr(i-1)+')';
if SG3.Cells[0,i]=rez then Symbol:=rez;
then begin Edit2.Text:=EDit2.Text+'('+'20,'+IntTostr(j-1)+')';
Edit2.Text:=EDit2.Text+'('+'20,'+IntTostr(i-1)+')';
if SG4.Cells[0,i]='type' then Symbol:=SG4.Cells[1,i];
then begin Edit2.Text:=EDit2.Text+'('+'30,'+IntTostr(j-1)+')';
Edit2.Text:=EDit2.Text+'('+'30,'+IntTostr(i-1)+')';
if SG5.Cells[0,i]=rez then Symbol:=SG5.Cells[1,i];
then begin Edit2.Text:=EDit2.Text+'('+'10,'+IntTostr(j-1)+')';
Edit2.Text:=EDit2.Text+'('+'10,'+IntTostr(i-1)+')';
if SG4.Cells[0,i]='id' then Symbol:=SG4.Cells[1,i];
then begin Edit2.Text:=EDit2.Text+'('+'30,'+IntTostr(j-1)+')';
Edit2.Text:=EDit2.Text+'('+'30,'+IntTostr(i-1)+')';
if SG4.Cells[0,i]='number' then Symbol:=SG4.Cells[1,i] ;
then begin Edit2.Text:=EDit2.Text+'('+'30,'+IntTostr(j-1)+')';
Edit2.Text:=EDit2.Text+'('+'30,'+IntTostr(i-1)+')';
ShowMessage('Для данной лексемы ' +rez+ ' не определен код');
if (s[k-3]='>') or (s[k-3]='<') or (s[k-3]='r') or (s[k-3]='a') then
type TSost=(q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15
,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,
q30,q31,q32,q33,q34,q35,q36,q37,q38,q70);
st1,fff,OutStr,InStr,InStrClear: string; //Выходная строка
Psevdo:string; // Строка для псевдокода
vspom,porogd,rez,lex_type,qprev:string;
while counts<=form1.Memo1.Lines.Count-1 do
s:=form1.memo1.Lines.Strings[counts];
if ((s[i]=' ') and (s[i+1]=' ')) or (s[i]=#9 ) and (flagdel<>true) then
if (s[i]='/') and (s[i+1]='/') then
if (s[i]=' ') and (i=length(s)) then
if (s[i]='[') or (flagdel=true) then
for i:=0 to Form1.Memo4.Lines.Count do
if Form1.Memo4.Lines[i]='' then InStrclear:=InStrclear else
InStrclear:=InStrclear+' '+Form1.Memo4.Lines[i];
// InStrClear:=MakeClearStr(instr);
';',',','(',')','{','}': Sost:=q33; //разделители
'=','<','>','/','+','-','*','!': sost:=q31;
' ','a'..'d','f'..'z','0'..'9',';': Sost:=q34;
':','=','<','>',' ',';',',','/','+','-','*','!': Sost:=q36;
' ','=','<','>',';',',','/','+','-','*':Sost:=q38;//считаем строку цифр num
ShowMessage('Произошла ошибка. Неправильный символ "'+InStrClear[i]+'"');
rez:=Copy(InStrClear,i_old,(i-i_old));
Form1.GetLexicalOutput(rez,lex_type);
rez:=Copy(InStrClear,i_old,(i-i_old));
Form1.GetLexicalOutput(rez,lex_type);
rez:=Copy(InStrClear,i_old,(i-i_old));
Form1.GetLexicalOutput(rez,lex_type);
rez:=Copy(InStrClear,i_old,(i-i_old));
Form1.GetLexicalOutput(rez,lex_type);
rez:=Copy(InStrClear,i_old,(i-i_old));
Form1.GetLexicalOutput(rez,lex_type);
rez:=Copy(InStrClear,i_old,(i-i_old));
Form1.GetLexicalOutput(rez,lex_type);
procedure TForm1.SpeedButton1Click(Sender: TObject);
for j := 1 to SG1.RowCount+1 do begin
for j := 1 to SG6.RowCount+1 do begin
for j := 1 to SG7.RowCount+1 do begin
for j := 1 to SG8.RowCount+1 do begin
if memo1.Text='' then application.MessageBox('Введите пример!','Внимание!',mb_iconwarning);
procedure TForm1.FormCreate(Sender: TObject);
form1.StringGrid1.Cells[1,0]:='First';
form1.StringGrid1.Cells[2,0]:='Follow';
form1.StringGrid2.Cells[0,0]:='Стек';
form1.StringGrid2.Cells[1,0]:='Входная лента';
form1.StringGrid2.Cells[2,0]:='Выходная лента';
procedure TForm1.SpeedButton6Click(Sender: TObject);
if not(Fileexists(inttostr(a)+'.txt')) then a:=1;
step: byte;//номер прохода по алгоритму
for i:=0 to Form1.Memo2.Lines.Count-1 do
temp:=Rule[symbol,k];//одно правило для нетерминала symbol
if temp[1]<>'$' then First[symbol,step]:=First[symbol,step]+[temp[1]];
for i:=0 to Form1.Memo2.Lines.Count-1 do
for j:=0 to Form1.Memo2.Lines.Count-1 do
входят другие нетерминалы, то объединяем соответствующие множества}
if(symbol<>notterm[j])and(notterm[j] in First[symbol,step-1])then
First[symbol,k]:=First[symbol,k-1]+First[notterm[j],step-1];
First[symbol,step]:=First[symbol,k-1];
for i:=0 to Form1.Memo2.Lines.Count-1 do
if First[notterm[i],step]<>First[notterm[i],step-1] then
//если не равны то вернутся к шагу 2
for i:=0 to Form1.Memo2.Lines.Count-1 do
for j:=0 to Form1.Memo2.Lines.Count-1 do
if (notterm[j] in First[symbol,step-1])then
First[symbol,k]:=First[symbol,k-1]-[notterm[j]];
First[symbol,1]:=First[symbol,k-1];
Form1.StringGrid1.RowCount:=Form1.Memo2.Lines.Count+1;
for i:=0 to Form1.Memo2.Lines.Count-1 do
if s=#32 then temp:=temp+' '+''' ''' else temp:=temp+' '+s;
Form1.StringGrid1.Cells[0,i+1]:=notterm[i];
Form1.StringGrid1.Cells[1,i+1]:=temp;
label step1,step2,step3,step4,step5,step6,final;
Follow1,Follow2, HelpFollow:array['A'..'Z',1..60] of mnoj;
for i:=0 to Form1.Memo2.Lines.Count-1 do
{в Follow для нетерминала symbol добавляем все символы, стоящие за symbol в правилах
for num:=0 to Form1.Memo2.Lines.Count-1 do
temp:=Rule[notterm[num],n];//одно правило для нетерминала
if temp[j]=symbol then str:=copy(temp,j+1,length(temp)-j) ;
Follow[symbol,k]:=Follow[symbol,k-1]+[str[j]];
Follow[symbol,step]:=Follow[symbol,k-1];
{добавляем символ # во множество Follow стартового нетерминала}
Follow[notterm[0],step+1]:=Follow[notterm[0],step]+['#'];
Follow[notterm[0],step]:=Follow[notterm[0],step+1];
for i:=0 to Form1.Memo2.Lines.Count-1 do
Follow1[symbol,k-1]:=Follow[symbol,step];
for j:=0 to Form1.Memo2.Lines.Count-1 do
{если во множество Follow для рассматриваемого нетерминала symbol
входят другие нетерминалы, то объединяем его со множеством
if(symbol<>notterm[j])and(notterm[j] in Follow[symbol,step-1])then
Follow1[symbol,k]:=Follow1[symbol,k-1]+First[notterm[j],1];
Follow1[symbol,step]:=Follow1[symbol,k-1];
for i:=0 to Form1.Memo2.Lines.Count-1 do
Follow2[symbol,k-1]:=Follow1[symbol,step];
{если во множество Follow1 для рассматриваемого нетерминала symbol
входят другие нетерминалы и существует правило B->$, то объединяем его
со мноржеством Follow1 входящего нетерминала}
for j:=0 to Form1.Memo2.Lines.Count-1 do
if(symbol<>notterm[j])and(notterm[j] in Follow1[symbol,step])then
if Rule[notterm[j],n]='$' then bool:=true;
Follow2[symbol,k]:=Follow2[symbol,k-1]+Follow1[notterm[j],step];
Follow2[symbol,step]:=Follow2[symbol,k-1];
for i:=0 to Form1.Memo2.Lines.Count-1 do
HelpFollow[symbol,k-1]:=Follow2[symbol,step];
for j:=0 to Form1.Memo2.Lines.Count-1 do
{если для некоторого терминала B существует правило
B->aSymbol, то объединяем Follow2(Symbol) и Follow2(B)}
if (temp<>'')and(temp
Условные операторы и описание простых типов языка Си. Предиктивный анализатор курсовая работа. Программирование, компьютеры и кибернетика.
Дипломная работа по теме Управление трудовой адаптацией персонала ООО 'Дистрибьюторская компания 'Джаз'
Нравственные Ценности Сочинение Бедная Лиза
Историческое Сочинение Про Правление Дмитрия Донского
Реферат: Peer Pressure To Allegiance Essay Research Paper
Реферат: Оценка основных характеристик финансового инвестиционного проекта. Скачать бесплатно и без регистрации
Реферат: Война за независимость Индонезии
Сочинение На Тему Читать Это Классно
Курсовая работа по теме Организация управления в области земельного кадастрового учета
Контрольная Работа 1 По Физике Ответы
Реферат: Выбор электродвигателя и кинематический расчет привода
Реферат: Электронное строение атома Периодический закон
Бокс Реферат По Физкультуре Кратко
Бизнес Это Искусство Эссе
Лекция по теме Средняя Азия
Реферат по теме Новый тип потребителя
Осенние Каникулы Сочинение 2 Класс
Реферат: Lincoln Could He Have Preserved The Union
Реферат: Архитектура Средневековья
Реферат: The Lion The Witch And The Wardrobe 2
Дипломная работа по теме Анализ миграционных процессов, протекающих между Россией и Украиной в период с 1992 по 2022 год
Тип "Комахи" - Биология и естествознание реферат
Состояние услуг, как категории гражданского права на современном этапе - Государство и право курсовая работа
Аудит оплаты труда - Бухгалтерский учет и аудит курсовая работа


Report Page