4 Содержание Введение ............................................................................................................................................................... 5 1 Нормативные ссылки .............................................................................................................................. 6 2 Теоретический материал ....................................................................................................................... 7 2.1Синтаксически управляемая обработка данных ........................................................... 7 2.2 Автоматы с магазинной памятью(МП-автоматы)...................................................... 7 2.3 Некоторые обозначения для множеств цепочек.......................................................... 9 2.4 Транслирующие грамматики ..................................................................................................10 2.5 Синтаксически управляемый перевод ............................................................................13 2.6 Атрибутные транслирующие грамматики ....................................................................14 3 Описание транслируемого языка.................................................................................................17 4 Синтез транслятора................................................................................................................................18 4.1 Разбор реализации .........................................................................................................................18 4.2 Лексический блок ...........................................................................................................................21 4.3 Синтаксический блок ..................................................................................................................21 5 Описание программы ...........................................................................................................................30 5.1 Общие сведения ...............................................................................................................................30 4.2 Работа с программой ....................................................................................................................30 Заключение ......................................................................................................................................................32 Список используемой литературы ..................................................................................................33 Приложение А – Листинг ......................................................................................................................34 Приложение Б – Проверка в системе Antiplagiat.NET…………………..……………..45 4 Введение В последнее время круг задач, решаемых с помощью ЭВМ, значительно расширился, а сложность задач возросла. В этой ситуации все чаще используются языки высокого уровня, а также специализированные языки. Кроме того, всем известен тот факт, что ЭВМ понимает программы, состоящие только из внутренних команд процессора. В связи с этим возникает задача перевода программы с языка высокого уровня на язык, понятный процессору ЭВМ (трансляция). Разрабатывается один из вариантов программы, выполняющей такой перевод, – транслятор. Теория автоматов - раздел дискретной математики, изучающий абстрактные автоматы - вычислительные машины, представленные в виде математических моделей - и задачи, которые они могут решать. Теория автоматов наиболее тесно связана с теорией алгоритмов: автомат преобразует дискретную информацию по шагам в дискретные моменты времени и формирует результат по шагам заданного алгоритма. Теория автоматов является основой производства современных цифровых систем: электронных вычислительных машин, информационно-управляющих комплексов промышленного, оборонного и космического назначения. Цель курсовой работы - закрепить основы и углубить знания в области теории автоматов и формальных языков. 5 1 Нормативные ссылки ГОСТ 2.105-95. Общие требования к текстовым документам ГОСТ Р 50739-95. Государственный стандарт РФ. Средства вычислительной техники. Защита от несанкционированного доступа к информации. Общие технические требования ГОСТ 7.32-2001. СИБИД. Отчет о НИР. Структура и правила оформления ГОСТ 7.1-84 СИБИД. Библиографическое описание документа. Общие требования и правила составления» ГОСТ 7.80-2000 Библиографическая запись. Заголовок. Общие требования и правила составления ГОСТ 19.701-90 (ИСО 5807-85) ЕСПД. Схемы алгоритмов, программ, данных и систем. Обозначения условные и правила выполнения ГОСТ 34.601-90 Информационная технология. Комплекс стандартов на автоматизированные системы. Автоматизированные системы. Стадии создания. 6 2 Теоретический материал 2.1 Синтаксически управляемая обработка данных Теория конечных распознавателей является адекватной теоретической базой для разработки конечных процессоров лексических блоков только для достаточно простых случаев лексического анализа. При распознавании контекстно-свободных языков используются автоматы с магазинной памятью (МП-автоматы). В отличие от КР для МП-распознавателей оказывается сложнее задать процедуры расширения (выход из распознавания, вычисление значений и т.д.). Поэтому теория распознавания КС-языков сама по себе не обеспечивает адекватной теоретической базы для построения трансляторов. Необходимо ее дополнение (модификация), которое позволило бы решать все задачи трансляции. Это дополнение базируется на технике, в которой процесс обработки КС-языка определяется в терминах обработки каждого конкретного правила соответствующей грамматики. Обобщенно эта техника носит название - синтаксически управляемые методы. Эти методы базируются на понятиях "транслирующая грамматика" и "атрибутная грамматика". 2.2 Автоматы с магазинной памятью (МП - автоматы) Материал предыдущего раздела ответил на вопросы осуществления лексического анализа языков программирования высокого уровня и синтеза основных частей лексического блока (транслитератора, КР служебных слов, КР констант, распознавателя идентификаторов). Как было показано, ключевая роль при этом отводится конечным автоматам, используемых для распознавания цепочек. КА имеют небольшой объем памяти, однако возникает много задач, которые не могут быть решены при таком ограничении. Рассмотрим, например, задачу обработки скобок в арифметических 7 выражениях, которые могут иметь неограниченное количество левых скобок, и транслятор должен проверить, имеется ли такое же количество правых скобок. Для этого КА усиливается дополнительной магазинной памятью (МП) или памятью типа стека. Особенность МП состоит в том, что символы можно помещать в МП и удалять по одному, причем удаляемый символ - это всегда тот, который был помещен последним. Иногда этот принцип интерпретируют так: первый пришел - последний ушел (обслужен); последний пришел - первый ушел (LIFO-last in first out). На рисунке 1, а) в МП - четыре символа АВАС (причем С - поступил последний). Если один символ удалить (это будет С), то останется 3 - АВА (рисунок 4.1, б). На рисунке 1, в) удалены все символы и имеется только символ дна МП (или маркер дна). Он никогда не выталкивается из МП . С А В А а) б) А В А в) г) С Рисунок 1 - Стековая система МП Как и в КА, обработка входной цепочки осуществляется за ряд мелких шагов. На каждом шаге действия автомата конфигурация его памяти может изменяться за счет перехода в новое состояние, а также вталкивания символа в магазин или выталкивания из него. Однако в отличие от КА, МПА может обрабатывать один входной символ в течение нескольких шагов. На каждом шаге управляющее устройство автомата решает, пора ли закончить обработку текущего символа и получить, если это возможно, новый входной символ или продолжить обработку текущего символа на 8 следующем шаге. Каждый шаг обработки задается правилами, использующими информацию трех видов: 1) состояние автомата; 2) верхний символ магазина; 3) текущий входной символ. Это множество правил называется управляющим воздействием. На рисунке 1 состояние автомата - q, верхний символ - С, текущий входной символ - 0. В зависимости от управляющего воздействия автомат или прекращает обработку, или переходит в новое состояние. Переход состоит из трех операций: над магазином, над состоянием и над входом. Операции над магазином: - втолкнуть в магазин определенный магазинный символ; - вытолкнуть символ (верхний); - оставить магазин без изменений. Операции над состояниями: -перейти в новое состояние. Операции над входом: - перейти к следующему входному символу и сделать его текущим; - оставить данный входной символ текущим, т.е. держать его до следующего шага. Если текущим входным символом является концевой маркер, то МПА не должен требовать входного символа и не должен выталкивать символ из магазина, если это маркер дна. 2.3 Некоторые обозначения для множеств цепочек Рассмотрим три операции над множествами цепочек: - объединение, - конкатенация, 9 - итерация Клини (или просто итерация). ОБЪЕДИНЕНИЕ. Если Р и Q - множества цепочек, то объединение определяется выражениями PUQ или P+Q (в теории автоматов). Пример. {FOR, IF, THEN}+{DO, IF}={FOR, IF, THEN, DO} . КОНКАТЕНАЦИЯ. Это сцепление двух цепочек, определяемое выражением P*Q. Конкатенация множества R c самим собой, обозначается R*R {FOR, IF, THEN}. ИТЕРАЦИЯ КЛИНИ. Если А - множество символов алфавита, то А* множество всех цепочек, составленных из символов алфавита А, причем А* всегда содержит ε- пустую цепочку. Так {0, 1}* обозначает множество всех цепочек в алфавите {0, 1}. Часто используют вариант итерации А+, называемый позитивной итерацией А+ = АА*, т.е. А+ = А1+А2+А3+..... Применение этих операций к регулярным множества дает регулярные множества. Регулярное множество распознается КА. Можно дополнить данные операции так, что в результате получим нерегулярные множества из регулярных. Первый способ - в использовании переменных как показателей степеней при обозначении множеств {1n0n|n>0}=10, 111000, 11110000,… {1n0m|n>m} = 1110, 111100, и т.д. Второй способ - это обозначение операции обращения цепочки с помощью верхнего индекса r (abc)r=cba. 2.4 Транслирующие грамматики В качестве иллюстрирующего примера используется задача трансляции арифметических выражений. Общепринятой является инфиксная запись, которая отображается следующей грамматикой: 10 1. <E> → <E> + <T> | <T>; 2. <T> → <T> * <P> | <P> ; (1) 3. <P> → (<E>) | I , где <E> - начальный символ; I - произвольное целое число. Каждому выражению в инфиксной записи соответствует выражение в постфиксной польской записи, например, постфиксной записью для `a+bc` будет `abc*+`, а для `ab+c` - `ab*c+`. Постфиксная польская запись не содержит скобок, даже когда соответствующие инфиксные выражения заключаются в скобки, например: инфиксное выражение `(a+b)c` записывается как `ab+c*`, а выражение `a+b(c+d)*(e+f)` будет `abcd+*ef+*+`. Транслятор должен обеспечить перевод из одной формы записи в другую. Это осуществляется синтаксическим блоком транслятора. Задача состоит в том, чтобы по входной грамматике (грамматике входного языка) построить грамматику выходного языка (транслирующую грамматику). Для рассматриваемого примера это значит, что по КС-грамматике, описывающей инфиксные арифметические выражения (1), получить КСграмматику, которая переводила бы выражения в инфиксной записи в постфиксную форму. Принципиальным здесь является то, что алгоритм обработки (и соответствующее устройство) превращаются из распознающего в транслирующее (переводящее). Следовательно, если конечный распознаватель, построенный на основе КС-грамматики (1), должен был только распознать выражение `a+bc` и сделать его допустимым, то новая процедура обработки должна "перевести" выражение `a+b*c` в выражение `abc*+`. И самое главное, необходимо построить (создать) эту новую транслирующую грамматику, которая бы обеспечила необходимый перевод. Из рассмотренного примера видно, что при переводе можно выделить цепочки символов на входе (a+bc), построенные на основе 11 входной грамматики и цепочки символов на выходе (abc*+), построенные на основе транслирующей грамматики. Начиная с данного момента, будем отличать символы на выходе (в выходных цепочках) тем, что будем заключать их в фигурные скобки {a}{b}{c}{*}{+}. Иногда их называют символами действия. Оказывается, что входную КС- грамматику (1) легко преобразовать в транслирующую КС-грамматику, если правила дополнить символами действия (выходными символами) в требуемых местах. Эти места определяются последовательностью символов в постфиксных записях. Выражения (2) представляют транслирующую грамматику, соответствующую входной КС-грамматике (1): 1.<E> → <E> + <T> {+} 2.<E> → <T> 3.<T> → <T> * <P> {*} 4.<T> → <P> 5.<P> → (<E>) 6.<P> → I {I} (2) В правилах 1 и 3 символы действия {+} и {*} расположены после соответствующих операндов, а символ действия {I} в правиле 6 расположен сразу же за соответствующим входным терминальным символом I. В нашем примере терминальный символ I обозначает любой из символов `a, b, c`. Левый вывод входной цепочки `a+b*c` дает следующий порядок применения правил (2) - 2, 4, 6, 3, 4, 6, 6: < E > => < T > + < T >{+} => < P > + < T >{+} => a{a} + < T >{+}=> a{a} + < T > * < P >{*}{+} => a{a} + < P > * < P >{*}{+} => a{a} + b{b}*< P> {*}{+} => a{a} + b{b} * c{c}{*}{+} . Если в конечном результате вывода выделить только входные символы, то получим распознаваемую входную цепочку `a+b*c`. При выделении символов действия (выходных) получим перевод (трансляцию) входной цепочки в выходную `abc*+`={a}{b}{c}{*}{+}. 12 Приведенные выше рассуждения сформулируем в виде математической модели с помощью следующих операций. Транслирующей грамматикой или грамматикой перевода называется КС-грамматика, множество терминальных символов которой разбито на множество входных символов и множество символов действия. Цепочки языка, определяемого транслирующей грамматикой, называются последовательностями актов. Подразумевается, что каждый символ действия представляет процедуру, которая осуществляет выдачу символа, заключенного в скобки. Иногда такая грамматика называется грамматикой, транслирующей в цепочки или грамматикой цепочечного перевода. 2.5 Синтаксически управляемый перевод Математически перевод рассматривается как множество пар, где первый элемент принадлежит множеству объектов, которые надо перевести, а второй элемент - множеству объектов, которые являются результатом перевода. Напомним, что первый элемент - это цепочка входного языка, а второй элемент - последовательность, являющаяся результатом перевода входной цепочки. Когда эти пары получают при помощи некоторой грамматики, перевод называют синтаксически управляемым переводом. Как ранее было определено, последовательность актов транслирующей грамматики включает входные символы и символы действия. Входная последовательность (входная цепочка) может быть получена из последовательности актов путем вычеркивания всех входных символов. Считают, что входная последовательность образует пару с последовательностью действий. Множество всех пар называется переводом, определяемым данной транслирующей грамматикой. В рассмотренном примере инфиксная и постфиксная записи арифметических выражений являются множеством пар 13 перевода. Акцентируем внимание на определении грамматик. Входная грамматика - определяет входной язык (в нашем примере формирует инфиксные выражения). Транслирующая грамматика может быть получена из входной грамматики путем добавления в последнюю символов действия. Аналогично входную грамматику получают из транслирующей методом вычеркивания из последней всех символов действия. Можно определить и выходную грамматику (грамматику действий), если из транслирующей грамматики вычеркнуть все терминальные входные символы. Таким образом, транслирующую грамматику можно рассматривать как переводящую с одного КС-языка (входного) на другой КС-язык (выходной). 2.6 Атрибутные транслирующие грамматики При переводе цепочек символов не учитывалось, что символ может состоять из двух частей (двух характеристик): класса и значения. Транслирующие грамматики учитывают только класс символов. Расширим транслирующие грамматики, включив в перевод и значение символа. Такая грамматика называется атрибутной. Атрибутная транслирующая грамматика (АТГ) - это транслирующая грамматика, к которой добавляются следующие определения: 1.Каждый входной символ, символ действия или нетерминальный символ имеет конечное множество атрибутов, и каждый атрибут имеет (возможно, бесконечное) множество допустимых значений. 2.Все атрибуты нетерминальных символов и символов действия делятся на наследуемые и синтезируемые. 3.Заданы правила вычисления атрибутов. В АТГ грамматике атрибуты записываются в виде индексов ( по одному индексу на каждый атрибут), например: <X>p,q,r → <Y>y,u <Z>v,w , где атрибуты q, r - синтезируемые, p, y, v 14 наследуемые. Первое правило вычисляет синтезируемый атрибут q. Второе правило вычисляет два атрибута, причем один из них синтезируемый - r, а второй - наследуемый - v, при этом оба атрибута вычисляются одинаково . Третье правило определяет наследуемый атрибут y. В атрибутной грамматике значения символов сопоставляются со всеми вершинами дерева вывода как терминальными, так и нетерминальными. Отношения между входными и выходными значениями выражаются по принципу "от правила к правилу". При этом значения находятся в вершинах дерева. Допустим, лексический блок задает входное множество {(, ), +, *, с}, где `с` - лексема константы; ее значением является значение константы, построенное лексическим блоком. Рассмотрим теперь проблему проектирования синтаксического блока, который допускает арифметические выражения, сформированные из символов данного входного множества, и выдает численные значения этих выражений. Соответствие между компонентами входов и выходов, представляющих их классы, можно выразить следующей грамматикой, транслирующей в цепочки: 1. <S> → <E> {ответ}; 2. <E> → <E> + <T>; 3. <E> → <T>; 4. <T> → <T> + <P>; 5. <T> → <P>; 6. <P> → (<E>); 7. <P> → C . Значение выходного символа ОТВЕТ должно быть числом. Требуемое отношение между значениями входных лексем и значением выходной лексемы ОТВЕТ можно выразить словами "значение лексемы ОТВЕТ - это числовое значение входного выражения" (рисунок 4.10). Найдем математический способ выражения рассмотренного отношения. 15 Рассмотрим конкретную цепочку (С3 + С9)*(С2 + С41), где значения входных лексем, выданных ЛБ, указаны индексами. Определим, как получить значения для всех частей дерева. С этой целью сопоставим каждому правилу грамматики (продукции) правило вычисления значения вершины, соответствующей нетерминалу левой части продукции, по данным значениям ее прямых потомков, соответствующих символам правой части продукций. Правила вычисления отражают "значение" или "смысл" продукций. Однако технику сопоставления правил продукциям можно использовать для определения значений, которые не обязательно отражают явное значение входной цепочки, например, с помощью правил для продукций можно с каждой вершиной дерева связать элемент некоторой таблицы. Продукции вместе с правилами вычисления значений являются атрибутными правилами и образуют атрибутную грамматику. В примере значение атрибута каждого нетерминала определяется символами, рассмотренными в дереве вывода под этим нетерминалом. Если синтезируемые атрибуты вычисляются по правилу: -атрибуты левых частей правил определяются атрибутами правых частей; то наследуемые атрибуты вычисляются по правилу: -атрибуты нетерминала правой части правила определяются символами правой части и атрибутами нетерминала левой части этого правила. Такое "восходящее" вычисление выражается в том, что правила вычисления атрибутов нетерминалов, ассоциированные с продукциями, указывают, как вычислить атрибуты левой части продукции по данным атрибутам символов правой части. Замечание по поводу обозначений. Атрибут символа действий пишется вне скобок {X}q, но в нашем случае символ действия образован заключением в скобки выходного символа. В этом случае атрибут может быть внутри скобок {ОТВЕТ 516}, т.е. он должен быть выдан как часть заключенного в скобки выходного символа. 16 3 Описание транслируемого языка За основу языка высокого уровня транслятора был взят язык программирования qBasic. Он был упрощен, а часть правил изменена или отсутствует. Отличия заданного языка от qBasic: 1) Необходимы разделы PROGRAM и VAR. 2) Определены только несколько типов. 3) Идентификатор может состоять из сочетания букв и цифр. 4) Из операторов описаны: оператор присваивания ‘:=’; операторы ввода-вывода WRITELN; оператор цикла FOR; выражения отношения<, >, =; арифметические операции +, -, *, /. 5) Операторы отделяются друг от друга “;”. 17 4 Синтез транслятора 4.1 Разбор реализации Транслятор – это программа, которая допускает в качестве входа программу на исходном языке высокого уровня, а в качестве выхода выдает другую версию этой программы, написанную на другом языке, который называется объектным языком. Объектный язык обычно является машинным языком некоторой вычислительной машины, причем программу в этом случае можно сразу же выполнять. Транслятор можно представить как сложный вычислительный процесс, включающий отдельные более простые блоки. На рисунке 2 представлена упрощенная схема транслятора, который содержит: - лексический блок; - синтаксический блок; - генератор кода; - таблицы. Лексический блок Синтаксический блок Генератор кода Таблицы Рисунок 2 – Упрощенная схема транслятора Лексический блок. Входом транслятора служит набор двоичных символов (цепочка). Лексический блок предназначен для того, чтобы разбивать цепочку символов на слова, из которых она состоит. Лексема if принадлежит классу "if" (служебное слово) и 18 информирования о ее значении не требуется. Лексический блок устанавливает, что цепочка представляет слово if, за которым следует левая скобка ( переменная b1, знак >, число 9, переменная x , знак присвоения =, число 5 и точка с запятой. Таким образом, 12 символов преобразуются в 9 новых единиц. Так b1 принадлежит классу "переменная" и имеет значение, которое служит указателем на элемент таблицы имен для b1. Этот указатель на таблицу имен фактически является внутренним именем переменной b1. Лексема 9 принадлежит классу "константа" и имеет в качестве значения набор битов, изображающих число 9. Знак равенства относится к классу "знак отношения", а его значение – указывает, какое именно отношение. Лексема while принадлежит классу "while" (служебное слово) и информирования о ее значении не требуется. Если рассматривать таблицу имен как словарь, то лексическая обработка аналогична группировке букв в слова и нахождению этих слов в словаре. Синтаксический блок - переводит последовательность лексем, построенную лексическим блоком, в другую последовательность, которая более непосредственно отражает порядок, в котором должны выполняться операции в программе. Например, если в программе написано a+b∙c - это значит, что числа, представляемые идентификаторами b, c, будут перемножены и к результату будет прибавлено число, представляемое идентификатором а. Указанные выражения можно перевести так: УМНОЖИТЬ (b, c, r1), СЛОЖИТЬ (a, r1, r2), где первое выражение идентифицируется как "умножить b на с и запомнить результат по адресу r1", а второе - "сложить а и значение по адресу r1 и запомнить результат по адресу r2". Таким образом, пять лексем, выданных лексическим блоком, преобразуются в две новые 19 единицы, которые называются атомами и образуют выход синтаксического блока. Преимуществом здесь является то, что последовательность атомов отражает порядок, в котором должны выполняться действия. Предположим, как и раньше, что каждый атом состоит из класса и значения. Тогда атом УМНОЖИТЬ (b, c, r1) принадлежит классу "УМНОЖИТЬ" и имеет значение, состоящее из 3-х указателей на элемент таблицы: для b, c и r1 соответственно. Внутри транслятора атом будет представлен целым числом, обозначающим "УМНОЖИТЬ" и тремя указателями, обозначающими его значение. Выполняя необходимые преобразования, синтаксический блок (СБ) должен учитывать структуру языка так же, как и при переводе с естественных языков учитываются их грамматические особенности. Генератор кода - блок "развертывает" атомы, построенные СБ, в последовательность выполняют команд соответствующие вычислительной действия. машины, Точный которые характер этого развертывания зависит от многих признаков. Например, от типа операторов (b, c) – с фиксированной или плавающей точкой, от используемых регистров машины и др. Та часть работы транслятора, которая связана со смысловым значением лексем, называется семантической обработкой. Семантика идентификатора может включать его тип, а в случае, если это массив, то его размерность. Один из видов семантической обработки включает занесение в таблицу имен свойств отдельных идентификаторов по мере их выявления. Другой вид включает действия, зависящие от типа данных. В некоторых трансляторах определенные семантические действия выполняются отдельным семантическим блоком, помещаемым между синтаксическим блоком и генератором кода. За основу языка высокого уровня транслятора был взят язык программирования, разработанный в среде Microsoft Visual Studio 2017, С #. 20 Произведем реализацию языка qBasic с арифметическими и логическими операциями на основе C# 4.2 Лексический блок Входом транслятора служит набор двоичных символов (цепочка). Лексический блок предназначен для того, чтобы разбивать цепочку символов на слова, из которых она состоит. В общем виде работа лексического блока выглядит следующим образом: 1. Входная строка анализируется посимвольно до разделителя, которым могут быть или символ пробел, или символ конца строки. 2. Если лексема распознана (является ключевым словом, или специальным символом), то она заносится в таблицу лексем, а иначе, мы предполагаем, что данная лексема является идентификатором. 3. Если лексема не является идентификатором, то выдается 4.3 Синтаксический блок Этот блок лексическим переводит блоком, в последовательность другую лексем, последовательность, построенную которая более непосредственно отражает порядок, в котором должны выполняться операции в программе. Для построения управляющей таблицы МПА необходимо нахождение множества ВЫБОР. Исходной для множества выбора является следующая грамматика: 1. [Программа] → [Заголов][ОписПер][Тело] 2. [Заголов] → program[Имя][ТочЗап] 3. [Заголов] → $ 4. [Имя] → ID 5. [ТочЗап] → ; 6. [Точка] →. 21 7.[ОписПер] → var[СписПер][ДопОпис] 8.[ОписПер] → $ 9.[СписПер] → [Перем]:[ТипПерем][ТочЗап] 10.[Перем] → [Имя][ДопПерем] 11.[ДопПерем] → $ 12.[ДопПерем] →,[Имя][ДопПерем] 13.[ДопОпис] → $ 14.[ДопОпис] → [Перем]:[ТипПерем][ТочЗап][ДопОпис] 15. [ТипПерем] → boolean 16. [Тело] → begin[Опер-ры]end[Точка] 17. [Опер-ры] → $ 18. [Опер-ры] → begin[Опер-ры]end[ТочЗап][Опер-ры] 19. [Опер-ры] → writeln[ДопWriteln][ТочЗап][Опер-ры] 20. [ДопWriteln] → [ЛевСкоб][Имя][Список][ПрСкоб] 21. [ДопWriteln] → $ 22. [ЛевСкоб] → ( 23. [ПрСкоб] →) 24. [Список] → $ 25. [Список] →,[Имя][Список] 26. [Опер-ры] → readln[ДопReadln][ТочЗап][Опер-ры] 27. [ДопReadln] → [ЛевСкоб][Имя][Список][ПрСкоб] 28. [ДопReadln] → $ 29. [Опер-ры] → for[Имя]:[Равно][Имя][TD][Имя]do[Опер-ры] 30. [TD] → to 31. [TD] → downto 32. [Опер-ры] → [Имя]:[Равно][Выражение][ТочЗап][Опер-ры] 33. [Знак] → + 34. [Знак] → 35. [Знак] → / 36. [Знак] → * 22 ШАГ 1Процедуры определяет аннулирующие нетерминалы и правила . 3. [Заголов] → $ 8. [ОписПер] → $ 11.[ДопПерем] → $ 9. 13.[ДопОпис] → $ 18. [Опер-ры] → $ 22. [ДопWriteln] → $ 25. [Список] → $ 29. [ДопReadln] → $ 39. [ЛогВыр] → $ 54. [Далее] → $ ШАГ 2 Процедуры состоит в нахождении отношения, называемого НАЧИНАЕТСЯ ПРЯМО С (НПС). Эти отношения определяются на множестве символов грамматики и означают, что если, применив к нетерминалу <A> точно одно правило и, возможно, заменив в нем некоторые аннулирующие нетерминалы на $, можно получить цепочку, начинающуюся, например с <B>. В этом случае пишут <A>НПС<B>. На рисунке 2 показан фрагмент полученных отношений. ШАГ 3 Процедуры - это вычисление отношения НАЧИНАЕТСЯ С (НС). В общем случае матрица отношений НС определяется рефлексивнотранзитивным замыканием матрицы НПС. Признак рефлексивности определяется тем, что любой символ всегда начинается с самого себя . 23 1) для каждого единичного элемента aij исходной матрицы в строку i дописать единичные элементы из строки j; п.1 повторять сверху вниз и слева направо для всех элементов матрицы. На рисунке 3 показан фрагмент полученного отношения. Рисунок 3 – Таблица отношений НПС ШАГ 4 вычисляет множество ПЕРВЫЙ. Для каждой строки матрицы отношения НС отмеченные столбцы, соответствующие терминальным символам, указывают терминалы, составляющие множество ПЕРВЫЙ для символа, которым помечена данная строка. Так, в нашем примере: ПЕРВЫЙ ([Программа])={ program, var, begin} ПЕРВЫЙ ([Заголов])={ program } ПЕРВЫЙ ([Имя])={ ID } и.т.д. 24 ШАГ 5 - вычисление множества ПЕРВЫЙ для правой части каждого правила. Имея информацию, полученную на шаге 4, эти вычисления проделать очень просто. ПЕРВЫЙ (1)={ program, var, begin} ПЕРВЫЙ (2)={ program } ПЕРВЫЙ (3)={ID} и.т.д. Рисунок 4 – Таблица множества Первый ШАГ 6 - это построение отношения, нызываемого ПРЯМО ПЕРЕД(ПП): Эти отношения определяются следующим образом: мы пишем А ПП В тогда и только тогда, когда существуют правила вида: <D> → <A><B> , <D> → <A>β<B> , где <А>, <В> - НТ символы, β - аннулирующая цепочка. На рисунке 4 показан фрагмент полученного отношения. 25 ШАГ 7 - это построение отношения ПРЯМО-НА-КОНЦЕ (ПНК). Отношение определяется следующим образом: если <А> и <В> символы грамматики, то <А> ПНК <В> тогда и только тогда, когда есть правила вида <B> →α<A>, <B> →α<A>β, где β - аннулирующая цепочка, α - произвольная цепочка. Это отношение является инверсией отношения НПС, если правую часть правила рассматривать "справа - налево". На рисунке 5 показан фрагмент полученного отношения. Рисунок 5 – Таблица отношения ПП 26 Рисунок 6 – Таблица отношения ПНК ШАГ 8 - построение отношения НА-КОНЦЕ (НК). Отношение НК - это рефлексивно-транзитивное замыкание отношения ПНК. На рисунке 6 показан фрагмент полученных отношений. 27 Рисунок 7 – Таблица отношений НК ШАГ 9 - это вычисление отношения, называемого ПЕРЕД (П): Мы пишем <А> П <В> тогда и только тогда, когда из начального символа можно вывести цепочку, в которой за вхождением <А> сразу же следует вхождение <В>. Можно записать без вывода, что отношение П является произведением отношений НК, ПП и НС. Это отношение также соответствует тем символам, которые находятся НА КОНЦЕ начального нетерминала для всех выводимых из него цепочек. ШАГ 10 заключается в расширении отношение ПЕРЕД (П+) за счет включения в него концевого маркера (последний столбец) Это отношение соответствует тем терминальным символам, которые находятся НА КОНЦЕ начального нетерминала для всех выводимых из него цепочек (первый столбец матрицы НК). На рисунке 7 показан фрагмент полученных отношений для шагов 9 и 10. 28 Рисунок 8 – Таблица отношений Перед ШАГ 11 аннулирующего терминальные - это вычисление множества СЛЕД для каждого нетерминала. Множество СЛЕД будет содержать все символы, для которых аннулирующие нетерминалы расположены ПЕРЕД. ШАГ 12 - вычисление множеств ВЫБОР, которые можно получить из уже вычисленных значений множеств ПЕРВЫЙ и СЛЕД. На рисунке 8 показан фрагмент множества ВЫБОР, из которого видно, что множества выбора правил, имеющих одинаковые левые части, не пересекаются. Грамматика, порождающая рассматриваемый язык, является LL(1)-грамматикой и для неё можно построить МП-распознаватель. Управляющая таблица МПА представлена на рисунке 9, а правила его работы на рисунке 10. 29 5 Описание программы 5.1 Общие сведения Весь программный продукт хранится в виде одного исполняемого файл “курсач.exe” В программу встроен редактор для написания и редактирования программ. Для обеспечения нормального функционирования программы необходим .NetFramework 4.5.Программа создана с учетом современных требований к интерфейсу и интерактивным программным продуктам. 5.2 Работа с программой Программа синтаксического анализатора представляет собой окно с полем редактирования текста программы и полем порядка выполнения обработки (рисунок 11). С помощью кнопки «Go» можно проверить код на ошибки. Рисунок 9 – Окно программы 30 Для демонстрации работы программы сделаем ошибку в коде в левом поле программы. Рисунок 10 – Результат работы программы с ошибкой 31 Заключение В данной работе были описаны основные принципы работы автоматов. При этом автоматы были разделены на абстрактные и автоматы, применяемые в микросхемотехнике. Так же теория автоматов тесно связана с теорией алгоритмов. В основе работы лежала синтаксически управляемая обработка языков с использованием языка C# и qBasic. Теория конечных распознавателей̆ является адекватной̆ теоретической̆ базой для разработки конечных процессоров лексических блоков только для достаточно простых случаев лексического анализа. При распознавании контекстно-свободных языков используются автоматы с магазинной памятью (МП-автоматы). В отличие от КР для МП-распознавателей оказывается сложнее задать процедуры расширения (выход из распознавания, вычисление значений и т.д.). Поэтому теория распознавания КС-языков сама по себе не обеспечивает адекватной теоретической базы для построения трансляторов. Необходимо ее дополнение (модификация), которое позволило бы решать все задачи трансляции. На основе изученного материала был сделан вывод, что исследование абстрактных автоматов в результате привели к активному развитию вычислительной техники и микросхемотехники соответственно. 32 Список используемой литературы 1. Ключко В.И., Власенко А.В., Кушнир Н.В., Кушнир А.В. Теория автоматов и формальных языков: учеб. пособие / Кубан. гос. технол. ун-т.Краснодар: Изд. ФГБОУ ВПО «КубГТУ», 2014.- 148 с. 2. Теория автоматов и формальных языков: метод. указания по выполнению курсовой работы для студентов всех форм обучения по направлениям: 230100.62 Информатика и вычислительная техника / Сост.: В.И. Ключко, А.В. Власенко, Н.В. Кушнир; Кубан. гос. технол. ун-т. Каф. информационных систем и программирования. – Краснодар: Изд. КубГТУ, 2014. – 27 с. 3. Теория автоматов и формальных языков: метод. указания по выполнению лабораторных работ для студентов всех форм обучения и МИППС направления 230100.62 Информатика и вычислительная техника / Сост.: . Ключко В.И., Власенко А.В., Кушнир Н.В., Кушнир А.В; Кубан. гос. технол. ун-т. Каф. информационных систем и программирования.– Краснодар: Изд. КубГТУ, 2014. – 43 с. Дополнительная 4.Введение в программирование на языке Visual C# : учеб. пособие /С.Р. Гуриков. — М. : ФОРУМ : ИНФРА-М, 2017. — 447 с. — (Высшее образование: Бакалавриат).http://znanium.com/bookread2.php?book=404441 (по паролю). 5. Преобразования грамматик [Электронный ресурс]. https://studall.org/all3-15882.html (свободный доступ). 33 Приложение А – Листинг using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Курсач; namespace Курсач { class Sintacsis { public Sintacsis(Queue<string> qu) { this.qu = qu; } private string lexicalClass; private Queue<string> qu; MainWindow df = new MainWindow(); string GetLC() { if (qu.Count != 0) { if (qu.Peek() == "12") { MainWindow.show.Add("Прочитано Лексема"); } else { MainWindow.show.Add("Прочитано " + qu.Peek()); } return qu.Dequeue(); } return ""; } public void Analiz() { lexicalClass = GetLC(); AllProgram(); } void nextStep(string lex) { if (lexicalClass == lex) 34 lexicalClass = GetLC(); else throw new SintaxError(string.Format("Неверная лексема '{0}', ожидается '{1}'.", lexicalClass, lex)); } void nextStep(int lex) { if (int.Parse(lexicalClass) == lex) lexicalClass = GetLC(); else throw new SintaxError(string.Format("Неверная лексема '{0}', ожидается '{1}'.", lexicalClass, lex)); } #region Title void AllProgram() { switch (lexicalClass) { case "PROGRAM": { lexicalClass = GetLC(); Name(); nextStep(";"); DescriptionOfValues(); DescriptionOfLabels(); Body(); break; } default: throw new SintaxError(string.Format("Неверная лексема '{0}'", lexicalClass)); } } void Name() { lexicalClass = GetLC(); } void DescriptionOfValues() { switch (lexicalClass) { case"VAR": { lexicalClass = GetLC(); ListOfValues(); 35 ExtraDescription(); break; } default: throw new SintaxError(string.Format("Неверная лексема '{0}'", lexicalClass)); } } void DescriptionOfLabels() { if (lexicalClass == "LABEL") { lexicalClass = GetLC(); Value(); nextStep(";"); } } void ListOfValues() { Value(); nextStep(":"); ValueType(); nextStep(";"); } void ExtraDescription() { if (lexicalClass == "BEGIN" || lexicalClass == "LABEL") { } else { Value(); nextStep(":"); ValueType(); nextStep(";"); ExtraDescription(); } } void Value() { Name(); ExtraValue(); } void ValueType() { switch (lexicalClass) 36 { case "BOOLEAN": { lexicalClass = GetLC(); break; } default: throw new SintaxError(string.Format("Неверная лексема '{0}'", lexicalClass)); } } void ExtraValue() { if (lexicalClass == ",") { lexicalClass = GetLC(); Name(); ExtraValue(); } } #endregion #region Body void Body() { if (lexicalClass == "BEGIN") { lexicalClass = GetLC(); Operators(); lexicalClass = GetLC(); nextStep("."); } else throw new SintaxError(string.Format("Неверная лексема '{0}'", lexicalClass)); } void Operators() { switch (lexicalClass) { case "BEGIN": { lexicalClass = GetLC(); Operators(); nextStep("END"); nextStep(";"); Operators(); break; 37 } case "WRITELN": case "WRITE": { lexicalClass = GetLC(); ExtraWriteLn(); nextStep(";"); Operators(); break; } case "READLN": case "READ": { lexicalClass = GetLC(); ExtraReadLn(); nextStep(";"); Operators(); break; } case "IF": { lexicalClass = GetLC(); Condition(); nextStep("THEN"); Operators(); ExtraElse(); break; } case "GOTO": { lexicalClass = GetLC(); Name(); nextStep(";"); break; } case "END": { break; } case "12": { Name(); nextStep(":"); nextStep("="); Expression(); nextStep(";"); Operators(); 38 break; } } } void ExtraElse() { if (lexicalClass == "ELSE") { lexicalClass = GetLC(); Operators(); } } void Expression() { switch (lexicalClass) { case "12": { lexicalClass = GetLC(); if (lexicalClass == "XOR" || lexicalClass == "AND" || lexicalClass == "OR") { LogicExpression(); } else { if (lexicalClass == "+" || lexicalClass == "-" || lexicalClass == "*" || lexicalClass == "/") { ArithmeticExpression(); Name(); ExtraArithmeticExpression(); //nextStep(";"); } } break; } case "TRUE": { lexicalClass = GetLC(); break; } case "FALSE": 39 { lexicalClass = GetLC(); break; } case "NOT": { lexicalClass = GetLC(); Name(); break; } default: { lexicalClass = GetLC(); break; } } } void LogicExpression() { LogicOperator(); Name(); } void LogicOperator() { switch (lexicalClass) { case "XOR": { lexicalClass = GetLC(); break; } case "OR": { lexicalClass = GetLC(); break; } case "AND": 40 { lexicalClass = GetLC(); break; } } } void ArithmeticExpression() { switch (lexicalClass) { case "+": { lexicalClass = GetLC(); break; } case "-": { lexicalClass = GetLC(); break; } case "*": { lexicalClass = GetLC(); break; } case "/": { lexicalClass = GetLC(); break; } default: Console.WriteLine("Error"); break; } } void ExtraArithmeticExpression() { if (lexicalClass == "+" || lexicalClass == "-" || lexicalClass == "*" || lexicalClass == "/") { 41 lexicalClass = GetLC(); nextStep("12"); ExtraArithmeticExpression(); } } void Condition() { Name(); Comparison(); Name(); } void Comparison() { switch (lexicalClass) { case "=": { lexicalClass = GetLC(); break; } case ">": { lexicalClass = GetLC(); break; } case "<": { lexicalClass = GetLC(); break; } default: { Console.WriteLine("ERROR"); break; } } } void ExtraWriteLn() { 42 if (lexicalClass == "(") { lexicalClass = GetLC(); Name(); List(); nextStep(")"); } } void List() { if (lexicalClass == ",") { lexicalClass = GetLC(); Name(); List(); } } void ExtraReadLn() { if (lexicalClass == "(") { lexicalClass = GetLC(); Name(); List(); nextStep(")"); } } } #endregion class SintaxError : Exception { private string ErInfo { get; set; } public SintaxError(string s) { if (s.Contains("12")) { 43 ErInfo = "Неверная переменная (значение)"; } else { ErInfo = s; } } public override string Message => ErInfo; } } 44 Приложение Б – Проверка в системе AntiPlagiat.NET 45