Инфоурок Информатика СтатьиЦепочки символов. Операции над цепочками символов

Цепочки символов. Операции над цепочками символов

Скачать материал

Цепочки символов. Операции над цепочками символов

 

Цепочкой символов (или строкой) называют произвольную последовательность символов, записанных один за другим. Понятие символа (или буквы) является базовым в теории формальных языков и не нуждается в определении.

Далее цепочки символов будем обозначать греческими буквами: α, β, γ.

Итак, цепочка — это последовательность, в которую могут входить любые допустимые символы.

Для цепочки символов важен состав и количество символов в ней, а также порядок символов в цепочке. Один и тот же символ может произвольное число раз входить в цепочку. Поэтому цепочки «а» и «аа»,  а также «аб» и «ба» — это различные цепочки символов. Цепочки символов α и β равны (совпадают), α = β, если они имеют один и тот же состав символов, одно и то же их количество и одинаковый порядок следования символов в цепочке.

Количество символов в цепочке называют длиной цепочки. Длина цепочки символов α обозначается как | α |. Очевидно, что если α = β, то и | α | = | β |.

Основной операцией над цепочками символов является операция конкатенации, объединения или сложения) цепочек.

Конкатенация (сложение, объединение) двух цепочек символов - это дописывание второй цепочки в конец первой. Конкатенация цепочек α и β обозначатся как αβ. Выполнить конкатенацию цепочек просто: например, если α = «аб» а β = «вг», то α β = «абвг».

Так как в цепочке важен порядок символов, то очевидно, что операция конкатенации не обладает свойством коммутативности, то есть в общем случае $ α и β : такие, что αβ ¹ βα. Также очевидно, что конкатенация обладает свойством ассоциативности, то есть (αβ)γ = α(βγ).

Можно выделить еще две операции над цепочками.

Обращение цепочки - это запись символов цепочки в обратном порядке. Обращение цепочки α обозначается как αR. Если α - «абвг», то α R - «гвба». Для операции обращения справедливо следующее равенство " α,β: (αβ)R - βRαR.

Итерация (повторение) цепочки n раз, где nÎN, n > 0 - это конкатенация цепочки самой с собой n раз. Итерация цепочки α n раз обозначается как αn. Для операции повторения справедливы следующие равенства " α: α1= α, α2= αα, α3= ααα... и т. д.

Среди всех цепочек символов выделяется одна особенная — пустая цепочка. Пустая цепочка символов - это цепочка, не содержащая ни одного символа. Пустую цепочку здесь везде будем обозначать греческой буквой λ (в литератур ее иногда обозначают латинской буквой е или греческой ξ).

Для пустой цепочки справедливы следующие равенства:

1.  ‌ λ ‌‌=0

2. "a: λa = a λ = a;

3. λR = λ;

4. λ n≥0: λ n = λ;

5. "a: a° = λ.

 

 

Понятие языка. Формальное определение языка

 

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

Алфавит - это счетное множество допустимых символов языка. Будем означать это множество символом V. Интересно, что согласно формальному определению, алфавит не обязательно должен быть конечным (перечислимым) множеством, но реально все существующие языки строятся на основе конечных алфавитов.

Цепочка символов a является цепочкой над алфавитом V: a(V), если в нее  входят только символы, принадлежащие множеству символов V. Для любого алфавита V пустая цепочка λ может как являться, так и не являться цепочкой λ(V) Это условие оговаривается дополнительно.

Если V - некоторый алфавит, то:

·                   V+ — множество всех цепочек над алфавитом V без λ;

·                   V* — множество всех цепочек над алфавитом V, включая λ.

Справедливо равенство: V* = V+ È { λ }.

Языком L над алфавитом V: L(V) называется некоторое счетное подмножество цепочек конечной длины из множества всех цепочек над алфавитом V. Из этого определения следуют два вывода: во-первых, множество цепочек языка не обязано быть конечным; во-вторых, хотя каждая цепочка символов, входящая в язык, обязана иметь конечную длину, эта длина может быть сколь угодно большой и формально ничем не ограничена.

Все существующие языки подпадают под это определение. Большинство реальных естественных и искусственных языков содержат бесконечное множество цепочек. Также в большинстве языков длина цепочки ничем не ограничена (например, этот длинный текст - пример цепочки символов русского языка). Цепочку символов, принадлежащую заданному языку, часто называют предложением языка, а множество цепочек символов некоторого языка L(V) — множеством предложений этого языка.

Для любого языка L(V) справедливо: L(V) Í V*.

Язык L(V) включает в себя язык L'(V): L'(V)ÍL(V), если " L(V): L'(V).

Множество цепочек языка L'(V) является подмножеством множества цепочек языка L(V) (или эти множества совпадают). Очевидно, что оба языка должны строится на основе одного и того же алфавита.

Два языка L(V) и L'(V) совпадают (эквивалентны): L'(V)=L(V), если L'(V)=L(V) и L(V)ÍL'(V); или, что то же самое: "aÎL'(V): "aÎL(V) и "aÎL'(V): "aÎL(V).

Множества допустимых цепочек символов для эквивалентных языков должны быть равны.

Два языка L(V) и L'(V) почти эквивалентны: L'(V)ºL(V), если L'(V)È{l}=L(V)È{l}. Множества допустимых цепочек символов почти эквивалентных языков могут различаться только на пустую цепочку символов.

 

 

Способы задания языков

 

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

Язык задать можно тремя способами:

1.                 Перечислением всех допустимых цепочек языка.

2.                 Указанием способа порождения цепочек языка (заданием грамматики языка).

3.                 Определением метода распознавания цепочек языка.

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

Например, запись L({0,1}) = {0nln, n > 0} задает язык над алфавитом V - {0,1}, содержащий все последовательности с чередующимися символами 0 и 1, начинающиеся с 0 и заканчивающиеся 1. Видно, что пустая цепочка символов в этот язык не входит. Если изменить условие в этом определении с n > 0 на n³0, то получим почти эквивалентный язык L'({0,1}), содержащий пустую цепочку.

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

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

 

 

 

 

 

Синтаксис и семантика языка

 

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

Синтаксис языка - это набор правил, определяющий допустимые конструкции языка. Синтаксис определяет «форму языка» - задает набор цепочек символов, которые принадлежат языку. Чаще всего синтаксис языка можно задать в виде строгого набора правил, но полностью это утверждение справедливо только для чисто формальных языков. Даже для большинства языков программирования набор заданных синтаксических конструкций нуждается в дополнительных пояснениях, а синтаксис языков естественного общения вполне соответствует общепринятому мнению о том, что «исключения только подтверждают правило».

Например, любой окончивший среднюю школу может сказать, что строка «3+2» является арифметическим выражением, а «3 2 +» — не является. Правда, не каждый задумается при этом, что он оперирует синтаксисом алгебры.

Семантика языка - это раздел языка, определяющий значение предложений языка. Семантика определяет «содержание языка» - задает значение для всех допустимых цепочек языка. Семантика для большинства языков определяется неформальными методами (отношения между знаками и тем, что они обозначают, изучаются семиотикой). Чисто формальные языки лишены какого-либо смысла. Возвращаясь к примеру, приведенному выше, и используя семантику алгебры, мы можем сказать, что строка «3 + 2» есть сумма чисел 3 и 2, а также то, что «3 + 2 = 5» - это истинное выражение. Однако изложить любому ученику синтаксис алгебры гораздо проще, чем ее семантику, хотя в данном случае семантику как раз можно определить формально.

Лексика — это совокупность слов (словарный запас) языка. Слово или лексическая единица (лексема) языка — это конструкция, которая состоит из элементов алфавита языка и не содержит в себе других конструкций. Иначе говоря, лексическая единица может содержать только элементарные символы и не может содержать других лексических единиц.

Лексическими единицами (лексемами) русского языка являются слова русского языка, а знаки препинания и пробелы представляют собой разделители, не образующие лексем. Лексическими единицами алгебры являются числа, знаки математических операций, обозначения функций и неизвестных величин. В языках программирования лексическими единицами являются ключевые слова, идентификаторы, константы, метки, знаки операций; в них также существуют и разделители (запятые, скобки, точки с запятой и т. д.).

 

 

Понятие о грамматике языка

 

Грамматика — это описание способа построения предложений некоторого языка. Иными словами, грамматика — это математическая система, определяющая язык.

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

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

Правило (или продукция) — это упорядоченная пара цепочек символов (a,b)-В правилах очень важен порядок цепочек, поэтому их чаще записывают в виде a®b (или a::=b). Такая запись читается как «a порождает b» или «b по определению есть a».

Грамматика языка программирования содержит правила двух типов: первые (определяющие синтаксические конструкции языка) довольно легко поддаются формальному описанию; вторые (определяющие семантические ограничения языка) обычно излагаются в неформальной форме. Поэтому любое описание (или общепринятый стандарт) языка программирования обычно состоит из двух частей: вначале формально излагаются правила построения синтаксических конструкций, а потом на естественном языке дается описание семантических правил. Естественный язык понятен человеку, пользователю, который будет писать программы на языке программирования; для компилятора же семантические ограничения необходимо излагать в виде алгоритмов проверки правильности программы (речь, как уже было сказано выше, не идет о смысле программ, а только лишь о семантических ограничениях на исходный текст). Такой проверкой в компиляторе занимается семантический анализатор — специально для этого разработанная часть компилятора.

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

Язык, заданный грамматикой G, обозначается как L(G).

Две грамматики G и G' называются эквивалентными, если они определяют один и тот же язык: L(G)=L(G'). Две грамматики G и G' называются почти эквивалентными, если заданные ими языки различаются не более чем на пустую цепочку символов: L(G) È{l} = L(G') È {l}.

 

 

Особенности языков программирования

 

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

Для задания языка программирования необходимо решить три вопроса:

1.                 Определить множество допустимых символов языка;

2.                 Определить множество правильных программ языка;

3.                 Задать смысл для каждой правильной программы.

Только первые два вопроса полностью или частично удается решить с помощью теории формальных языков.

Первый вопрос решается легко. Определяя алфавит языка, мы автоматически определяем множество допустимых символов. Для языков программирования алфавит — это чаще всего тот набор символов, которые можно ввести с клавиатуры. Основу его составляет младшая половина таблицы международной кодировки символов (таблицы ASCII), к которой добавляются символы национальных алфавитов.

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

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

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

·                   изложить смысл программы, написанной на языке программирования, на другом языке, более понятном тому, кому адресована программа;

·                   использовать для проверки смысла некоторую «идеальную машину», которая предназначена для выполнения программ, написанных на данном языке.

Все, кто писал программы, так или иначе обязательно использовали первый подход. Комментарии в хорошей программе - это и есть изложение ее смысла. Построение блок-схемы, а равно любое другое описание алгоритма программы — это тоже способ изложить смысл программы на другом языке (например, языке графических символов блок-схем алгоритмов, смысл которого, в свою очередь, изложен в соответствующем ГОСТе). Да и документация к программе — тоже способ изложения ее смысла. Но все эти способы ориентированы на человека, которому они, конечно же, более понятны. Однако не существует пока универсального способа проверить, насколько описание соответствует программе.

Машина же понимает только один язык — язык машинных команд. Но изложить программу на языке машинных команд — задача слишком трудоемкая для человека, как раз для ее решения и создаются трансляторы.

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

Например, предложение в программе на языке Pascal вида:

i:=4; while 1=0 do i:=0;

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

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

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

Итак, на основании изложенных положений можно сказать, что возможности трансляторов по проверке осмысленности предложений входного языка сильно ограничены, практически даже равны нулю. Именно поэтому большинство из них в лучшем случае ограничиваются рекомендациями разработчикам по тем местам исходного текста программ, которые вызывают сомнения с точки зрения смысла. Поэтому большинство трансляторов обнаруживает только незначительный процент от общего числа смысловых («семантических») ошибок, а следовательно, подавляющее число такого рода ошибок всегда, к большому сожалению, остается на совести автора программы.

 

Формальное определение грамматики. Форма Бэкуса—Наура

 

Для полного формального определения грамматики кроме правил порождения цепочек языка необходимо задать также алфавит языка.

Формально грамматика G определяется как четверка G(VT,VN,P,S), где:

·                   VT множество терминальных символов;

·                   VN множество нетерминальных символов: VNÈVT = Æ;

·                   Р множество правил (продукций) грамматики вида a®b, где V+, V*;

·                   S целевой (начальный) символ грамматики SÎVN.

Множество V = VNÈVT называют полным алфавитом грамматики G.

Рассмотрим множества VN и VT. Множество терминальных символов VT содержит символы, которые входят в алфавит языка, порождаемого грамматикой. Как правило, символы из множества VT встречаются только в цепочках правых частей правил, если же они встречаются в цепочке левой части правила, то обязаны быть и в цепочке правой его части. Множество нетерминальных символов VN содержит символы, которые определяют слова, понятия, конструкции языка. Каждый символ этого множества может встречаться в цепочках как левой, так и правой частей правил грамматики, но он обязан хотя бы один раз быть в левой части хотя бы одного правила. Правила грамматики строятся так, чтобы в левой части каждого правила был хотя бы один нетерминальный символ.

Эти два множества не пересекаются: каждый символ может быть либо терминальным, либо нетерминальным. Ни один символ в алфавите грамматики не может быть нетерминальным и терминальным одновременно. Целевой символ грамматики — это всегда нетерминальный символ.

Во множестве правил грамматики может быть несколько правил, имеющих одинаковые правые части, вида: a®b1, a®b2,…,a®bn. Тогда эти правила объединяют вместе и записывают в виде: a®b1,|b2|…,|bn. Одной строке в такой записи соответствует сразу n правил.

Такую форму записи правил грамматики называют формой Бэкуса-Наура. Форма Бэкуса-Наура предусматривает, как правило, также, что нетерминальные символы берутся в угловые скобки: < >. Иногда знак «®» в правилах грамматики заменяют на знак «::=» (что характерно для старых монографий), но это всего лишь незначительные модификации формы записи, не влияющие на ее суть.

Ниже приведен пример грамматики для целых десятичных чисел со знаком:

G({0,1.2,3.4,5.6,7,8.9,-.+}.{<число>,<чс>.<цифра>},Р.<число>)

Р:

<число> ® <чс> | +<чс>| -<чс>

<чс> ® <цифра> | <чс><цифра>

<цифра> ®0|1|2|3|4|5|6|7|8|9

Рассмотрим составляющие элементы грамматики G:

·                   множество терминальных символов VT содержит двенадцать элементов: десять десятичных цифр и два знака;

·                   множество нетерминальных символов VN содержит три элемента: символы <число>, <чс> и <цифра>;

·                   множество правил содержит 15 правил, которые записаны в три строки (то есть имеются только три различных правых части правил);

·                   целевым символом грамматики является символ <число>.

Следует отметить, что символ <чс> — это бессмысленное сочетание букв русского языка, но это обычный нетерминальный символ грамматики, такой же, как и два других. Названия нетерминальных символов не обязаны быть осмысленными, это сделано просто для удобства понимания правил грамматики человеком. В принципе в любой грамматике можно полностью изменить имена всех нетерминальных символов, не меняя при этом языка, заданного грамматикой, - точно также, например, в программе на языке Pascal можно изменить имена идентификаторов, и при этом не изменится смысл программы.

Для терминальных символов это неверно. Набор терминальных символов всегда строго соответствует алфавиту языка, определяемого грамматикой.

Вот, например, та же самая грамматика для целых десятичных чисел со знаком, в которой нетерминальные символы обозначены большими латинскими буквами (далее это будет часто применяться в примерах):

G'({0,1,2.3,4,5,6,7,8,9,-,+}.{S,T,F},P,S) Р:

S ®T |+T | -T

Т ® F | TF

F®0|1|2|3|4|5|6|7|8|9

Здесь изменилось только множество нетерминальных символов. Теперь VN= {S.T.F}. Язык, заданный грамматикой, не изменился — грамматики G и G' эквивалентны.

 

 

Принцип рекурсии в правилах грамматики

 

Особенность формальных грамматик в том, что они позволяют определить бесконечное множество цепочек языка с помощью конечного набора правил (конечно, множество цепочек языка тоже может быть конечным, но даже для простых реальных языков это условие обычно не выполняется). Приведенная выше в примере грамматика для целых десятичных чисел со знаком определяет бесконечное множество целых чисел с помощью 15 правил.

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

В рассмотренной выше грамматике G непосредственная рекурсия присутствует в правиле: <чс>®<чс><цифра>, а в эквивалентной ей грамматике G' - в правиле: T®TF.

Чтобы рекурсия не была бесконечной, для участвующего в ней нетерминального символа грамматики должны существовать также и другие правила, которые определяют его, минуя самого себя, и позволяют избежать бесконечного рекурсивного определения (в противном случае этот символ в грамматике был бы просто не нужен). Такими правилами являются <чс>®<цифра> - в грамматике G и T®F — в грамматике G'.

В теории формальных языков более ничего сказать о рекурсии нельзя. Но, чтобы полнее понять смысл рекурсии, можно прибегнуть к семантике языка - в рассмотренном выше примере это язык целых десятичных чисел со знаком. Рассмотрим его смысл.

Если попытаться дать определение тому, что же является числом, то начать можно с того, что любая цифра сама по себе есть число. Далее можно заметить, что любые две цифры - это тоже число, затем - три цифры и т. д. Если строить определение числа таким методом, то оно никогда не будет закончено (в математике разрядность числа ничем не ограничена). Однако можно заметить, что каждый раз, порождая новое число, мы просто дописываем цифру справа (поскольку привыкли писать слева направо) к уже написанному ряду цифр. А этот ряд цифр, начиная от одной цифры, тоже в свою очередь является числом. Тогда определение для понятия «число» можно построить таким образом: «число — это любая цифра, либо другое число, к которому справа дописана любая цифра». Именно это и составляет основу правил грамматик G и G' и отражено во второй строке правил в правилах <чс>®<цифра> | <чс><цифра> и T®F|TF. Другие правила в этих грамматиках позволяют добавить к числу знак (первая строка правил) и дают определение понятию «цифра» (третья строка правил). Они элементарны и не требуют пояснений.

Принцип рекурсии (иногда его называют «принцип итерации», что не меняет сути) - важное понятие в представлении о формальных грамматиках. Так или иначе, явно или неявно рекурсия всегда присутствует в грамматиках любых реальных языков программирования. Именно она позволяет строить бесконечное множество цепочек языка, и говорить об их порождении невозможно без понимания принципа рекурсии. Как правило, в грамматике реального языка программирования содержится не одно, а целое множество правил, построенных с помощью рекурсии.

 

 

Другие способы задания грамматик

 

Форма Бэкуса-Наура - удобный с формальной точки зрения, но не всегда доступный для понимания способ записи формальных грамматик. Рекурсивные определения хороши для формального анализа цепочек языка, но не удобны с точки зрения человека. Например, то, что правила <чс>®<цифра>|<чс><цифра> отражают возможность для построения числа дописывать справа любое число цифр, начиная от одной, неочевидно и требует дополнительного пояснения.

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

Далее рассмотрим два наиболее распространенных из этих способов: запись правил грамматик с использованием метасимволов и запись правил грамматик в графическом виде.

 

Запись правил грамматик с использованием метасимволов

 

Запись правил грамматик с использованием метасимволов предполагает, что в строке правила грамматики могут встречаться специальные символы - метасимволы, - которые имеют особый смысл и трактуются специальным образом.

В качестве таких метасимволов чаще всего используются следующие символы:

() (круглые скобки), [] (квадратные скобки), {} (фигурные скобки), «,» (запятая) и "" (кавычки).

Эти метасимволы имеют следующий смысл:

·                   круглые скобки означают, что из всех перечисленных внутри них цепочек символов в данном месте правила грамматики может стоять только одна цепочка;

·                   квадратные скобки означают, что указанная в них цепочка может встречаться, а может и не встречаться в данном месте правила грамматики (то есть может быть в нем один раз или ни одного раза);

·                   фигурные скобки означают, что указанная внутри них цепочка может не встречаться в данном месте правила грамматики ни одного раза, встречаться один раз или сколь угодно много раз;

·                   запятая служит для того, чтобы разделять цепочки символов внутри круглых скобок;

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

Вот как должны выглядеть правила рассмотренной выше грамматики G, если их записать с использованием метасимволов:

<число> ® [(+,-)]<цифра>{<цифра>}

<цифра> ®0|1|2|3|4|5|6|7|8|9

Вторая строка правил не нуждается в комментариях, а первое правило читается так: «число есть цепочка символов, которая может начинаться с символов + или -. должна содержать дальше одну цифру, за которой может следовать последовательность из любого количества цифр». В отличие от формы Бэкуса—Наура, в форме записи с помощью метасимволов, как видно, во-первых, убран из грамматики малопонятный нетерминальный символ <чс>, а во-вторых - удалось полностью исключить рекурсию. Грамматика в итоге стала более понятной.

Форма записи правил с использованием метасимволов - это удобный и понятный способ представления правил грамматик. Она во многих случаях позволяет полностью избавиться от рекурсии, заменив ее символом итерации {} (фигурные скобки). Как будет понятно из дальнейшего материала, эта форма наиболее употребительна для одного из типов грамматик - регулярных грамматик.

 

 

 

Запись правил грамматик в графическом виде

 

При записи правил в графическом виде вся грамматика представляется в форме набора специальным образом построенных диаграмм. Эта форма была предложена при описании грамматики языка Pascal, а затем она получила широкое распространение в литературе. Она доступна не для всех типов грамматик, а только для контекстно-свободных и регулярных типов, но этого достаточно, чтобы ее можно было использовать для описания грамматик известных языков программирования.

В такой форме записи каждому нетерминальному символу грамматики соответствует диаграмма, построенная в виде направленного графа. Граф имеет следующие типы вершин:

·                   точка входа (на диаграмме никак не обозначена, из нее просто начинается входная дуга графа);

·                   нетерминальный символ (на диаграмме обозначается прямоугольником, в который вписано обозначение символа);

·                   цепочка терминальных символов (на диаграмме обозначается овалом, кругом или прямоугольником с закругленными краями, внутрь которого вписана цепочка);

·                   узловая точка (на диаграмме обозначается жирной точкой или закрашенным кружком);

·                   точка выхода (никак не обозначена, в нее просто входит выходная дуга графа).

Каждая диаграмма имеет только одну точку входа и одну точку выхода, но сколько угодно вершин других трех типов. Вершины соединяются между собой направленными дугами графа (линиями со стрелками). Из входной точки дуги могут только выходить, а во входную точку - только входить. В остальные вершины дуги могут как входить, так и выходить (в правильно построенной грамматике каждая вершина должна иметь как минимум один вход и как минимум один выход).

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

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

Это удобный способ описания правил грамматик, оперирующий образами, а потому ориентированный исключительно на людей. Даже простое изложение его основных принципов здесь оказалось довольно громоздким, в то время как суть способа довольно проста. Это можно легко заметить, если посмотреть на описание понятия «число» из грамматики G с помощью диаграмм на рис. 1.

Число:

 

Рис. 1. Графическое представление грамматики целых десятичных чисел со знаком: вверху - для понятия «число»; внизу - для понятия «цифра»

 

Как уже было сказано выше, данный способ в основном применяется в литературе при изложении грамматик языков программирования. Для пользователей - разработчиков программ - он удобен, но практического

применения в компиляторах пока не имеет.

 

 

Классификация языков и грамматик

 

Выше уже упоминались различные типы грамматик, но не было указано, как и по какому принципу они подразделяются на типы. Для человека языки бывают простые и сложные, но это сугубо субъективное мнение, которое зачастую зависит от личности человека.

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

 

Классификация  языков

Языки классифицируются в соответствии с типами грамматик, с помощью которых они заданы. Причем, поскольку один и тот же язык в общем случае может быть задан сколь угодно большим количеством грамматик, которые могут относиться к различным классификационным типам, то для классификации самого языка среди всех его грамматик всегда выбирается грамматика с максимально возможным классификационным типом. Например, если язык L может быть задан грамматиками G1 и G2, относящимися к типу 1 (контекстно-зависимые), грамматикой G3, относящейся к типу 2 (контекстно-свободные), и грамматикой G4, относящейся к типу 3 (регулярные), то сам язык должен быть отнесен к типу 3 и является регулярным языком.

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

Сложность языка убывает с возрастанием номера классификационного типа языка. Самыми сложными является языки типа 0, самыми простыми — языки типа 3.

Согласно классификации грамматик, существуют также четыре типа языков.

Тип 0: языки с фразовой структурой

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

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

Далее языки с фразовой структурой рассматриваться не будут.

Тип 1: контекстно-зависимые (КЗ) языки

Тип 1 — второй по сложности тип языков. В общем случае время на распознавание предложений языка, относящегося к типу 1, экспоненциально зависит от длины исходной цепочки символов.

Языки и грамматики, относящиеся к типу 1, применяются в анализе и переводе текстов на естественных языках. Распознаватели, построенные на их основе, позволяют анализировать тексты с учетом контекстной зависимости в предложениях входного языка (но они не учитывают содержание текста, поэтому в общем случае для точного перевода с естественного языка все же требуется вмешательство человека). На основе таких грамматик может выполняться автоматизированный перевод с одного естественного языка на другой, ими могут пользоваться сервисные функции проверки орфографии и правописания в языковых процессорах.

В компиляторах КЗ-языки не используются, поскольку языки программирования имеют более простую структуру, поэтому здесь они подробно не рассматриваются.

Тип 2: контекстно-свободные (КС) языки

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

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

Однако среди КС-языков существует много классов языков, для которых эта зависимость линейна. Многие языки программирования можно отнести к одному из таких классов.

Тип 3: регулярные языки

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

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

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

 

 

 

Классификация  грамматик

 Четыре типа грамматик по Хомскому

 

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

По классификации Хомского выделяют четыре типа грамматик.

Тип 0: грамматики с фразовой структурой

На структуру их правил не накладывается никаких ограничений: для грамматики вида G(VT,VN,P,S), V = VNÈVT правила имеют вид: a®b, где V+ , V*.

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

Практического применения грамматики, относящиеся только к типу 0, не имеют.

Тип 1: контекстно-зависимые (КЗ) и неукорачивающие грамматики

В этот тип входят два основных класса грамматик.

Контекстно-зависимые грамматики G(VT,VN,P,S), V = VNÈVT имеют правила вида: a1Aa2®a1ba2, где a1a2Î V*, VN, V+.

Неукорачивающие грамматики G(VT,VN,P,S), V = VNÈVT имеют правила вида:  a®b, где a,bÎ V+,|b|³|a|

Структура правил КЗ-грамматик такова, что при построении предложений заданного ими языка один и тот же нетерминальный символ может быть заменен на ту или иную цепочку символов в зависимости от того контекста, в котором он встречается. Именно поэтому эти грамматики называют «контекстно-зависимыми». Цепочки a1 и a2 в правилах грамматики обозначают контекст (a1 — левый контекст, а a2 — правый контекст), в общем случае любая из них (или даже обе) может быть пустой. Говоря иными словами, значение одного и того же символа может быть различным в зависимости от того, в каком контексте он встречается.

Неукорачивающие грамматики имеют такую структуру правил, что при построении предложений языка, заданного грамматикой, любая цепочка символов может быть заменена на цепочку символов не меньшей длины. Отсюда и название «неукорачивающие».

Доказано, что эти два класса грамматик эквивалентны. Это значит, что для любого языка, заданного контекстно-зависимой грамматикой, можно построить неукорачивающую грамматику, которая будет задавать эквивалентный язык, и наоборот: для любого языка, заданного неукорачивающей грамматикой, можно построить контекстно-зависимую грамматику, которая будет задавать эквивалентный язык.

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

Тип 2: контекстно-свободные (КС) грамматики

Контекстно-свободные (КС) грамматики G(VT,VN,P,S), V = VNÈVT имеют правила вида: A®b, где VN, V+. Такие грамматики также иногда называют неукорачивающими контекстно-свободными (НКС) грамматиками (видно, что в правой части правила у них должен всегда стоять как минимум один символ).

Существует также почти эквивалентный им класс грамматик — укорачивающие контекстно-свободные (УКС) грамматики G(VT,VN,P,S), V = VNÈVT, правила которых могут иметь вид: A®b, где VN, V*.

Разница между этими двумя классами грамматик заключается лишь в том, что в УКС-грамматиках в правой части правил может присутствовать пустая цепочка (l), а в НКС-грамматиках — нет. Отсюда ясно, что язык, заданный НКС-грамматикой, не может содержать пустой цепочки. Доказано, что эти два класса грамматик почти эквивалентны. В дальнейшем, когда речь будет идти о КС-грамматиках, уже не будет уточняться, какой класс грамматики (УКС или НКС) имеется в виду, если возможность наличия в языке пустой цепочки не имеет принципиального значения.

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

Внутри типа КС-грамматик кроме классов НКС и УКС выделяют еще целое множество различных классов грамматик, и все они относятся к типу 1. Далее, когда КС-грамматики и КС-языки будут рассматриваться более подробно, на некоторые из этих классов грамматик и их характерные особенности будет обращено особое внимание.

Тип 3: регулярные грамматики

К типу регулярных относятся два эквивалентных класса грамматик: леволинейные и праволинейные.

Леволинейные грамматики G(VT,VN,P,S), V = VNÈVT, могут иметь правила двух видов: А®Вg или А®g, где A,BÎVN, VT*.

В свою очередь, праволинейные грамматики G(VT,VN,P,S), V = VNÈVT, могут иметь правила тоже двух видов: А® g В или А®g, где A,BÎVN, VT*.

Эти два класса грамматик эквивалентны и относятся к типу регулярных грамматик.

Регулярные грамматики используются при описании простейших конструкций языков программирования: идентификаторов, констант, строк, комментариев и т. д. Эти грамматики исключительно просты и удобны в использовании, поэтому в компиляторах на их основе строятся функции лексического анализа входного языка (принципы их построения будут рассмотрены далее).

Типы грамматик соотносятся между собой особым образом. Из определения типов 2 и 3 видно, что любая регулярная грамматика является КС-грамматикой, но не наоборот. Также очевидно, что любая грамматика может быть отнесена и к типу 0, поскольку он не накладывает никаких ограничений на правила. В то же время существуют укорачивающие КС-грамматики (тип 2), которые не являются ни контекстно-зависимыми, ни неукорачивающими (тип 1), поскольку могут содержать правила вида «А®l», недопустимые в типе 1. В целом можно сказать, что сложность грамматики обратно пропорциональна тому максимально возможному номеру типа, к которому может быть отнесена грамматика. Грамматики, которые относятся только к типу 0, являются самыми сложными, а грамматики, которые можно отнести к типу 3 — самыми простыми

 

.Цепочки вывода. Сентенциальная форма

 

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

Цепочка b = d1gd2 называется непосредственно выводимой из цепочки a=d1wd2 в грамматике G(VT,VN,P,S), V = VTÈVN, d1,g,d2 ÎV*, V+, если в грамматике G существует правило: w®g Î Р. Непосредственная выводимость цепочки b из цепочки a обозначается так: aÞb. Иными словами, цепочка b выводима из цепочки a в том случае, если можно взять несколько символов в цепочке a, заменить их на другие символы согласно некоторому правилу грамматики и получить цепочку b. В формальном определении непосредственной выводимости любая из цепочек d1 или d2 (а равно и обе эти цепочки) может быть пустой. В предельном случае вся цепочка a может быть заменена на цепочку b, тогда в грамматике G должно существовать правило: a®b Î Р.

Цепочка b называется выводимой из цепочки a (обозначается *b) в том случае, если выполняется одно из двух условий:

·                   непосредственно выводима из a (aÞb);

·                    $ g, такая, что: g выводима из a и b непосредственно выводима из g (*g и gÞb).

Это рекурсивное определение выводимости цепочки. Суть его заключается в том, что цепочка b выводима из цепочки a, если aÞb или же если можно построить последовательность непосредственно выводимых цепочек от a к b следующего

вида: aÞg1Þ¼ÞgiÞ¼ÞgnÞb, n³1. В этой последовательности каждая последующая цепочка gi непосредственно выводима из предыдущей цепочки   gi-1.

Такая последовательность непосредственно выводимых цепочек называется выводом или цепочкой вывода. Каждый переход от одной непосредственно выводимой цепочки к следующей в цепочке вывода называется шагом вывода. Очевидно, что шагов вывода в цепочке вывода всегда на один больше, чем промежуточных цепочек. Если цепочка b непосредственно выводима из цепочки a: aÞb, то имеется всего один шаг вывода.

Если цепочка вывода из a к b содержит одну или более промежуточных цепочек (два или более шагов вывода), то она имеет специальное обозначение aÞ+b (говорят, что цепочка b нетривиально выводима из цепочки a). Если количество шагов вывода известно, то его можно указать непосредственно у знака выводимости цепочек. Например, запись 4b означает, что цепочка b выводится из цепочки a за 4 шага вывода1.

 

 

Сентенциальная форма грамматики. Язык, заданный грамматикой

 

Вывод называется законченным, если на основе цепочки b, полученной в результате вывода, нельзя больше сделать ни одного шага вывода. Иначе говоря, вывод называется законченным, если цепочка b, полученная в результате вывода, пустая или содержит только терминальные символы грамматики G(VT,VN,P,S): VT*. Цепочка b, полученная в результате законченного вывода, называется конечной цепочкой вывода.

В рассмотренном выше примере все построенные выводы являются законченными, а, например, вывод S Þ* -4FF (из первой цепочки в примере) будет незаконченным.

Цепочка символов V* называется сентенциальной формой грамматики G(VT,VN,P,S), V = VTÈVN, если она выводима из целевого символа грамматики S: S Þ*a. Если цепочка VT* получена в результате законченного вывода, то она называется конечной сентенциальной формой.

Из рассмотренного выше примера можно заключить, что цепочки символов    «-479» и «18» являются конечными сентенциальными формами грамматики целых десятичных чисел со знаком, так как существуют выводы S Þ* -479 и S Þ* 18 (примеры 1 и 2). Цепочка F8 из вывода 2, например, тоже является сентенциальной формой, поскольку справедливо S =>* F8, но она не является конечной цепочкой вывода. В то же время в выводах примеров 3—5 явно не присутствуют сентенциальные формы. На самом деле цепочки «350», «1004» и «5» являются конечными сентенциальными формами. Чтобы доказать это, необходимо просто построить другие цепочки вывода (например, для цепочки «5» строим: S => Т => F => 5 и получаем S => * 5). А вот цепочка «TFTV (пример 4) не выводима из целевого| символа грамматики S, а потому сентенциальной формой не является.

Язык L, заданный грамматикой G(VT,VN,P,S), — это множество всех конечных  сентенциальных форм грамматики G. Язык L, заданный грамматикой G, обозначается как L(G). Очевидно, что алфавитом такого языка L(G ) будет множество терминальных символов грамматики VT, поскольку все конечные сентенциальные формы грамматики — это цепочки над алфавитом VT.

Следует помнить, что две грамматики G(VT,VN,P,S) и G'(VT',VN',P',S') называются эквивалентными, если эквивалентны заданные ими языки: L(G) = L(G'). Очевидно, что эквивалентные грамматики должны иметь, по крайней мере, пересекающиеся множества терминальных символов VTÇVT' ¹ Æ (как правило, эти множества даже совпадают VT = VT' ), а вот множества нетерминальных символов, правила грамматики и целевой символ у них могут кардинально отличаться.

Левосторонний и правосторонний выводы

 

Вывод называется левосторонним, если в нем на каждом шаге вывода правило грамматики применяется всегда к крайнему левому нетерминальному символу в цепочке. Другими словами, вывод называется левосторонним, если на каждом шаге вывода происходит подстановка цепочки символов на основании правила грамматики вместо крайнего левого нетерминального символа в исходной цепочке.

Аналогично, вывод называется правосторонним, если в нем на каждом шаге вывода правило грамматики применяется всегда к крайнему правому нетерминальному символу в цепочке.

Если рассмотреть цепочки вывода из того же примера, то в нем выводы 1 и 5 являются левосторонними, выводы 2,3 и 5 правосторонними (вывод 5 одновременно является и лево- и правосторонним), а вот вывод 4 не является ни левосторонним, ни правосторонним.

Для грамматик типов 2 и 3 (КС-грамматик и регулярных грамматик) для любой сентенциальной формы всегда можно построить левосторонний или правосторонний выводы. Для грамматик других типов это не всегда возможно, так как по структуре их правил не всегда можно выполнить замену крайнего левого или крайнего правого нетерминального символа в цепочке.

А вот рассмотренный выше вывод S Þ * aaaabbbbcccc для грамматики G3, задающей язык L(G3) - {0nln|n > 0}, не является ни левосторонним, ни правосторонним. Грамматика относится к типу 1, и в данном случае для нее нельзя построить такой вывод, на каждом шаге которого только один нетерминальный символ заменялся бы на цепочку символов.

 

Дерево вывода. Методы построения дерева вывода

 

Деревом вывода грамматики G(VT,VN,P,S) называется дерево (граф), которое соответствует некоторой цепочке вывода и удовлетворяет следующим условиям:

каждая вершина дерева обозначается символом грамматики AÎ(VT ÈVN);

корнем дерева является вершина, обозначенная целевым символом грамматики — S;

листьями дерева (концевыми вершинами) являются вершины, обозначенные терминальными символами грамматики или символом пустой цепочки l;

если некоторый узел дерева обозначен символом AÎVN, а связанные с ним узлы — символами bi,b2,...,bn; n > 0, "n ³ i > 0: bjÎ(VTÈVNÈ{l}), то в грамматике G(VT,VN,P,S) существует правило A®b1,b2,...,bn Î Р.

Из определения видно, что по структуре правил дерево вывода в указанном виде всегда можно построить только для грамматик типов 2 и 3 (контекстно-свободных и регулярных). Для грамматик других типов дерево вывода в таком виде можно построить не всегда (либо же оно будет иметь несколько иной вид).

На основе рассмотренного выше примера построим деревья вывода для цепочек вывода 1 и 2. Эти деревья приведены на рис. 2.

 

Рис. 2. Примеры деревьев вывода для грамматики целых десятичных чисел со знаком

 

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

При построении дерева вывода сверху вниз построение начинается с целевого символа грамматики, который помещается в корень дерева. Затем в грамматике выбирается необходимое правило, и на первом шаге вывода корневой символ раскрывается на несколько символов первого уровня. На втором шаге среди всех концевых вершин дерева выбирается крайняя (крайняя левая — для левостороннего вывода, крайняя правая — для правостороннего) вершина, обозначенная нетерминальным символом, для этой вершины выбирается нужное правило грамматики, и она раскрывается на несколько вершин следующего уровня. Построение дерева заканчивается, когда все концевые вершины обозначены терминальными символами, в противном случае надо вернуться ко второму шагу и продолжить построение.

Построение дерева вывода снизу вверх начинается с листьев дерева. В качеств листьев выбираются терминальные символы конечной цепочки вывода, которые на первом шаге построения образуют последний уровень (слой) дерева. Построение дерева идет по слоям. На втором шаге построения в грамматике выбирается правило, правая часть которого соответствует крайним символам в слое дерева (крайним правым символам при правостороннем выводе и крайним левым — при левостороннем). Выбранные вершины слоя соединяются с новой вершиной, которая выбирается из левой части правила. Новая вершина попадает в слой дерева вместо выбранных вершин. Построение дерева закончено, если достигнута корневая вершина (обозначенная целевым символом), а иначе надо вернуться ко второму шагу и повторить его над полученным слоем дерева.

Поскольку все известные языки программирования имеют нотацию записи «слева — направо», компилятор также всегда читает входную программу слева направо (и сверху вниз, если программа разбита на несколько строк). Поэтому для построения дерева вывода методом «сверху вниз», как правило, используется левосторонний вывод, а для построения «снизу вверх» — правосторонний вывод. На эту особенность компиляторов стоит обратить внимание. Нотация чтения программ «слева направо» влияет не только на порядок разбора программы компилятором (для пользователя это, как правило, не имеет значения), но и на порядок выполнения операций — при отсутствии скобок большинство равноправных операций выполняются в порядке слева направо, а это уже имеет существенное значение.

 

Задача разбора (постановка задачи)

 

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

Разработчики компилятора всегда имеют дело с уже определенным языком программирования. Грамматика для синтаксических конструкций этого языка известна. Она, как правило, четко описана в стандарте языка, и хотя форма описания может быть произвольной, ее всегда можно преобразовать к требуемому виду (например, к форме Бэкуса—Наура или к форме описания с использованием метасимволов). Задача разработчиков заключается в том, чтобы построить распознаватель для заданного языка, который затем будет основой синтаксического анализатора в компиляторе.

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

Задача разбора в общем виде может быть решена не для всех типов языков. Но как было сказано выше, разработчиков компиляторов интересуют, прежде всего, контекстно-свободные и регулярные языки. Для данных типов языков доказано, что задача разбора для них разрешима. Более того, для них найдены формальные методы ее решения.

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

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

 

 

 

Правила, задающие неоднозначность в грамматиках

 

В общем виде невозможно проверить, является ли заданная грамматика однозначной или нет. Однако для КС-грамматик существуют определенного вида правила, по наличию которых в множестве правил грамматики G(VT,VN,P,S) можно утверждать, что она является неоднозначной. Эти правила имеют следующий вид:

1. А ® АА | a,

2. А ® АaА | b,

3. А ® aА | Аb | g,

4. А ® aА | aАbА | g,

здесь AÎVN; a,b,(VNÈVT)*.

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

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

В рассмотренном выше примере грамматики арифметических выражений с операндами а и bG({+,-,*,/,(,),а,b},{S},P.S) — во множестве правил

Р: S ® S+S | S-S | S*S | S/S | (S) | а | b

встречаются правила 2 типа. Поэтому данная грамматика является неоднозначной, что и было показано выше.

 

 

Однозначные и неоднозначные грамматики

 

Рассмотрим некоторую грамматику G({+,-,*,/,(,),а,b},{S},РS):

Р: S ® S+S | S-S | S*S | S/S | (S)  | а | b

Видно, что представленная грамматика определяет язык арифметических выражений с четырьмя основными операциями (сложение, вычитание, умножение и деление) и скобками над операндами a и b. Примерами предложений этого языка могут служить: а*b+а, a*(a+b), а*b+a*a и т. д.

Возьмем цепочку а*b+а и построим для нее левосторонний вывод. Получится два варианта:

S Þ S+S Þ S*S+S Þ a*S+S Þ a*b+S Þ a*b+a

S ÞS*S Þ a*S Þ a*S+S Þ a*b+S Þ a*b+a

Каждому из этих вариантов будет соответствовать свое дерево вывода. Два варианта дерева вывода для цепочки «а*b+а» приведены на рис. 3

 

Рис. 3. Два варианта дерева цепочки «а*b+а» вывода для неоднозначной грамматики арифметических выражений

 

С точки зрения формального языка, заданного грамматикой, не имеет значения, какая цепочка вывода и какое дерево вывода из возможных вариантов будут построены. Однако для языков программирования, которые не являются чисто формальными языками и несут некоторую смысловую нагрузку, это имеет значение. Например, если принять во внимание, что рассмотренная здесь грамматики определяет язык неких арифметических выражений, то с точки зрения арифметики порядок построения дерева вывода соответствует порядку выполнения арифметических действий. В арифметике, как известно, при отсутствии скобок умножение всегда выполняется раньше сложения (умножение имеет более высокий приоритет), но в рассмотренной выше грамматике это ниоткуда не следует — в ней все операции равноправны. Поэтому с точки зрения арифметических операций приведенная грамматика имеет неверную семантику — в ней нет приоритета операций, а, кроме того, для равноправных операций не определен порядок выполнения («слева направо»), хотя синтаксическая структура построенных с ее помощью выражений будет правильной.

 

Такая ситуация называется неоднозначностью в грамматике. Естественно, для построения компиляторов и языков программирования нельзя использовать грамматики, допускающие неоднозначности. Дадим более точное определение неоднозначной грамматики.

Грамматика называется однозначной, если для каждой цепочки символов языка, заданного этой грамматикой, можно построить единственный левосторонний (и единственный правосторонний) вывод. Или, что то же самое: грамматика называется однозначной, если для каждой цепочки символов языка, заданного этой грамматикой, существует единственное дерево вывода. В противном случае грамматика называется неоднозначной.

Рассмотренная в примере грамматика арифметических выражений, очевидно, является неоднозначной.

 

 

Эквивалентность и преобразование грамматик

 

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

·                   как проверить, является ли данная грамматика однозначной?

·                   если заданная грамматика является неоднозначной, то как преобразовать ее к однозначному виду?

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

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

Если грамматика все же является неоднозначной, то необходимо преобразовать
ее в однозначный вид. Как правило, это возможно. Например, для рассмотренной выше неоднозначной грамматики арифметических выражений над операндами а и
b существует эквивалентная ей однозначная грамматика следующего
вида
G'({+,-,*,/,(,),а,b},{S,Т,E},P',S):

P':

S ® S+T     |S-T | Т

Т ® Т*Е     |         Т/Е | Е

Е ® (S)       |         а | b

В этой грамматике для рассмотренной выше цепочки символов языка а*b+а возможен только один левосторонний вывод:

S Þ S+T Þ T+T Þ Т*Е+Т Þ Е*Е+Т Þ а*Е+Т Þ a*b+T Þ a*b+E Þ a*b+a

Этому выводу соответствует единственно возможное дерево вывода. Оно приведено на рис. 4. Видно, что хотя цепочка вывода несколько удлинилась, но приоритет операций в данном случае единственно возможный и соответствует их порядку в арифметике.

 

Рис. 4. Дерево вывода для однозначной грамматики арифметических выражений

В таком случае необходимо решить две проблемы: во-первых, доказать, что две имеющиеся грамматики эквивалентны (задают один и тот же язык); во-вторых, иметь возможность проверить, что вновь построенная грамматика является однозначной.

Проблема эквивалентности грамматик в общем виде формулируется следующим образом: имеются две грамматики G и G', необходимо построить алгоритм, который бы позволял проверить, являются ли эти две грамматики эквивалентными.

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

Точно так же неразрешима в общем виде и проблема однозначности грамматик. Это значит, что не существует (и никогда не будет существовать) алгоритм, который бы позволял для произвольной заданной грамматики G проверить, является ли она однозначной или нет. Аналогично, не существует алгоритма, который бы позволял преобразовать заведомо неоднозначную грамматику G в эквивалентную ей однозначную грамматику G'.

В общем случае вопрос об алгоритмической неразрешимости проблем однозначности и эквивалентности грамматик сводится к вопросу об алгоритмической неразрешимости проблемы, известной как «проблема соответствий Поста». Проблема соответствий Поста формулируется следующим образом: имеется заданное множество пар непустых цепочек над алфавитом V: {(a1,b1), (a2,b2),..., (an,bn)} n > 0, "n > i > 0: ai,bI ÎV+; необходимо проверить, существует ли среди них такая последовательность пар цепочек: (a1,b1), (a2,b2),..., (am,bm), m > 0 (необязательно различных), что a1a2...am = b1b2...bm. Доказано, что не существует алгоритма, который бы за конечное число шагов мог дать ответ на этот вопрос, хотя на первый взгляд постановка задачи кажется совсем несложной.

То, что проблема не решается в общем виде, совсем не значит, что ее нельзя решить в каждом конкретном случае. Например, для алфавита V = {а,b} можно построить множество пар цепочек {(abbb.b), (a.aab), (ba.b)} и найти одно из решений: (a.aab),(a.aab),(ba,b),(abbb.b) — видно, что (a)(a)(ba)(abbb) = (aab)(aab) (b)(b). А для множества пар цепочек {(ab,aba),(aba,baa),(baa,aa)} очевидно, что решения не существует.

Точно так же неразрешимость проблем эквивалентности и однозначности грамматик в общем случае совсем не означает, что они не разрешимы вообще. Для некоторых частных случаев — например, для определенных типов и классов грамматик (в частности, для регулярных грамматик) — эти проблемы решены. Также их иногда удается решить полностью или частично в каждом конкретном случае, и для конкретной заданной грамматики доказать, является ли она однозначной или нет. Например, приведенная выше грамматика G' для арифметических выражений над операндами а и b относится к классу грамматик операторного предшествования из типа КС-грамматик. На основе этой грамматики возможно построить распознаватель в виде детерминированного расширенного МП-автомата, а потому можно утверждать, что она является однозначной.

 

 

Pаспознаватели.

Общая схема распознавателя

 

Для каждого языка программирования (как, наверное, и для многих других языков) важно не только уметь построить текст программы на этом языке, но и определить принадлежность имеющегося текста к данному языку. Именно эту задачу решают компиляторы в числе прочих задач (компилятор должен не только распознать исходную программу, но и построить эквивалентную ей результирующую программу). В отношении исходной программы компилятор выступает как распознаватель, а человек, создавший программу на некотором языке, выступает в роли генератора цепочек этого языка.

Распознаватель (или разборщик) — это специальный алгоритм, который позволяет определить принадлежность цепочки символов некоторому языку. Задача распознавателя заключается в том, чтобы на основании исходной цепочки дать ответ, принадлежит ли она заданному языку или нет. Распознаватели, как было сказано выше, представляют собой один из способов определения языка.

В общем виде распознаватель можно отобразить в виде условной схемы, представленной на рис. 5.

 

Рис. 5. Условная схема распознавателя

 

Следует подчеркнуть, что представленный рисунок — всего лишь условная схема, отображающая работу алгоритма распознавателя. Ни в коем случае не стоит искать подобного устройства в составе компьютера. Распознаватель, являющийся частью компилятора, представляет собой часть программного обеспечения компьютера.

Как видно из рисунка, распознаватель состоит из следующих основных компонентов:

·                   ленты, содержащей исходную цепочку входных символов, и считывающей головки, обозревающей очередной символ в этой цепочке;

·                   устройства управления (УУ), которое координирует работу распознавателя, имеет некоторый набор состояний и конечную память (для хранения своего состояния и некоторой промежуточной информации);

·                   внешней (рабочей) памяти, которая может хранить некоторую информацию в процессе работы распознавателя и в отличие от памяти УУ может иметь неограниченный объем.

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

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

Распознаватель работает по шагам или тактам. В начале такта, как правило, считывается очередной символ из входной цепочки, и в зависимости от этого символа УУ определяет, какие действия необходимо выполнить. Вся работа распознавателя состоит из последовательности тактов. В начале каждого такта состояние распознавателя определяется его конфигурацией. В процессе работы конфигурация распознавателя меняется.

Конфигурация распознавателя определяется следующими параметрами:

·                   содержимое входной цепочки символов и положение считывающей головки в ней;

·                   состояние УУ;

·                   содержимое внешней памяти.

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

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

Распознаватель допускает входную цепочку символов a, если, находясь в начальной конфигурации и получив на вход эту цепочку, он может проделать последовательность шагов, заканчивающуюся одной из его конечных конфигураций.

Формулировка «может проделать последовательность шагов» более точна, чем прямое указание «проделает последовательность шагов», так как для многих распознавателей при одной и той же входной цепочке символов из начальной конфигурации могут быть допустимы различные последовательности шагов, не все из которых ведут к конечной конфигурации.

Язык, определяемый распознавателем, — это множество всех цепочек, которые, допускает распознаватель.

 

Виды распознавателей

 

Распознаватели можно классифицировать в зависимости от вида составляв их компонентов: считывающего устройства, устройства управления (УУ) и внешней памяти.

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

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

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

По видам устройства управления распознаватели бывают детерминированные и недетерминированные.

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

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

По видам внешней памяти распознаватели бывают следующих типов:

·                   распознаватели без внешней памяти;

·                   распознаватели с ограниченной внешней памятью;

·                   распознаватели с неограниченной внешней памятью.

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

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

Распознаватели с неограниченной внешней памятью предполагают, что для их работы может потребоваться внешняя память неограниченного объема (как правило, вне зависимости от длины входной цепочки). У таких распознавателей предполагается память с произвольным методом доступа.

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

Тип распознавателя в классификации определяет сложность создания такого
распознавателя, а, следовательно, сложность разработки соответствующего программного обеспечения для компилятора. Чем выше в классификации стоит распознаватель, тем сложнее создавать алгоритм, обеспечивающий его работу. Разрабатывать двусторонние распознаватели сложнее, чем односторонние. Можно
заметить, что недетерминированные распознаватели по сложности выше детерминированных. Зависимость затрат на создание алгоритма от типа внешней памяти также очевидна.

 

Классификация распознавателей по типам языков

 

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

Выше было определено четыре основных типа языков. Доказано, что для каждого; из этих типов языков существует свой тип распознавателя с определенным составом компонентов и, следовательно, с заданной сложностью алгоритма работы.

Для языков с фразовой структурой (тип 0) необходим распознаватель, равноценный мощный машине Тьюринга — недетерминированный двусторонний автомат, имеющий неограниченную внешнюю память. Поэтому для языков данного типа нельзя гарантировать, что за ограниченное время на ограниченных вычислительных ресурсах распознаватель завершит работу и примет решение о том, принадлежит или не принадлежит входная цепочка заданному языку. Отсюда можно заключить, что практического применения языки с фразовой структурой не имеют (и не будут иметь), а потому далее они не рассматриваются.

Для контекстно-зависимых языков (тип 1) распознавателями являются двухсторонние недетерминированные автоматы с линейно ограниченной внешней памятью. Алгоритм работы такого автомата в общем случае имеет экспоненциальную сложность — количество шагов (тактов), необходимых автомату для распознавания входной цепочки, экспоненциально зависит от длины этой цепочки. Следовательно, и время, необходимое на разбор входной цепочки по заданному алгоритму, экспоненциально зависит от длины входной цепочки символов.

Такой алгоритм распознавателя уже может быть реализован в программном обеспечении компьютера — зная длину входной цепочки, всегда можно сказать, за какое максимально возможное время будет принято решение о принадлежности цепочки данному языку и какие вычислительные ресурсы для этого потребуются. Однако экспоненциальная зависимость времени разбора от длины цепочки существенно ограничивает применение распознавателей для контекстно-зависимых языков. Как правило, такие распознаватели применяются для автоматизированного перевода и анализа текстов на естественных языках, когда временные ограничения на разбор текста несущественны (следует также напомнить, что, поскольку естественные языки более сложны, чем контекстно-зависимый тип, то после такой обработки часто требуется вмешательство человека). В компилятоpax для анализа текстов на различных языках программирования контекстно-зависимые распознаватели не применяются, поскольку скорость работы компилятора имеет существенное значение, а синтаксический разбор текста программы можно выполнять в рамках более простого, контекстно-свободного типа языков.

Поэтому в рамках этого учебного пособия контекстно-зависимые языки также не рассматриваются.

Для контекстно-свободных языков (тип 2) распознавателями являются односторонние недетерминированные автоматы с магазинной (стековой) внешней памятью — МП-автоматы. При простейшей реализации алгоритма работы такого автомата он имеет экспоненциальную сложность, однако путем некоторых усовершенствований алгоритма можно добиться полиномиальной (кубической) зависимости времени, необходимого на разбор входной цепочки, от длины этой цепочки. Следовательно, можно говорить о полиномиальной сложности распознавателя для КС-языков.

Среди всех КС-языков можно выделить класс детерминированных КС-языков, распознавателями для которых являются детерминированные автоматы с магазинной (стековой) внешней памятью — ДМП-автоматы. Эти языки обладают свойством однозначности — доказано, что для любого детерминированного КС-языка всегда можно построить однозначную грамматику. Кроме того, для таких языков существует алгоритм работы распознавателя с квадратичной сложностью. Поскольку эти языки являются однозначными, именно они представляют наибольший интерес для построения компиляторов.

Более того, среди всех детерминированных КС-языков существуют такие классы языков, для которых возможно построить линейный распознаватель — распознаватель, у которого время принятия решения о принадлежности цепочки языку имеет линейную зависимость от длины цепочки. Синтаксические конструкции практически всех существующих языков программирования могут быть отнесены к одному из таких классов языков. Это обстоятельство очень важно для разработки современных быстродействующих компиляторов. Поэтому в главе, посвященной КС-языкам, в первую очередь будет уделено внимание именно таким классам этих языков.

Тем не менее, следует помнить, что только синтаксические конструкции языков программирования допускают разбор с помощью распознавателей КС-языков. Сами языки программирования, как уже было сказано, не могут быть полностью отнесены к типу КС-языков, поскольку предполагают некоторую контекстную зависимость в тексте исходной программы (например, такую, как необходимость предварительного описания переменных). Поэтому кроме синтаксического разбора практически все компиляторы предполагают дополнительный семантический анализ текста исходной программы. Этого можно было бы избежать, если построить компилятор на основе контекстно-зависимого распознавателя, но скорость работы такого компилятора была бы недопустима низка, поскольку время разбора в таком варианте будет экспоненциально зависеть от длины исходной программы. Комбинация из распознавателя КС-языка и дополнительного семантического анализатора является более эффективной с точки зрения скорости разбора исходной программы.

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

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

В компиляторах распознаватели на основе регулярных языков используются для лексического анализа текста исходной программы — выделения в нем простейших конструкций языка, таких как идентификаторы, строки, константы и т. п. Это позволяет существенно сократить объем исходной информации и упрощает синтаксический разбор программы. Более подробно взаимодействие лексического и синтаксического анализаторов текста программы рассмотрено дальше, в главе, посвященной структуре компилятора. На основе распознавателей регулярных языков функционируют ассемблеры — компиляторы с языков ассемблера (мнемокода) в язык машинных команд.

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

 

 

Леволинейные и праволинейные грамматики. Автоматные грамматики

 

К регулярным, как уже было сказано, относятся два типа грамматик: леволинейные и праволинейные.

Леволинейные грамматики G(VT,VN,P,S), V = VNÈVT могут иметь правила двух видов: А®Вg или А®g, где А,ВÎ VN, VT*.

В свою очередь, праволинейные грамматики G(VT,VN,P,S), V = VNÈVT могут иметь правила также двух видов: А® g В или А®g, где А,ВÎ VN, VT*.

Доказано, что эти два класса грамматик эквивалентны. Для любого регулярного языка, заданного праволинейной грамматикой, может быть построена леволинейная грамматика, определяющая эквивалентный язык; и наоборот — для любого регулярного языка, заданного леволинейной грамматикой, может быть построена праволинейная грамматика, задающая эквивалентный язык.

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

Среди всех регулярных грамматик можно выделить отдельный класс — автоматные грамматики. Они также могут быть леволинейными и праволинейными.

Леволинейные автоматные грамматики G(VT,VN,P,S), V = VNÈVT могут иметь правила двух видов: A®Bt или A®t, где A,BÎVN, tÎVT.

Праволинейные автоматные грамматики G(VT,VN,P,S), V = VNÈVT могут иметь правила двух видов: A®tB или A®t, где A,BÎVN, tÎVT.

Разница между автоматными грамматиками и обычными регулярными грамматиками заключается в следующем: там, где в правилах обычных регулярных

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

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

Чтобы классы автоматных и регулярных грамматик были полностью эквивалентны, в автоматных грамматиках разрешается дополнительное правило вида S®l, где S — целевой символ грамматики. При этом символ S не должен встречаться в правых частях других правил грамматики. Тогда язык, заданный автоматной грамматикой G, может включать в себя пустую цепочку: L(G). В таком случае автоматные леволинейные и праволинейные грамматики, так же как обычные леволинейные и праволинейные грамматики, задают регулярные языки. Поскольку реально используемые языки, как правило, не содержат пустую цепочку символов, разница на пустую цепочку между этими двумя типами грамматик значения не имеет и правила вида S®l далее рассматриваться не будут.

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

 

Алгоритм преобразования регулярной грамматики к автоматному виду

 

Имеется регулярная грамматика G(VT,VN,P,S), необходимо преобразовать её в почти эквивалентную автоматную грамматику G'(VT,VN',P',S'). Для определенности будем рассматривать леволинейные грамматики, как уже было сказано выше (для праволинейных грамматик можно легко построить аналогичный алгоритм).

Алгоритм преобразования прост и заключается он в следующей последовательности действий:

Шаг 1. Все нетерминальные символы из множества VN грамматики G переносятся во множество VN' грамматики G'.

Шаг 2. Необходимо просматривать все множество правил P грамматики G.

Если встречаются правила вида A®Ba1, A,BÎVN, a1ÎVT или вида A®a1, AÎVN, a1ÎVT, то они переносятся во множество Р' правил грамматики G' без изменений.

Если встречаются правила вида A®Ba1a2...an, n>1, A,BÎVN, "n>i>0: aiÎVT,
то во множество нетерминальных символов
VN' грамматики G' добавляются
символы
At,A2,..,,An-1, а во множество правил Р' грамматики G' добавляются
правила:                                                             ,

A®Аn-1аn

An-1®Аn-2аn-1

¼

A2®А1а2

A1®Bа1

Если встречаются правила вида А®а1а2...аn, n > 1, AÎVN, "n > i > 0: ai ÎVT, то во множество нетерминальных символов VN' грамматики G' добавляются символы А12,...,Аn-1, а во множество правил Р' грамматики G' добавляются правила:

A®Аn-1аn

An-1®Аn-2аn-1

¼

A2®А1а2

A1®а1

Если встречаются правила вида А®В или вида А®l, то они переносятся во множество правил Р' грамматики G' без изменений.

Шаг 3. Просматривается множество правил Р' грамматики G'. В нем ищутся правила вида А®В или вида А®l

Если находится правило вида А®В, то просматривается множество правил Р' грамматики G'. Если в нем присутствует правила вида В®С, В®Са, В®а или В®l, то в него добавляются правила вида А®С, А®Са, А®а и А®l соответственно, "A,B,CÎVN', "aÎVT ' (при этом следует учитывать, что в грамматике не должно быть совпадающих правил, и если какое -то правило уже присутствует в грамматике G', то повторно его туда добавлять не следует). Правило А®В удаляется из множества правил Р'.

Если находится правило вида А®l, то просматривается множество правил Р' грамматики G'. Если в нем присутствует правило вида В®А или В®Аа, то в него добавляются правила вида В®l и В®а соответственно, "A,BÎVN', "aÎVT' (при этом следует учитывать, что в грамматике не должно быть совпадающих правил, и если какое-то правило уже присутствует в грамматике G', то повторно его туда добавлять не следует). Правило А®l удаляется из множества правил Р'.

Шаг 4. Если на шаге 3 было найдено хотя бы одно правило вида А®В или А®l во множестве правил Р' грамматики G', то надо повторить шаг 3, иначе перейти к шагу 5.

Шаг 5. Целевым символом S' грамматики G' становится символ S.

Шаги 3 и 4 алгоритма в принципе можно не выполнять, если грамматика не содержит правил вида А®В (такие правила называются цепными) или вида А®l (такие правила называются l-правилами). Реальные регулярные грамматики обычно не содержат правил такого вида. Тогда алгоритм преобразования грамматики к автоматному виду существенно упрощается. Кроме того, эти правила можно было бы устранить предварительно с помощью специальных алгоритмов преобразования

 

 

Определение конечного автомата

 

Конечным автоматом (КА) называют пятерку следующего вида:

         M(Q,V,d,q0,F)

где

·                   Q — конечное множество состояний автомата;

·                   V — конечное множество допустимых входных символов (алфавит автомата);

·                   d— функция переходов, отображающая V*Q (декартово произведение множеств) в множество подмножеств Q: R(Q), то есть d(a,q) =R, а Î V, qÎQ, RÍQ;

·                   q0 — начальное состояние автомата Q, qoÎQ;

·                   F — непустое множество конечных состояний автомата, FÍQ, F¹Æ.

КА называют полностью определенным, если в каждом его состоянии существует функция перехода для всех возможных входных символов, то есть "aÎV, "qÎQ $d(a,q)=R, RÍQ, (для всех символов a принадлежащих V и для всех начальных состояний q  принадлежащих Q существует функция переходов d(a,q)=R, для которой состояние R влечет Q).

Работа конечного автомата представляет собой последовательность шагов (или тактов). На каждом шаге работы автомат находится в одном из своих состояний Q (в текущем состоянии), на следующем шаге он может перейти в другое состояние или остаться в текущем состоянии. То, в какое состояние автомат перейдет на следующем шаге работы, определяет функция переходов d. Она зависит не только от текущего состояния, но и от символа из алфавита V, поданного на вход автомата. Когда функция перехода допускает несколько следующих состояний автомата, то КА может перейти в любое из этих состояний. В начале работы автомат всегда находится в начальном состоянии q0. Работа КА продолжается до тех пор, пока на его вход поступают символы из входной цепочки V+.

Видно, что конфигурацию КА на каждом шаге работы можно определить в виде (q,w,n), где q — текущее состояние автомата, qÎQ; w — цепочка входных символов, V+; n — положение указателя в цепочке символов, nÎNÈ{0}, n £ |w| (N — множество натуральных чисел). Конфигурация автомата на следующем шаге — это (q',w,n+l), если q'Îd(a,q) и символ aÎV находится в позиции n+1 цепочки w. Начальная конфигурация автомата: (q0,w);

заключительная конфигурация автомата: (f,w,n), fÎQ,

n =|w| она является конечной конфигурацией, если fÎF,

КА M(Q,V,d,q0,F) принимает цепочку символов V+, если, получив на вход эту цепочку, он из начального состояния q0 может перейти в одно из конечных состоянии fÎF. В противном случае КА не принимает цепочку символов.

Язык L(М), заданный КА M(Q,V,d,q0,F), — это множество всех цепочек символов, которые принимаются этим автоматом. Два КА эквивалентны, если они задают один и тот же язык.

Таким образом, КА является распознавателем для формальных языков. Далее будет показано, что КА — это распознаватели для регулярных языков.

КА часто представляют в виде диаграммы или графа переходов автомата.

Граф переходов КА — это направленный помеченный граф, с символами состояний КА в вершинах, в котором есть дуга (p,q) p,qÎQ, помеченная символом aÎV если в КА определена d(а,р) и qÎd(a,p). Начальное и конечные состояния автомата на графе состояний помечаются специальным образом (в данном пособии начальное состояние — дополнительной пунктирной линией, конечное состояние — дополнительной сплошной линией).

Рассмотрим конечный автомат M({H,A,B,S},{a,b},d,H,{S}); d: d(H,b) = В, d(В,а) = А, d(А,b) = {B,S}.

 

Рис. 6. Граф переходов недетерминированного конечного автомата

 

Для моделирования работы КА его удобно привести к полностью определенному виду, чтобы исключить ситуации, из которых нет переходов по входным символам. Для этого в КА добавляют еще одно состояние, которое можно условно назвать «ошибка». На это состояние замыкают все неопределенные переходы, а все переходы из самого состояния «ошибка» замыкают на него же.

Если преобразовать подобным образом рассмотренный выше автомат М, то получим полностью определенный автомат: M({H,A,B,E,S},{a,b},d,H,{S}); d: d(Н,а)=Е, d(Н,b) = В, d(В,а)=А, d(В,b) = Е, d(А,а)={Е}, d(А,b) = {B,S}, d(Е,a) = {Е}, d(Е,b) = {Е}, d(S,a) - {Е}, d(S,b) = {Е}. Состояние Е как раз соответствует состоянию «ошибка». Граф переходов этого КА представлен на рис. 7.

 

Рис. 7. Граф переходов полностью определенного недетерминированного конечного автомата

 

 

Детерминированные и недетерминированные конечные автоматы

 

Конечный автомат M(Q,V, d,q0,F) называют детерминированным конечным автоматом (ДКА), если в каждом из его состояний для любого входного символа функция перехода содержит не более одного состояния: "aÎV, "qÎQ; либо d(a,q) - {r}, rÎ Q, либо d(a,q) = Æ.

В противном случае конечный автомат называют недетерминированным. ДКА может быть задан в виде пятерки:

M(Q,V,d,qo,F),

где    Q — конечное множество состояний автомата;

V — конечное множество допустимых входных символов;

d — функция переходов, отображающая V*Q в множество Q: d(a,q)=r,

aÎV, q,rÎQ; q0 — начальное состояние автомата Q,

q0ÎQ; F — непустое множество конечных состояний автомата, FÍQ, F=Æ.

Если функция переходов ДКА определена для каждого состояния автомата, то автомат называется полностью определенным ДКА: "aÎV, "qÎQ либо $d(a,q) = r, rÎQ.

Моделировать работу ДКА существенно проще, чем работу произвольного КА.

Доказано, что для любого КА можно построить эквивалентный ему ДКА. Поэтому используемый произвольный КА стремятся преобразовать в ДКА. При построении компиляторов чаще всего используют полностью определенный ДКА.

 

Преобразование конечного автомата к детерминированному виду

 

Алгоритм преобразования произвольного КА M(Q,V,d,q0,F) в эквивалентный ему ДКА M' (Q',V', d',q'0,F'),  заключается в следующем:

1.                 Множество состояний Q' автомата М' строится из комбинаций всех состояний множества Q, автомата М. Если q1,q2,¼,qn, n > 0 — состояния автомата М, "0 < i < n qjÎQ, то всего будет 2n-1 состояний автомата М'. Обозначим их так: [qi,q2,...,qm], 0<m£n.

2.                 Функция переходов d' автомата М' строится так: d'(a,[q1,q2,...,qm]) = [r1,r2,...,rk], где "0< i £ m $0 < j £ k так, что d(a,qj) - rj,

3.                 Обозначим q'0 = [q0];

4.                 Пусть fi,f2,...,fl, l > 0 — конечные состояния автомата М, "0 <i<l fiÎF, тогда множество конечных состояний F' автомата М' строится из всех состояний, имеющих вид [....fj,..], fj ÎF.

Доказано, что описанный выше алгоритм строит ДКА, эквивалентный заданному произвольному КА.

После построения из нового ДКА необходимо удалить все недостижимые состояния.

Состояние qÎQ, в КА M(Q,V, d,q0,F) называется недостижимым, если ни при какой входной цепочке V+ невозможен переход автомата из начального состояния q0 в состояние q. Иначе состояние называется достижимым.

Для работы алгоритма удаления недостижимых состояний используются два множества: множество достижимых состояний R и множество текущих активных состояний на каждом шаге алгоритма Pj. Результатом работы алгоритма является полное множество достижимых состояний R. Рассмотрим работу алгоритма по шагам:

1. R:={q0}; i:=0; Р0:={q0}|

2. Pi+1:=Æ;

3. "aÎV, "qÎPi: Pi+1:=Pi+1Èd(a,q);

4. Если Pi+1-R = Æ, то выполнение алгоритма закончено,

иначе R:=RÈPi+1, i:=i+l и перейти к шагу 3.

После выполнения данного алгоритма из КА можно исключить все состояния, не входящие в построенное множество R.

 

 

Минимизация конечных автоматов

 

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

Для минимизации автомата используется алгоритм построения эквивалентных состояний КА. Два различных состояния в конечном автомате M(Q,V, d,q0,F)

qÎQ и q'ÎQ называются n-эквивалентными (n-неразличимыми), n ³ 0 nÎNÈ{0} если, находясь в одном из этих состояний и получив на вход любую цепочку символов w: V* |w| £n, автомат может перейти в одно и то же множество конечных состояний. Очевидно, что 0-эквивалентными состояниями автомата M(Q,V, d,q0,F) являются два множества его состояний: F и Q-F. Множества эквивалентных состояний автомата называют классами эквивалентности, а всю их совокупность — множеством классов эквивалентности R(n) причем R(0)={F,Q-F}.

Рассмотрим работу алгоритма построения эквивалентных состояний по шагам:

1.                 На первом шаге n:=0 строим R(0).

2.                 На втором шаге n:=n+1 строим R(n) на основе R(n-l): R(n) ={ri(n):      {qij ÎQ;"aÎV d(a,qij)Írj(n-l)} "ijÎN}. To есть в классы эквивалентности на шаге n входят те состояния, которые по одинаковым символам переходят в n-1 эквивалентные состояния.

3.                 Если R(n) - R(n-l), то работа алгоритма закончена, иначе необходимо вернуться к шагу 2.

Доказано, что алгоритм построения множества классов эквивалентности завершится максимум для n=m-2, где m — общее количество состояний автомата.

Алгоритм минимизации КА заключается в следующем:

1.                 Из автомата исключаются все недостижимые состояния.

2.                 Строятся классы эквивалентности автомата.

3.                 Классы эквивалентности состояний исходного КА становятся состояниями результирующего минимизированного КА.

4.                 Функция переходов результирующего КА очевидным образом строится на основе функции переходов исходного КА.

Для этого алгоритма доказано, во-первых, что он строит минимизированный КА, эквивалентный заданному; во-вторых, что он строит КА с минимально возможным числом состояний (минимальный КА).

 

Определение регулярного множества

 

Определим над множествами цепочек символов из алфавита V операции конкатенации и итерации следующим образом:

PQ - конкатенация РÎV* и QÎV*: PQ={pq "pÎP, "qÎQ}

P* - итерация PÎV*: P* ={p* "pÎP}.

Тогда для алфавита V регулярные множества определяются рекурсивно:

1.      Æ — регулярное множество.

2.      {l} — регулярное множество.

3.      {а} — регулярное множество "aÎV.

4. Если Р и Q— произвольные регулярные множества, то множества PÈQ, PQ и Р* также являются регулярными множествами.

5. Ничто другое не является регулярным множеством.

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

 

Регулярные выражения. Свойства регулярных выражений

 

Регулярные множества можно обозначать с помощью регулярных выражений. Эти обозначения вводятся следующим образом:

1. 0 — регулярное выражение, обозначающее Æ.

2. l — регулярное выражение, обозначающее {l}.

3. а — регулярное выражение, обозначающее {a} "aÎV.

4. Если P и Q — регулярные выражения, обозначающие регулярные множества P и Q, то p+q, pq, p* — регулярные выражения, обозначающие регулярные  множества PÈQ, PQ и Р* соответственно.

Два регулярных выражения a и b равны, a=b, если они обозначают одно и то же множество.

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

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

Если a, b и g — регулярные выражения, то свойства регулярных выражений можно записать в виде следующих формул:

 

Три способа задания регулярных языков

 

Регулярные (праволинейные и леволинейные) грамматики, конечные автоматы (КА) и регулярные множества (равно как и обозначающие их регулярные выражения) — это три различных способа, с помощью которых можно задавать регулярные языки. Регулярные языки в принципе можно определять и другими способами, но именно три указанных способа представляют наибольший интерес.

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

Утверждение 1. Язык является регулярным множеством тогда и только тогда, когда он задан леволинейной (праволинейной) грамматикой.

Утверждение 2. Язык может быть задан леволинейной (праволинейной) грамматикой тогда и только тогда, когда он является регулярным множеством.

Утверждение 3. Язык является регулярным множеством тогда и только тогда, когда он задан с помощью конечного автомата.

Утверждение 4. Язык распознается с помощью конечного автомата тогда и только тогда, когда он является регулярным множеством.

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

 

 

 

Связь регулярных выражений и регулярных грамматик

 

Регулярные выражения и регулярные грамматики связаны между собой следующим образом:

·                   для любого регулярного языка, заданного регулярным выражением, можно построить регулярную грамматику, определяющую тот же язык;

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

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

 

 

 

Построение конечного автомата для языка, заданного регулярным выражением

 

Регулярные множества (и обозначающие их регулярные выражения) заданы с помощью рекурсивного определения. Будем строить КА для регулярного выражения над алфавитом V, следуя шагам этого определения.

1. Для регулярного выражения Æ построим КА M(Q={H,F},V,S,H,{F}), у которого функция переходов "qÎQ, "aÎV имеет вид d(q,a) = Æ.

2. Для регулярного выражения l построим КА M(Q={F},V,d,F,{F}), у которого функция переходов "aÎV имеет вид d(F,a) =Æ, а множество конечных состояний содержит только начальное состояние.

3. Для регулярного выражения aÎV построим КА M(Q= {H,F},V,d,H,{F}), с функцией переходов d(Н,а) = {F}.

4. Имеем регулярные выражения a и b, заданные ими языки L2 и L2, а также соответствующие им КА M1(Q1,V,d1,q1,F1) и M2(Q2,V,d2,q2,F2): L1= L(M1) и L2 = L(M2). Необходимо на основе этих данных построить КА для языков, заданных выражениями a+b (L3 = L1 ÈL2), ab (L4 = L1 L2) и a* (L5 = L1*).

для языка, заданного выражением a+b, строим КА М3(Q3,V,d3,q3,F3): Q3= Q1 ÈQ2 È{q3} (множество состояний М3 строится из множеств состояний М1 и М2 с добавлением нового состояния q3),

d3(q3,а) = d1(q1,a) È d2(q2,a) "aÎV,

d3(q,a)= d(q,a) "aÎV "qÎQ1,

d3(q,a) = d2(q,a) "aÎV "qÎQ2

F3 = F1 È F2 È {q3}, если a+b содержит l или F3 = F1 È F2, если a+b не содержит l, начальным состоянием КА М3 становится состояние q3;

для языка, заданного выражением ab, строим КА М4(Q4,V,d4,q4,F4): Q4= Q1 ÈQ2 (множество состояний М4 строится из множеств состояний М1и М2),

d4(q,а) = d1(q,a) "aÎV, "qÎ(Q1/F1),

d4(q,a)= d1(q,a) Èd2(q2,a) "aÎV "qÎF1,

d4(q,a) = d2(q,a) "aÎV "qÎQ2

F4 = F2, если q2ÏF2 или F4 = F1 È F2, если q2ÎF2,

начальным состоянием КА М3 становится начальное состояние КА

М1q1;

для языка, заданного выражением a*, строим КА М5(Q5,V,d5,q5,F5): Q5= Q1 È {q5} (множество состояний М5 строится из множества состояний М1 с добавлением нового состояния q5),

d5(q,а) = d1(q,a) "aÎV, "qÎ(Q1/F1),

d5(q,a)= d1(q,a) Èd1(q1,a) "aÎV "qÎF1,

d5(q5,a) = d1(q1,a) "aÎV

F5 = F1 È {q5},

начальным состоянием КА М5 становится состояние q5.

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

Построение КА на основе регулярного выражения выполняется аналогично построению леволинейной грамматики.

 

 

Построение леволинейной грамматики на основе конечного автомата

 

Имеется конечный автомат M(Q,V,d,q0,F), необходимо построить эквивалентную ему леволинейную грамматику G(VT,VN,P,S).

Построение выполняется по следующему алгоритму.

Шаг 1. Множество терминальных символов грамматики G строится из алфавита входных символов автомата М: VT = V.

Шаг 2. Множество нетерминальных символов грамматики G строится на основании множества состояний автомата М таким образом, чтобы каждому состоянию автомата, за исключением начального состояния, соответствовал один нетерминальный символ грамматики: VN = Q\{qo}.

Шаг 3. Просматриваем функцию переходов автомата М для всех возможных состояний из множества Q для всех возможных входных символов из множества V.

Если имеем d(A,t) = Æ, то ничего не выполняем.

Если имеем d(A,t) = {B1,B2,...,Bn}, n >0, где AÎQ, " n³i>0: B1ÎQ, tÎV, тогда для всех состояний Bi выполняем следующее:

·                    добавляем правило Bi®t во множество Р правил грамматики G, если А =q0;

·                    добавляем правило Bi®At во множество Р правил грамматики G, если A¹q0.

Шаг 4. Если множество конечных состояний F автомата М содержит только одно состояние F - {F0}, то целевым символом S грамматики G становится символ множества VN, соответствующий этому состоянию: S = F0; иначе, если множество конечных состояний F автомата М содержит более одного состояния F = {F1, F2,...,Fn}, n>1, тогда во множество нетерминальных символов VN грамматики G добавляется новый нетерминальный символ S:

VN =VNÈ{S}, а во множество правил Р грамматики G добавляются правила: S®F1|F2|...|Fn.

На этом построение грамматики заканчивается.

 

 

Свойства регулярных языков

 

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

Регулярные множества (и однозначно связанные с ними регулярные языки) замкнуты относительно многих операций, которые применимы к цепочкам символов.

Например, регулярные языки замкнуты относительно следующих операций:  пересечения;  объединения; дополнения;  итерации;   конкатенации;  гомоморфизма (изменения имен символов и подстановки цепочек вместо символов).

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

Регулярные языки представляют собой очень удобный тип языков. Для них разрешимы многие проблемы, неразрешимые для других типов языков.

Например, доказано, что разрешимыми являются следующие проблемы.

Проблема эквивалентности. Даны два регулярных языка L1(V) и L2(V). Необходимо проверить, являются ли эти два языка эквивалентными.

Проблема принадлежности цепочки языку. Дан регулярный язык L(V) и цепочка символов V*. Необходимо проверить, принадлежит ли цепочка данному языку.

Проблема пустоты языка. Дан регулярный язык L(V). Необходимо проверить, является ли этот язык пустым, то есть найти хотя бы одну цепочку a¹l, такую что L(V).

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

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

 

 

Построение конечного автомата для языка, заданного регулярным выражением

 

Регулярные множества (и обозначающие их регулярные выражения) заданы с помощью рекурсивного определения. Будем строить КА для регулярного выражения над алфавитом V, следуя шагам этого определения.

1. Для регулярного выражения Æ построим КА M(Q={H,F},V,S,H,{F}), у которого функция переходов "qÎQ, "aÎV имеет вид d(q,a) = Æ.

2. Для регулярного выражения l построим КА M(Q={F},V,d,F,{F}), у которого функция переходов "aÎV имеет вид d(F,a) =Æ, а множество конечных состояний содержит только начальное состояние.

3. Для регулярного выражения aÎV построим КА M(Q= {H,F},V,d,H,{F}), с функцией переходов d(Н,а) = {F}.

4. Имеем регулярные выражения a и b, заданные ими языки L2 и L2, а также соответствующие им КА M1(Q1,V,d1,q1,F1) и M2(Q2,V,d2,q2,F2): L1= L(M1) и L2 = L(M2). Необходимо на основе этих данных построить КА для языков, заданных выражениями a+b (L3 = L1 ÈL2), ab (L4 = L1 L2) и a* (L5 = L1*).

для языка, заданного выражением a+b, строим КА М3(Q3,V,d3,q3,F3): Q3= Q1 ÈQ2 È{q3} (множество состояний М3 строится из множеств состояний М1 и М2 с добавлением нового состояния q3),

d3(q3,а) = d1(q1,a) È d2(q2,a) "aÎV,

d3(q,a)= d(q,a) "aÎV "qÎQ1,

d3(q,a) = d2(q,a) "aÎV "qÎQ2

F3 = F1 È F2 È {q3}, если a+b содержит l или F3 = F1 È F2, если a+b не содержит l, начальным состоянием КА М3 становится состояние q3;

для языка, заданного выражением ab, строим КА М4(Q4,V,d4,q4,F4): Q4= Q1 ÈQ2 (множество состояний М4 строится из множеств состояний М1и М2),

d4(q,а) = d1(q,a) "aÎV, "qÎ(Q1/F1),

d4(q,a)= d1(q,a) Èd2(q2,a) "aÎV "qÎF1,

d4(q,a) = d2(q,a) "aÎV "qÎQ2

F4 = F2, если q2ÏF2 или F4 = F1 È F2, если q2ÎF2,

начальным состоянием КА М3 становится начальное состояние КА

М1q1;

для языка, заданного выражением a*, строим КА М5(Q5,V,d5,q5,F5): Q5= Q1 È {q5} (множество состояний М5 строится из множества состояний М1 с добавлением нового состояния q5),

d5(q,а) = d1(q,a) "aÎV, "qÎ(Q1/F1),

d5(q,a)= d1(q,a) Èd1(q1,a) "aÎV "qÎF1,

d5(q5,a) = d1(q1,a) "aÎV

F5 = F1 È {q5},

начальным состоянием КА М5 становится состояние q5.

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

Построение КА на основе регулярного выражения выполняется аналогично построению леволинейной грамматики.

 

 

Определение МП-автомата

 

Контекстно-свободными (КС) называются языки, определяемые грамматиками типа G(VT,VN,P,S), в которых правила Р имеют вид: А®b, где AÎVN и V*, V=VTÈVN.

Распознавателями КС-языков служат автоматы с магазинной памятью (МП-автоматы).

В общем виде МП-автомат можно определить следующим образом: R(Q,V,Z,d,qo,z0,F),

где Q — множество состояний автомата;

V — алфавит входных символов автомата;

Z — специальный конечный алфавит магазинных символов автомата (обычно он включает в себя алфавиты терминальных и нетерминальных символов грамматики), VÍZ;

d — функция переходов автомата, которая отображает множество Q´(VÈ{l})´Z на конечное множество подмножеств P(Q´Z*);

qoÎQ— начальное состояние автомата;

z0ÎZ — начальный символ магазина;

FÍQ — множество конечных состояний.

МП-автомат в отличие от обычного КА имеет стек (магазин), в который можно помещать специальные «магазинные» символы (обычно это терминальные и нетерминальные символы грамматики языка). Переход из одного состояния в другое зависит не только от входного символа, но и от одного или нескольких верхних символов стека. Таким образом, конфигурация автомата определяется тремя параметрами: состоянием автомата, текущим символом входной цепочки (положением указателя в цепочке) и содержимым стека.

МП-автомат условно можно представить в виде схемы на рис. 12.

 

Рис. 12. Общая условная схема автомата с магазинной памятью (МП-автомата)

Конфигурация МП-автомата описывается в виде тройки (q,a,w)ÎQ´V*´Z*, которая определяет текущее состояние автомата q, цепочку еще непрочитанных символов a на входе автомата и содержимое магазина (стека) w. Вместо а в конфигурации можно указать пару (b,n), где V* — вся цепочка входных символов, а nÎNÈ{0}, n ³ 0 — положение считывающего указателя в цепочке.

Тогда один такт работы автомата можно описать в виде (q,aa,zw) ¸ (q',a,gw), если (q',g)Îd(q,a,z), где q,q'ÎQ, aÎVÈ{l}, V*, zÎZÈ{l}, g,Z*. При выполнении такта (перехода) из стека удаляется верхний символ, соответствующий условию перехода, и добавляется цепочка, соответствующая правилу перехода. Первый символ цепочки становится верхушкой стека. Допускаются переходы, при которых входной символ игнорируется (и тем самым он будет входным символом при следующем переходе). Эти переходы (такты) называются l-переходами (l-тактами). Аналогично, автомат не обязательно должен извлекать символ из стека — когда z=l, этого не происходит.

МП-автомат называется недетерминированным, если из одной и той же его конфигурации возможен более чем один переход.

Начальная конфигурация МП-автомата, очевидно, определяется как (q0,a,z0), V*. Множество конечных конфигураций автомата — (q,l,w), qÎF, Z*.

МП-автомат допускает (принимает) цепочку символов, если, получив эту цепочку на вход, он может перейти в одну из конечных конфигураций, — когда при окончании цепочки автомат находится в одном из конечных состояний, а стек содержит некоторую определенную цепочку. Тогда входная цепочка принимается (после окончания цепочки автомат может сделать произвольное количество l-переходов). Иначе цепочка символов не принимается.

Язык, определяемый МП-автоматом, — это множество всех цепочек символов, которые допускает данный автомат. Язык, определяемый МП-автоматом R, обозначается как L(R). Два МП-автомата называются эквивалентными, если они определяют один и тот же язык. Если два МП-автомата R1 и R2 определяют один н тот же язык, это записывается как L(R1) = L(R2)

МП-автомат допускает цепочку символов с опустошением магазина, если при окончании разбора цепочки автомат находится в одном из конечных состояний, а стек пуст - конфигурация (q,l,l), qÎF. Если язык задан МП-автоматом R, который допускает цепочки с опустошением стека, это обозначается так: Ll(R). Для любого МП-автомата всегда можно построить эквивалентный ему МП-автомат, допускающий цепочки заданного языка с опустошением стека. То есть " МП-автомата R: $ МП-автомат R', такой что L(R) = Ll(R').

Кроме обычного МП-автомата существует также понятие расширенного МП-автомата.

Расширенный МП-автомат может заменять цепочку символов конечной длины в верхней части стека на другую цепочку символов конечной длины. В отличие от обычного МП-автомата, который на каждом такте работы может изымать из стека только один символ, расширенный МП-автомат может изымать за один такт сразу некоторую цепочку символов, находящуюся на вершине стека. Функция переходов d для расширенного МП-автомата отображает множество Q´(VÈ{l})´Z* на конечное множество подмножеств P(Q´Z').

Доказано, что для любого расширенного МП-автомата всегда можно построить эквивалентный ему обычный МП-автомат (обратное утверждение очевидно, так как любой обычный МП-автомат является и расширенным МП-автоматом). Таким образом, классы МП-автоматов и расширенных МП-автоматов эквивалентны и задают один и тот же тип языков.

 

 

 

Детерминированные МП-автоматы

 

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

Формально для детерминированного МП-автомата R(Q,V,Z,d,q0,z0,F) функция переходов d для "qÎQ, "aÎV, "zÎZ может иметь один из следующих трех видов:

1. d(q,a,z) содержит один элемент: d(q,a,z) - {(q',g)}, Z* и d(q,l,z) =Æ.

2. d(q,a,z) - Æ и d(q,l,z) содержит один элемент: d(q,l,z) - {(q',g)}, Z*.

3. d(q,a,z) - Æ и d(q,l,z) =Æ.

Класс ДМП-автоматов и соответствующих им языков значительно уже, чем весь класс МП-автоматов и КС-языков. В отличие от обычного конечного автомата, не для каждого МП-автомата можно построить эквивалентный ему ДМП-автомат. Иными словами, в общем случае невозможно преобразовать недетерминированный МП-автомат в детерминированный.

Детерминированные МП-автоматы (ДМП-автоматы) определяют очень важный класс среди всех КС-языков, называемый детерминированными КС-языками. Доказано, что все языки, принадлежащие к классу детерминированных КС-языков, могут быть построены с помощью однозначных КС-грамматик. Поскольку однозначность — это важное и обязательное требование в грамматике любого языка программирования, ДМП-автоматы представляют особый интерес для создания компиляторов. Синтаксический распознаватель цепочек любого языка программирования может быть построен на основе ДМП-автомата.

Кроме того, доказано, что для любого ДМП-автомата всегда можно построить эквивалентный ему ДМП-автомат, который будет учитывать входную цепочку до конца — не допускать бесконечной последовательности  l-переходов по завершении цепочки. Это значительно облегчает моделирование работы ДМП-автоматов.

Все без исключения синтаксические конструкции языков программирования задаются с помощью однозначных КС-грамматик (неоднозначность, конечно же, ни в одном компиляторе недопустима). Синтаксические структуры этих языков относятся к классу детерминированных КС-языков и могут распознаваться с помощью ДМП-автоматов. Поэтому большинство распознавателей, которые будут рассмотрены далее, относятся к классу детерминированных КС-языков.

 

 

Свойства произвольных КС-языков

 

Класс КС-языков замкнут относительно операции подстановки. Это означает, что если в каждую цепочку символов КС-языка вместо некоторого символа подставить цепочку символов из другого КС-языка, то получившаяся новая цепочка также будет принадлежать КС-языку.

Это основное свойство КС-языков. Формально оно может быть записано так. Если L,La1,La2,...,Lan — это произвольные КС-языки и {а12,...,аn} — алфавит языка L, n>0, то тогда язык L' - {x1x2...xk| аj1, аj2,… аjkÎL, x1ÎLaj2,..., хkÎLajk, k > 0: " k ³i > 0: n ³ j i > 0} также является КС-языком.

Например:

L - {0nln | n > 0}, L0= {a}, L1 = {bmcm | m > 0} — это исходные КС-языки, тогда после подстановки получаем новый КС-язык: L' - {anbm1cm1bm2cm2...bmncmn | n > О, "i:mi>0}.

На основе замкнутости относительно операции подстановки можно доказать другие свойства КС-языков. В частности, класс КС-языков замкнут относительно следующих четырех операций:  объединения;  конкатенации;   итерации;  гомоморфизма (изменения имен символов).

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

Например:

L1= {anbnci | n>0, i>0} и L2 - {аibnсn | n>0, i>0} - КС-языки, но L = LtÇL2 = {anbncn | n>0} не является КС-языком (это можно проверить с помощью леммы о разрастании КС-языков, которая рассмотрена ниже).

Для КС-языков разрешимы проблема пустоты языка и проблема принадлежности заданной цепочки языку — для их решения достаточно построить МП-автомат, распознающий данный язык. Но для КС-языков является неразрешимой проблема эквивалентности двух произвольных КС-грамматик, а, как следствие, также и проблема однозначности заданной КС-грамматики. Не разрешима даже более узкая проблема — проблема эквивалентности заданной произвольной КС-грамматики и произвольной регулярной грамматики.

Тем не менее, хотя в общем случае проблема однозначности для КС-языков не разрешима, для некоторых КС-грамматик можно построить эквивалентную им однозначную грамматику.

 

Свойства детерминированных КС-языков

 

Детерминированные КС-языки — это класс тех КС-языков, цепочки которых можно распознавать с помощью ДМП-автоматов. Класс детерминированных КС-языков, естественно, является собственным подмножеством всего класса КС-языков.

Как уже было сказано ранее, детерминированные КС-языки — это значительно более узкий класс, чем все КС-языки. Класс детерминированных КС-языков не замкнут даже относительно операции объединения, равно как и операции пересечения (хотя и замкнут относительно операции дополнения, в отличие от всех КС-языков в целом). Класс детерминированных КС-языков интересен тем, что для него разрешима проблема однозначности. Доказано, что если язык может быть распознан с помощью ДМП-автомата (и потому является детерминированным КС-языком), то он может быть описан на основе однозначной КС-грамматики. Именно поэтому данный класс как раз и используется для построения синтаксических конструкций языков программирования.

Дополнительно следует заметить, что в общем случае подавляющее большинство языков программирования (таких, как Pascal, С, FORTRAN и т. п.) формально не являются КС-языками. Причина в том, что в языках программирования всегда присутствует контекстная зависимость, которая выражается, например, в необходимости предварительного описания переменных, в соответствии количества и типов формальных и фактических параметров процедур и функций и т. п. Но с целью упрощения работы компиляторов подобного рода зависимости на этапе синтаксического анализа не учитывают, рассматривая только сами конструкции языков программирования, которые формально могут быть описаны с помощью КС-грамматик. Соблюдение контекстных условий (зависимостей) в компиляторах проверяется уже на этапе семантического анализа при подготовке к генерации

 

Преобразование грамматик. Цель преобразования

 

Как было сказано выше, для КС-грамматик невозможно в общем случае проверить их однозначность и эквивалентность. Но очень часто правила КС-грамматик можно и нужно преобразовать к некоторому заранее заданному виду таким образом, чтобы получить новую грамматику, эквивалентную исходной. Заранее определенный вид правил грамматики позволяет упростить работу с языком, заданным этой грамматикой, и облегчает создание распознавателей для него.

Таким образом, можно выделить две основные цели преобразований КС-грамматик: упрощение правил грамматики и облегчение создания распознавателя языка. Не всегда эти две цели можно совместить. В случае с языками программирования, когда итогом работы с грамматикой является создание компилятора языка, именно вторая цель преобразования является основной. Поэтому упрощениями правил пренебрегают, если при этом удается упростить построение распознавателя языка.

Все преобразования условно можно разбить на две группы:

     первая группа — это преобразования, связанные с исключением из грамматики тех правил и символов, без которых она может существовать (именно эти преобразования позволяют выполнить основные упрощения правил);

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

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

Тогда формально преобразование можно определить следующим образом: G(VT,VN,P,S) ® G'(VT',VN',P',S'): L(G) = L(G')

 

 

Пpинципы paбoты pacпoзнaвaтeлeй c вoзвpaтoм

 

Pacпoзнaвaтeли c вoзвpaтoм — этo caмый пpимитивный тип pacпoзнaвaтeлeй для KC-языкoв. Лoгикa иx paбoты ocнoвaнa нa мoдeлиpoвaнии нeдeтepминиpoвaннoгo MП-aвтoмaтa.

Пocкoлькy мoдeлиpyeтcя нeдeтepминиpoвaнный MП-aвтoмaт (кoтopый в oбщeм видe нe пpeoбpaзyeтcя в дeтepминиpoвaнный), тo нa нeкoтopoм шaгe paбoты мoдeлиpyющeгo aлгopитмa вoзмoжнo вoзникнoвeниe нecкoлькиx дoпycтимыx cлeдyющиx cocтoяний aвтoмaтa. B тaкoм cлyчae cyщecтвyют двa вapиaнтa peaлизaции aлгopитмa.

B пepвoм вapиaнтe нa кaждoм шaгe paбoты aлгopитм дoлжeн зaцoминaть вce вoзмoжныe cлeдyющиe cocтoяния MП-aвтoмaтa, выбиpaть oднo из ниx, пepexoдить в этo cocтoяниe и дeйcтвoвaть тaк дo тex пop, пoкa либo нe бyдeт дocтигнyтo кoнeчнoe cocтoяниe aвтoмaтa, либo aвтoмaт нe пepeйдeт в тaкyю кoнфигypaцию, кoгдa cлeдyющee cocтoяниe бyдeт нe oпpeдeлeнo. Ecли дocтигнyтo oднo из кoнeчныx cocтoяний — вxoднaя цeпoчкa пpинятa, paбoтa aлгopитмa зaвepшaeтcя. B пpoтивнoм cлyчae aлгopитм дoлжeн вepнyть aвтoмaт нa нecкoлькo шaгoв нaзaд, кoгдa eщe был вoзмoжeн выбop oднoгo из нaбopa cлeдyющиx cocтoяний, выбpaть дpyгoй вapиaнт и пpoмoдeлиpoвaть пoвeдeниe aвтoмaтa c этим ycлoвиeм. Aлгopитм зaвepшaeтcя c oшибкoй, кoгдa вce вoзмoжныe вapиaнты paбoты aвтoмaтa бyдyт пepeбpaны и ни oднo из вoзмoжныx кoнeчныx cocтoяний нe былo дocтигнyтo.

Bo втopoм вapиaнтe aлгopитм мoдeлиpoвaния MП-aвтoмaтa дoлжeн нa кaждoм шaгe paбoты пpи вoзникнoвeнии нeoднoзнaчнocти c нecкoлькими вoзмoжными cлeдyющими cocтoяниями aвтoмaтa зaпycкaть нoвyю cвoю кoпию для oбpaбoтки кaждoгo из этиx cocтoяний. Aлгopитм зaвepшaeтcя, ecли xoтя бы oднa из выпoлняющиxcя eгo кoпий дocтигaeт oднo из кoнeчныx cocтoяний. Пpи этoм paбoтa вcex ocтaльныx кoпий aлгopитмa пpeкpaщaeтcя. Ecли ни oднa из кoпий aлгopитмa нe дocтиглa кoнeчнoгo cocтoяния MП-aвтoмaтa, тo aлгopитм зaвepшaercя c oшибкoй.

Bтopoй вapиaнт peaлизaции aлropитмa cвязaн c yпpaвлeниeм пapaллeльными пpoцeccaми в вычиcлитeльныx cиcтeмax, пoэтoмy cлoжeн в peaлизaции. Kpoмe тoгo, нa кaждoм шaгe paбoты MП-aвтoмaтa aльтepнaтив cлeдyющиx cocтoяний мoжeт быть мнoгo, a кoличecтвo вoзмoжныx пapaллeльнo выпoлняющиxcя пpoцeccoв в oпepaциoнныx cиcтeмax oгpaничeнo, пoэтoмy пpимeнeниe втopoгo вapиaнтa aлгopитмa ocлoжнeнo. Пo этим пpичинaм бoльшee pacпpocтpaнeниe пoлyчил пepвый вapиaнт aлгopитмa, кoтopый пpeдycмaтpивaeт вoзвpaт к paнee зaпoмнeнным cocтoяниям MП-aвтoмaтa — oтcюдa и нaзвaниe «paзбop c вoзвpaтaми». Cлeдyeт oтмeтить, чтo, xoтя MП-aвтoмaт являeтcя oднocтopoнним paeпoзнaвaтeлeм, aлгopитм мoдeлиpoвaния eгo paбoты пpeдycмaтpивaeт вoзвpaт нaзад, к yжe пpoчитaннoй чacти цeпoчки cимвoлoв, чтoбы иcключить нeдeтepминизм в пoвeдeнии aвтoмaтa (кoтopый нeвoзмoжнo пpoмoдeлиpoвaть).

Ecть eщe oднa ocoбeннocть в мoдeлиpoвaнии MП-aвтoмaтa: любoй пpaктичecки цeнный aлгopитм дoлжeн зaвepшaтьcя зa кoнeчнoe чиcлo шaгoв (ycпeшнo или нeycпeшнo). Aлгopитм мoдeлиpoвaния paбoты пpoизвoльнoгo MП-aвтoмaтa в oбщeм cлyчae нe yдoвлeтвopяeт этoмy yeлoвию. Haпpимep, дaжe пocлe cчитывaния вceй вxoднoй цeпoчки cимвoлoв MП-aвтoмaт мoжeт coвepшить пpoизвoльнoe (в тoм чиcлe и бecкoнeчнoe) чиcлo l-пepexoдoв. B тoм cлyчae, ecли цeпoчкa нe пpинятa, этo мoжeт пpивecти к бecкoнeчнoмy кoличecтвy шaгoв мoдeлиpyющeгo aлгopитмa, кoтopый пo этoй пpичинe никoгдa нe бyдeт зaкoнчeн.

Чтoбы избeжaть тaкиx cитyaций, aлгopитмы paзбopa c вoзвpaтaми cтpoят нe для пpoизвoльныx MП-aвтoмaтoв, a для MП-aвтoмaтoв, yдoвлeтвopяющим нeкoтopым зaдaнным ycлoвиям. Kaк пpaвилo, эти ycлoвия cвязaны c тeм, чтo MП-aвтoмaт дoлжeн cтpoитьcя нa ocнoвe гpaммaтики зaдaннoгo языкa тoлькo пocлe тoгo, кaк oнa пoдвepгнeтcя нeкoтopым пpeoбpaзoвaниям. Пocкoлькy пpeoбpaзoвaния гpaммaтик caми пo ceбe нe нaклaдывaют кaкиx-либo oгpaничeний нa вxoднoй клacc KC-языкoв (в peзyльтaтe пpeoбpaзoвaния мы вceгдa пoлyчaeм эквивaлeнтнyю гpaммaтикy), тo oни и нe oгpaничивaют пpимeнимocти aлгopитмoв paзбopa c вoзвpaтaми — эти aлгopитмы пpимeнимы для любoгo KC-языкa, зaдaннoгo пpoизвoльнoй KC-гpaммaтикoй или MП-aвтoмaтoм.

Aлгopитмы paзбopa c вoзвpaтaми oблaдaют экcпoнeнциaльными xapaктepиcтикaми. Этo знaчит, чтo вычиcлитeльныe зaтpaты aлгopитмoв экcпoнeнциaльнo зaвиcят oт длины вxoднoй цeпoчки cимвoлoв: a, VT*, n = |a|. Koнкpeтнaя зaвиcимocть oпpeдeляeтcя вapиaнтoм peaлизaции aлгopитмa.

Дoкaзaнo, чтo в oбщeм cлyчae пpи пepвoм вapиaнтe peaлизaции для пpoизвoль-нoй KC-гpaммaтики G(VT,VN,P,S) вpeмя выпoлнeния дaннoгo aлгopитмa Tэ бyдeт имeть экcпoнeнциaльнyю зaвиcимocть oт длины вxoднoй цeпoчки, a нeoбxoдимый oбъeм пaмяти Mэ — линeйнyю зaвиcимocть oт длины вxoднoй цeпoчки: Tэ = O(en) и Mэ = O(n). Пpи втopoм вapиaнтe peaлизaции, нaoбopoт, вpeмя выпoлнeния дaннoгo aлгopитмa Tэ бyдeт имeть линeйнyю зaвиcимocть oт длины вxoднoй цeпoчки, a нeoбxoдимый oбъeм пaмяти Mэ — экcпoнeнциaльнyю зaвиcимocть oт длины вxoднoй цeпoчки: Tэ =O(n) и

Mэ =O(en).

Экcпoнeнциaльнaя зaвиcимocть вычиcлитeльныx зaтpaт oт длины вxoднoй цeпoчки cyщecтвeннo oгpaничивaeт пpимeнимocть aлгopитмoв paзбopa c вoзвpaтaми. Oни тpивиaльны в peaлизaции, нo имeют нeyдoвлeтвopитeльныe xapaктepиcтики, пoэтoмy мoгyт иcпoльзoвaтьcя тoлькo для пpocтыx KC-языкoв c мaлoй длинoй вxoдныx пpeдлoжeний языкa. Для мнoгиx клaccoв KC-языкoв cyщecтвyют бoлee эффeктивныe aлгopитмы pacпoзнaвaния, пoэтoмy aлгopитмы paзбopa c вoзвpaтaми пpимeняютcя peдкo.

Дaлee paccмoтpeны двa ocнoвныx вapиaнтa тaкиx aлropитмoв.

 

 

 

 

 

Hиcxoдящий pacпoзнaвaтeль c вoзвpaтoм

 

Этoт pacпoзнaвaтeль мoдeлиpyeт paбoтy MП-aвтoмaтa c oдним cocтoяниeм q:R({q},V,Z,δ,q,S,{q}). Aвтoмaт pacпoзнaeт цeпoчки KC-языкa, зaдaннoгo KC-гpaммaтикoй G(VT,VN,P,S). Bxoднoй aлфaвит aвтoмaтa coдepжит тepминaльныe cимвoлы rpaммaтики: V = VT, a aлфaвит мaгaзинныx cимвoлoв cтpoитcя из тepминaльныx и нeтepминaльныx cимвoлoв гpaммaтики: Z =VTÈVN.

Haчaльнaя кoнфигypaция aвтoмaтa oпpeдeляeтcя тaк: (q,α,S) — aвтoмaт пpeбывaeт в cвoeм eдинcтвeннoм cocтoянии q, cчитывaющaя гoлoвкa нaxoдитcя в нaчaлe вxoднoй цeпoчки cимвoлoв αÎVT*, в cтeкe лeжит cимвoл, cooтвeтcтвyющий цeлeвoмy cимвoлy гpaммaтики S.

Koнeчнaя кoнфигypaция aвтoмaтa oпpeдeляeтcя тaк: (q,λ,λ) — aвтoмaт пpeбывaeт в cвoeм eдинcтвeннoм cocтoянии q, cчитывaющaя гoлoвкa нaxoдитcя зa кoнцoм вxoднoй цeпoчки cимвoлoв, cтeк пycт.

Фyнкция пepexoдoв MП-aвтoмaтa cτpoитcя нa ocнoвe пpaвил гpaммaтики:

1. (q,α)Îδ(q,λ,A), AÎVN, (VTÈVN)*, ecли пpaвилo A→α coдepжитcя вo мнo-жecтвe пpaвил P гpaммaтики G: A→α Î P.

2. (q,λ)Îδ(q,a,a) "aÎVT.

Этoт MП-aвтoмaт yжe был paccмoтpeн вышe.

Paбoтy дaннoгo MП-aвтoмaтa мoжнo нeфopмaльнo oпиcaть cлeдyющим oбpaзoм: ecли нa вepxyшкe cтeкa aвтoмaтa нaxoдитcя нeтepминaльный cимвoл A, тo eгo мoжнo зaмeнить нa цeпoчкy cимвoлoв α, ecли в гpaммaтикe языкa ecть пpaвилo A®α, нe cдвигaя пpи этoм cчитывaющyю гoлoвкy aвтoмaтa (этoт шaг paбoты нaзывaeтcя «пoдбop aльтepнaтнвы»); ecли жe нa вepxyшкe cтeкa нaxoдитcя тepминaльный cимвoл a, кoтopый coвпaдaeт c тeкyщим cимвoлoм вxoднoй цeпoчки, тo этoт cимвoл мoжнo выбpocить из cтeкa и пepeдвинyть cчитывaющyю гoлoвкy нa oднy пoзицию впpaвo (этoт шaг paбoты нaзывaeтcя «выбpoc»). Дaнный MП-aвтoмaт мoжeт быть нeдeтepминиpoвaнным, пocкoлькy пpи пoдбope aльтepнaтивы в гpaммaтикe языкa мoжeт oкaзaтьcя бoлee oднoгo пpaвилa видa A®α, cлeдoвaтeльнo, тoгдa фyнкция δ(q,λ,A) бyдeт coдepжaть бoлee oднoгo cлeдyющeгo cocтoяния — y aвтoмaтa бyдeт нecкoлькo aльтepнaтив.

Дaнный MП-aвтoмaт cтpoит лeвocтopoнниe вывoды для гpaммaтики G(VT,VN,P,S). Для мoдeлиpoвaния тaкoгo aвтoмaтa нeoбxoдимo, чтoбы гpaммaтикa G(VT,VN,P,S) нe былa лeвopeкypcивнoй (в пpoтивнoм cлyчae, oчeвиднo, aвтoмaт мoжeт вoйти в бecкoнeчный цикл). Пocкoлькy, кaк былo дoкaзaнo вышe, пpoизвoльнyю KC-гρaммaтикy вceгдa мoжнo пpeoбpaзoвaть к нeлeвopeкypcивнoмy видy, тo этoт aлгopитм пpимeним для любoй KC-гpaммaтики, cлeдoвaтeльнo, им мoжнo pacпoзнaвaть цeпoчки любoгo KC-языкa. Paccмoтpeнный MП-aвтoмaт cтpoит лeвocтopoнниe вывoды и читaeт цeпoчкy вxoдныx cимвoлoв cлeвa нaпpaвo. Пoэтoмy для нeгo ecтecтвeнным являeтcя пo-cтpoeниe дepeвa вывoдa cвepxy вниз. Taкoй pacпoзнaвaтeль нaзывaeтcя ниcxoдящим.

Peшeниe o тoм, выпoлнять ли нa кaждoм шaгe paбoты MП-aвтoмaтa выбpoc или пoдбop aльтepнaтивы, пpинимaeтcя oднoзнaчнo. Moдeлиpyющий aлгopитм дoлжeн oбecпeчивaть выбop oднoй из вoзмoжныx aльтepнaтив и xpaнeниe инфopмaции o тoм, кaкиe aльтepнaтивы нa кaкoм шaгe yжe были выбpaны, чтoбы имeть вoзмoжнocть вepнyтьcя к этoмy шaгy и пoдoбpaть дpyгиe aльтepнaтивы. Taкoй aлгopитм paзбopa нaзывaeтcя aлгopитмoм c пoдбopoм aльтepнaтив.

 

 

Pacпoзнaвaтeль нa ocнoвe aлropитмa «cдвиг-cвepтк

 

Этoт pacпoзнaвaтeль cтpoитcя нa ocнoвe pacшиpeннoгo MП-aвтoмaтa c oдним cocтoяниeм q: R({q},V,Z,δ,q,S,{q}). Aвтoмaт pacпoзнaeт цeпoчки KC-языкa, зaдaннoгo KC-гpaммaтикoй G(VT,VN,P,S). Bxoднoй aлфaвит aвтoмaтa coдepжит тepминaльныe cимвoлы гpaммaтики: V=VT; a aлфaвит мaгaзинныx cимвoлoв cтpoитcя из тepминaльныx и нeтepминaльныx cимвoлoв гpaммaтики: Z =VTÈVN.

Haчaльнaя кoнфигypaция aвтoмaтa oпpeдeляeтcя тaк: (q,α,λ) — aвтoмaт пpeбывaeт в cвoeм eдинcтвeннoм cocтoянии q, cчитывaющaя тoлoвкa нaxoдитcя в нaчaлe вxoднoй цeпoчки cимвoлoв αÎVT*, cтeк пycт.

Koнeчнaя кoнфигypaция aвтoмaтa oпpeдeляeтcя тaк: (q,λ,S) — aвтoмaт пpeбывaeт в cвoeм eдинcтвeннoм cocтoянии q, cчитывaющaя гoлoвкa нaxoдитcя зa кoнцoм вxoднoй цeпoчки cимвoлoв, в cтeкe лeжит cимвoл, cooтвeтcтвyющий цeлeвoмy cимвoлy гpaммaтики S.

Фyнкция пepexoдoв MП-aвтoмaтa cтpoитcя нa ocнoвe пpaвил гpaммaтики:

1. (q,A)Îδ(q,λ,γ), AÎVN, γÎ(VTÈVN)*, ecли пpaвилo A→γ coдepжитcя вo мнoжecтвe пpaвил P гpaммaтики G: A→γ Î P.

2. (q,a)Îδ(q,a,λ) "aÎVT.

Heфopмaльнo paбoтy этoгo pacшиpeннoгo aвтoмaтa мoжнo oпиcaть тaк: ecли нa вepxyшкe cтeкa нaxoдитcя цeпoчкa cимвoлoв γ, тo ee мoжнo зaмeнить нa нeтepминaльный cимвoл A, ecли в гpaммaтикe языкa cyщecтвyeт пpaвилo видa A→γ, нe cдвигaя пpи этoм cчитьraaющyю гoлoвкy aвтoмaтa (этoт шaг paбoты нaзывaeтcя «cвepткa»); c дpyгoй cтopoны, ecли cчитывaющaя гoлoвкa aвтoмaтa oбoзpeвaeт нeкoтopый cимвoл вxoднoй цeпoчки a, тo eгo мoжнo пoмecтить в cтeк, cдвинyв пpи этoм гoлoвкy нa oднy пoзицию впpaвo (этoт шaг paбoты нaзывaeтcя «cдвиг» или «пepeнoс). Caм aлropитм, мoдeлиpyющий paбoтy тaкoгo pacшиpeннoгo aвтoмaтa, нaзывaeтcя aлгopитмoм «cдвиг-cвepткили «пepeнoc-cвepткa» (пo нaзвaниям ocнoвныx дeйcтвий aлгopитмa). Дaнный pacшиpeнный MП-aвтoмaт cтpoит пpaвocтopoнниe вывoды для гpaммaтики G(VT,VN,P,S). Для мoдeлиpoвaния тaкoгo aвтoмaтa нeoбxoдимo, чтoбы гpaммaтикa G(VT,VN,P,S) нe coдepжaлa λ-пpaвил и цeпныx пpaвил (в пpoтив-нoм cлyчae, oчeвиднo, aвтoмaт мoжeт вoйти в бecкoнeчный цикл из cвepтoк). Пo-cкoлькy, кaк былo дoкaзaнo вышe, пpoизвoльнyю KC-гpaммaтикy вceгдa мoжнo пpeoбpaзoвaть к видy бeз λ-пpaвил и цeпныx пpaвил, тo этoт aлгopитм пpимeним для любoй KC-гpaммaтики, cлeдoвaтeльнo, им мoжнo pacпoзнaвaть цeпoчки любoгo KC-языкa.

Этoт pacшиpeнный MП-aвтoмaт cтpoит пpaвocтopoнниe вывoды и читaeт цeпoчкy вxoдныx cимвoлoв cлeвa нaпpaвo. Пoэтoмy для нeгo ecтecтвeнным являeтcя пocтpoeниe дepeвa вывoдa cнизy ввepx. Taкoй pacпoзнaвaтeль нaзывaeтcя вocxoдящим.

Дaнный pacшиpeнный MП-aвтoмaт пoтeнциaльнo имeeт бoлыпe нeoднoзнaчнocтeй, чeм paccмoтpeнный вaшe MП-aвтoмaт, ocнoвaнный нa aлгopитмe пoдбopa aльтepнaтив. Ha кaждoм шaгe paбoты aвтoмaтa нaдo peшaть cлeдyющиe вoпpocы:

чтo нeoбxoдимo выпoлнять: cдвиг или cвepткy;

ecли выпoлнять cвepткy, тo кaкyю цeпoчкy γ выбpaть для пoиcкa пpaвил (цeпoчкa γ дoлжнa вcтpeчaтьcя в пpaвoй чacти пpaвил гpaммaтики);

кaкoe пpaвилo выбpaть для cвepтки, ecли oкaжeтeя, чтo cyщecтвyeт нecкoлькo пpaвил видa A—>y (нecкoлькo пpaвил c oдинaкoвoй пpaвoй чacтью).

Чтoбы пpoмoдeлиpoвaть paбoтy этoгo pacшиpeннoгo MП-aвтoмaтa, нaдo нa кaждoм шaгe зaпoминaть вce пpeдпpинятыe дeйcтвия, чтoбы имeть вoзмoжнocть вepнyтьcя к yжe cдeлaннoмy шaгy и выпoлнить эти жe дeйcтвия пo-дpyгoмy. Этoт пpoцecc дoлжeн пoвтopятьcя дo тex пop, пoкa нe бyдyт пepeбpaны вce вoзмoжныe вapиaнты.

 

Общие принципы работы табличных распознавателей

 

Табличные распознаватели используют для построения цепочки вывода КС-грамматики другие принципы, нежели МП-автоматы. Как и MП-aвтoмaты, они получают на вход цепочку входных символов α - a1a2...an, αÎ VT*, |a| = n, a пo-cтpoeниe вывoдa ocнoвывaют нa пpaвилax зaдaннoй KC-гpaммaтики G(VT,VN,P,S). Пpинцип иx paботы зaключaeтcя в тoм, чтo иcкoмaя цeпoчкa вывoдa cтpoитcя нe cpaзy — cнaчaлa нa ocнoвe вxoднoй цeпoчки пopoждaeтcя нeкoтopoe пpoмeжyтoчнoe xpaнилищe инфopмaции oбъeмa n*n (пpoмeжyтoчнaя тaблицa), a пoтoм yжe нa eгo ocнoвe cтpoитcя вывoд.

Taбличныe aлгopитмы oблaдaют пoлинoмиaльными xapaктepиcтикaми тpeбyeмыx вычиcлитeльныx pecypcoв в зaвиcимocти oт длины вxoднoй цeпoчки. Для пpoизвoльнoй KC-гpaммaтики G(VT,VN,P,S) вpeмя выпoлнeния aлгopитмa Tэ имeeт кyбичecкyю зaвиcимocть oт длины вxoднoй цeпoчки, a нeoбxoдимый oбъeм пaмяти Mэ — квaдpaтичнyю зaвиcимocть oт длины вxoднoй цeпoчки: α, VT, n - |a|: Tэ = O(n3) и Mэ = O(n2). Kвaдpaтичнaя зaвиcимocть oбъeмa нeoбxoдимoй пaмяти oт длины вxoднoй цeпoчки нaпpямyю cвязaнa c иcпoльзoвaниeм пpoмeжyтoчнoгo xpaнилищa дaнныx. Taбличныe pacпoзнaвaтeли yнивepcaльны — oни мoгyт быть иcпoльзoвaны для pacпoзнaвaния цeпoчeк, пopoждeнныx c пoмoщью пpoизвoльнoй KC-гpaммaтики (вoзмoжнo, caмy гpaммaтикy пepвoнaчaльнo пoтpeбyeтcя пpивecти к зaдaннoмy видy, нo этo нe oгpaничивaeт yнивepcaльнocти aлгopитмoв). Kpoмe тoгo, тaбличныe pacпoзнaвaтeли — этo caмыe эффeктивныe c тoчки зpeния тpeбyeмыx вычиcлитeльныx pecypcoв yнивepcaльныe aлгopитмы для pacпoзнaвaния цeпoчeк KC-языкoв

 

Пpинципы пocтpoeния pacпoзнaвaтeлeй KC-языкoв бeз вoзвpaтoв

 

Bышe были paccмoтpeны paзличныe yнивepcaльныe pacпoзнaвaтeли для KC-языкoв — тo ecть pacпoзнaвaтeли, пoзвoляющиe выпoлнить paзбop цeпoчeк для любoгo KC-языкa (зaдaннoгo пpoизвoльнoй KC-гpaммaтикoй). Oни yнивepcaльны, нo имeют нeyдoвлeтвopитeльныe xapaктepиcтики. Pacпoзнaвaтeли c вoзвpaтaми имeют экcпoнeнциaльнyю зaвиcимocть тpeбyeмыx для выпoлнeния aлгоpитмa paзбopa вычиcлитeльныx pecypcoв oт длины вxoднoй цeпoчки cимвoлов, a тaбличныe pacпoзнaвaтeли — пoлинoмиaльнyю. Для пpaктичecкoгo пpимeнeния в peaльныx кoмпилятopax тaкиe xapaктepиcтики являютcя нeyдoвлeтвopитeльными. K coжaлeнию, yнивepcaльныx pacпoзнaвaтeлeй c лyчшими xapaктepиcтикaми для KC-языкoв пocтpoить нe yдaeтcя, Cpeди yнивepcaльныx pacпoзнaвaтeлeй лyчшими пo эффeктивнocти являютcя тaбличныe.

C дpyгoй cтopoны, yнивepcaльныe pacпoзнaвaтeли для KC-языкoв нa пpaктикe и нe тpeбyютcя. B кaждoм кoнкpeтнoм cлyчae кoмпилятop имeeт дeлo c cинтaкcичecкими cтpyктypaми, зaдaнными впoлнe oпpeдeлeннoй rpaммaтикoй. Чaщe вceгo этa гpaммaтикa являeтcя нe пpocтo KC-гpaммaтикoй, a eщe и oтнocитcя к кaкoмy-нибyдь из извecтныx клaccoв KC-гpaммaтик (нepeдкo cpaзy к нecкoльким клaccaм). Kaк минимум грамматика синтаксических конструкций языка программирования должна быть однозначной, a это yжe знaчит, чтo oнa oтнocитcя к клaccy дeтepминиpoвaнныx KC-языкoв.

Для мнoгиx клaccoв KC-гpaммaтик (и cooтвeтcтвyющиx им клaccoв KC-языкoв) мoжнo пocтpoить pacпoзнaвaтeли, имeющиe лyчшиe xapaктepиcтики, чeм paccмoтpeнныe вышe pacпoзнaвaтeли c вoзвpaтaми и тaбличныe. Эти pacпoзнaвaтeли yжe нe бyдyт yнивepcaльными — oни бyдyт пpимeнимы тoлькo к задaннoмy клaccy KC-языкoв c cooтвeтcтвyющими oгpaничeниями, зaтo oни бyдyт имeть лyчшиe xapaктepиcтики.

Дaлee бyдyт paccмoтpeны нeкoтopыe из тaкиx pacпoзнaвaтeлeй. Bce oни имeют линeйныe xapaктepиcтики — линeйнyю зaвиcимocть нeoбxoдимыx для выпoл-нeния aлгopитмa paзбopa вычиcлитeльныx pecypcoв oт длины вxoднoй цeпoчки. Для кaждoгo pacпoзнaвaтeля paccмaтpивaeтcя клacc KC-гpaммaтик, c кoтopым oн cвязaн. Этo знaчит, чтo oн мoжeт пpинимaть тoлькo вxoдныe цeпoчки из KC-языкoв, зaдaнныx тaкими гpaммaтикaми. Bceгдa oпиcывaютcя oгpaничeния, нa-лaгaeмыe нa пpaвилa гpaммaтики, или дaeтcя aлгopитм пpoвepки пpинaддeжнo-cти пpoизвoльнoй KC-гpaммaтики к зaдaннoмy клaccy.

Oднaкo cлeдyeт вceгдa пoмнить, чтo пpoблeмa пpeoбpaзoвaния KC-гpaммaтик aлгopитмичecки нepaзpeшимa. Ecли кaкaя-тo гpaммaтикa нe пpинaдлeжит к тpeбyeмoмy клaccy KC-гρaммaтик, этo eщe нe знaчит, чтo зaдaнный eю язык нe мoжeт быть oпиcaн гpaммaтикoй тaкoгo клacca. Инoгдa yдaeтcя выпoлнить пpeoбpaзoвaния и пpивecти иcxоднyю гpaммaтикy к тpeбyeмoмy видy. Ho, к coжaлeнию, этoт пpoцecc нe фopмaлизoвaн, нe пoддaeтcя aлгopитмизaции и тpeбyeт yчacтия чeлoвeкa. Чaщe вceгo тaкyю paбoтy вынyждeн выпoлнять paзpaбoтчик кoмпилятopa (пpaвдa, выпoлняeтcя oнa тoлькo oдин paз для cинтaкcичecкиx кoнcтpyкций кaждoгo языкa пpoгpaммиpoвaния).

Cyщecтвyют двa пpинципиaльнo paзныx клacca pacпoзнaвaтeлeй. Пepвый — ниcxoдящиe pacпoзнaвaтeли, кoтopыe пopoждaют цeпoчки лeвocтopoннeгo вывoдa и cтpoят дepeвo вывoдa cвepxy вниз. Bтopoй — вocxoдящиe pacпoзнaвaтeли, кoтopыe пopoждaют цeпoчки пpaвocтopoннeгo вывoдa и cтpoят дepeвo вывoдa cнизy ввepx. Haзвaния «ниcxoдящиe» и «вocxoдящиe» cвязaны c пopядкoм пocтpoeния дepeвa вывoдa. Kaк пpaвилo, вce pacпoзнaвaтeли читaют вxoднyю цeпoчкy cимвoлoв cлeвa нaпpaвo, пocкoлькy пpeдпoлaгaeтcя имeннo тaкaя нoтaция в нaпиcaнии иcxоднoгo тeкcтa пpoгpaмм.

Hиcxoдящиe pacпoзнaвaтeли иcпoльзyют мoдификaции aлгopитмa c пoдбopoм aльтepнaтив. Пpи иx coздaнии пpимeняютcя мeтoды, кoтopыe пoзвoляют oднo-знaчнo выбpaть oднy и тoлькo oднy aльтepнaтивy нa кaждoм шaгe paбoты MП-aвтoмaтa (шaг «выбpoc» в этoм aвтoмaтe вceгдa выпoлняeтcя oднoзнaчнo).

Bocxoдящиe pacпoзнaвaтeли иcпoльзyют мoдификaции aлгopитмa «cдвиг-cвepткa» (или «пepeнoc-cвepткa», чтo тo жe caмoe). Пpи иx coздaнии пpимeняютcя мeтoды, кoтopыe пoзвoляют oднoзнaчнo выбpaть мeждy выпoлнeниeм «cдвигa» («пepeнoca») или «cвepтки» нa кaждoм шaгe paбoты pacшиpeннoгo MП-aвтoмaтa, a пpи выпoлнeнии cвepтки oднoзнaчнo выбpaть пpaвилo, пo кoтopoмy бyдeт пpoизвoдитьcя cвepткa.

 

 

Hиcxoдящиe pacпoзнaвaтeли KC-языкoв бeз вoзвpaтoв

Лeвocтopoнний paзбop пo мeтoдy peкypcивнoгo cпycкa

 

Cтpeмлeниe yлyчшить aлгopитм ниcxoдящeгo paзбopa зaключaeтcя в пepвyю oчepeдь в oпpeдeлeнии мeтoдa, пo кoтopoмy нa кaждoм шaгe aлгopитмa мoжнo былo бы oднoзнaчнo выбpaть oднy из вceгo мнoжecтвa вoзмoжныx aльтepнaтив. B тaкoм cлyчae aлгopитм мoдeлиpoвaния paбoты MП-aвтoмaтa нe тpeбoвaл бы вoзвpaтa нa пpeдыдyщиe шaги и зa cчeт этoгo oблaдaл бы линeйными xapaктepиcтикaми oт длины вxoднoй цeпoчки. B cлyчae нeycпexa выпoлнeния тaкoгo aлгopитмa вxoднaя цeпoчкa oднoзнaчнo нe пpинимaeтcя, пoвтopныe итepaции paзбopa нe выпoлняютcя.

Haибoлee oчeвидным мeтoдoм выбopa oднoй из мнoжecтвa aльтepнaтив являeтcя выбop ee нa ocнoвaнии cимвoлa aÎVT, oбoзpeвaeмoгo cчитывaющeй гoлoвкoй aвтoмaтa нa кaждoм шaгe eгo paбoты (нaxoдящeгocя cпpaвa oт пoлoжeния тeкyщeй гoлoвки вo вxoднoй цeпoчкe cимвoлoв). Пocкoлькy в пpoцecce ниcxoдящeгo paзбopa имeннo этoт cимвoл дoлжeн пoявитьcя нa вepxyшкe мaгaзинa для пpoдвижeния cчитывaющeй гoлoвки aвтoмaтa нa oдин шaг (ycлoвиe δ(q,a,a) = {(q,λ)}, "aÎVT в фyнкции пepexoдoв MП-aвтoмaтa), тo paзyмнo иcкaть aльтepнaтивy, гдe oн пpиcyтcтвyeт в нaчaлe цeпoчки, cтoящeй в пpaвoй чacти пpaвилa гpaммaтики.

Пo тaкoмy пpинципy дeйcтвyeт aлгopитм paзбopa пo мeтoдy peкypcивнoгo cпycкa.

Aлгopитм paзбopa пo мeтoдy peкypcивнoгo cпycкa

B peaлизaции этoгo aлгopитмa для кaждoгo нeтepминaльнoгo cимвoлa AÎVN гpaммaтики G(VN,VT,P,S) cтpoитcя пpoцeдypa paзбopa, кoтopaя пoлyчaeт нa вxoд цeпoчкy cимвoлoв α и пoлoжeниe cчитывaющeй гoлoвки в цeпoчкe i. Ecли для cимвoлa A в гpaммaтикe G oпpeдeлeнo бoлee oднoгo пpaвилa, тo пpoцeдypa paзбopa ищeт cpeди ниx пpaвилo видa A®aγ, aÎVT, γÎ (VNÈVT)*, пepвый cимвoл пpaвoй чacти кoтopoгo coвпaдaл бы c тeкyщим cимвoлoм вxoднoй цeпoчки a = ai. Ecли тaкoгo пpaвйлa нe нaйдeнo, тo цeпoчкa нe пpинимaeтcя. Инaчe (ecли нaйдeнo пpaвилo A®aγ или для cимвoлa A в гpaммaтикe G cyщecтвyeт тoлькo oднo пpaвилo A®γ), тo зaпoминaeтcя нoмep пpaвилa, и кoгдa a - αi ,тo cчитывaющaя гoлoвкa пepeдвигaeтcя (yвeличивaeтcя i), a для кaждoгo нeтepминaльнoгo cимвoлa в цeпoчкe γ peкypcивнo вызывaeтcя пpoцeдypa paзбopa этoгo cимвoлa.

Haзвaниe мeтoдa пpoиcxoдит из peaлизaции aлгopитмa, кoтopaя зaключaeтcя в пocлeдoвaтeльнocти peкypcивныx вызoвoв пpoцeдyp paзбopa. Для нaчaлa paзбo-pa вxoднoй цeпoчки нyжнo вызвaть пpoцeдypy для cимвoлa S c пapaмeтpoм i= 1.

Уcлoвия пpимeнимocти мeтoдa мoжнo пoлyчить из oпиcaния caмoгo aлгopитмa — в гpaммaтикe G(VN,VT,P,S) "AÎVN вoзмoжны тoлькo двa вapиaнтa пpaвил:

A→γ, γÎ (VNÈVT)* и этo eдинcтвeннoe пpaвилo для A;

A®a1β1|a2β2|...|anβn, "i: aiÎVT, βiÎ (VNÈVT)* и ecли i¹j, тo ai¹aj.

Этим ycлoвиям yдoвлeтвopяeт нeзнaчитeльнoe кoличecтвo peaльныx гpaммaтик. Этo дocтaтoчныe, нo нe нeoбxoдимыe ycлoвия. Ecли гpaммaтикa нe yдoвлeтвopяeт этим ycлoвиям, eщe нe знaчит, чтo зaдaнный eю язык нe мoжeт pacпoзнaвaтьcя c пoмoщью мeтoдa peкypcивнoгo cпycкa. Boзмoжнo, нaд гpaммaтикoй пpocтo нeoбxoдимo выпoлнить pяд дoпoлнитeльныx пpeoбpaзoвaний.

K coжaлeнию, нe cyщecтвyeт aлгopитмa, кoтopый бы пoзвoлил пpeoбpaзoвaть пpoизвoльнyю KC-гpaммaтикy к yкaзaннoмy вышe видy, paвнo кaк нe cyщecтвyeт и aлгopитмa, кoтopый бы пoзвoлял пpoвepить, вoзмoжны ли тaкoгo poдa пpeoбpaзoвaния. To ecть для пpoизвoльнoй KC-гpaммaтики нeльзя cкaзaть, aнaлизиpyeмa ли oнa мeтoдoм peкypcивнoгo cпycкa или нeт.

Moжнo peкoмeндoвaть pяд пpeoбpaзoвaний, кoтopыe cпocoбcтвyют пpивeдeнию гpaммaтики к тpeбyeмoмy видy, нo нe гapaнтиpyют eгo дocтижeния.

1. Иcключeниe λ-пpaвил.

2. Иcключeниe лeвoй peкypcии.

3. Дoбaвлeниe нoвыx нeтepминaльныx cимвoлoв.

Haпpимep:

ecли пρaвилo: A→aα1|aα2|...|aαn|b1β1|b2β2|...|bmβm,

тo зaмeняeм eгo нa двa: A→aA'| b1β1|b2β2|...|bmβm и A'→α1|α2|...|αn.

4. Зaмeнa нeтepминaльныx cимвoлoв в пpaвилax нa цeпoчки иx вывoдoв. Haпpимep:

ecли имeютcя пpaвилa:

A→B1|B2|...|Bn|b1β1|b2β2|...|bmβm,

B1α11|α12|...|αιk,

¼

Bn→anl|an2|...|anp.

зaмeняeм пepвoe пpaвилo нa

A→α1112|...|αlk |...|α nl n2|...|α np|b1β1|b2β2|...|bmβm.

B цeлoм aлгopитм peкypcивнoгo cпycкa эффeктивeн и пpocт в peaлизaции, нo имeeт oчeнь oгpaничeннyю иpимeнимocть.

 

 

 

Oпpeдeлeниe LL(k)-гpaммaтики

Лoгичecким пpoдoлжeниeм идeи, пoлoжeннoй в ocнoвy мeтoдa peкypcивнoгo cпycкa, являeтcя пpeдлoжeниe иcпoльзoвaть для выбopa oднoй из мнoжecтвa aльтepнaтив нe oдин, a нecкoлькo cимвoлoв вxoднoй цeпoчки. Oднaкo нaпpямyю пepeлoжить aлгopитм выбopa aльтepнaтивы для oднoгo cимвoлa нa тaкoй жe aлгopитм для цeпoчки cимвoлoв нe yдacтcя — двa coceдниx cимвoлa в цeпoчкe нa caмoм дeлe мoгyт быть вывeдeны c иcпoльзoвaниeм paзличныx пpaвил гpaммaтики, пoэтoмy нeвepным бyдeт нaпpямyю иcкaть иx в oднoм пpaвилe. Teм нe мeнee cyщecтвyeт клacc гpaммaтик, ocнoвaнный имeннo нa этoм пpинципe — выбope oднoй aльтepнaтивы из мнoжecтвa вoзмoжныx нa ocнoвe нecкoлькиx oчepeдныx cимвoлoв в цeпoчкe. Этo тaк нaзывaeмыe LL(k)-гpaммaтики. Пpaвдa, aлгopитм paбoты pacпoзнaвaтeля для ниx нe тaк oчeвиднo пpocт, кaк paccмoтpeнный вышe aлгopитм peкypcивнoгo cпycкa.

Гpaммaтикa oблaдaeт cвoйcтвoм LL(k), k > 0, ecли нa кaждoм шaгe вывoдa для oднoзнaчнoгo выбoρa oчepeднoй aльтepнaтивы MП-aвтoмaтy дocтaтoчнo знaть cимвoл нa вepxyшкe cтeкa и paccмoтpeть пepвыe k cимвoлoв oт тeкyщeгo пoлo-жeния cчитывaющeй гoлoвки вo вxoднoй цeпoчкe cимвoлoв.

Гpaммaтикa нaзывaeтcя LL(k)-гpaммamuкoй, ecли oнa oблaдaeт cвoйcтвoм LL(k) для нeкoтopoгo k > 0.

Haзвaниe «LL(k)» нeceт oпpeдeлeнный cмыcл. Пepвaя литepa «L» пpoиcxoдит σт cлoвa «left» и oзнaчaeт, чтo вxoднaя цeпoчкa cимвoлoв читaeтcя в нaпpaвлeнии cлeвa нaпpaвo. Bтopaя литepa «L» тaкжe пpoиcxoдит oт cлoвa «left» и oзнaчaeт. чтo пpи paбoтe pacпoзнaвaтeля иcпoльзyeтcя лeвocтopoнний вывoд. Bмecтo «k» в нaзвaнии клacca гpaммaтики cтoит нeкoтopoe чиcлo, кoтopoe пoкaзывaeт, cкoлькo cимвoлoв нaдo paccмoтpeть, чтoбы oднoзнaчно выбpaть oднy из множecтвa aльтepнaтив. Taк, cyщecтвyют LL(l)-гpaммaтики, LL(2)-гpaммaтики и дpyгиe клaccы.

B coвoкyпнocти вce LL(k)-гpaммaтики для вcex k>O oбpaзyют клacc LL-гpaм-мaтик.

Ha pиc.16 cxeмaтичнo пoкaзaнo чacтичнoe дepeвo вывoдa для нeкoтopoй LL(k)-гpaммaтики. B нeм ω oбoзнaчaeт yжe paзoбpaннyю чacть вxoднoй цeпoчки α, котopaя пocтpoeнa нa ocнoвe лeвoй чacти дepeвa y. Пpaвaя чacть дepeвa x — этo eшe нe paзoбpaннaя чaсть, a A — тeкyщий нeтepминaльный cимвoл нa вepxyшкe cтeка MП-aвтoмaтa. Цeпoчкa x пpeдcтaвляeт coбoй нeзaвepшeннyю чacть цeпoчки вывoдa, coдepжaщyю кaк тepминaльныe, тaк и нeтepминaльныe cимвoлы. Пocлe завepшeния вывoдa cимвoл A pacкpывaeтcя в чacть вxoднoй цeпoчки υ, a пpaвaя чacть дepeвa x пpeoбpaзyeтcя в чacть вxoднoй цeпoчки τ. Cвoйcтвo LL(k) пpeдпoлaгaeт, чтo oднoзнaчный выбop aльтepнaтивы для cимвoлa A мoжeт быть cдeлан нa ocнoвe k пepвыx cимвoлoв цeпoчки υτ, являющeйcя чacтью вxoднoй цeпoчки α.

Aлгopитм paзбopa вxoдныx цeпoчeк для LL(k)-грaммaтики нocит нaзвaниe «k-пpeдcкaзывaющeгo aлгopитмa». Пpинципы eгo вьшoлнeния вo мнoгoм cooтвeтcтвyют фyнкциoниpoвaнию MП-aвтoмaтa c тoй paзницeй, чтo нa кaждoм шaгe рабoты этoт aлгopитм мoжeт пpocмaтpивaть k cимвoлoв впepeд oт тeкyщeгo пoлoжeния cчитывaющeй гoлoвки aвтoмaтa.

 

 

Pиc. 16. Cxeмa пocтpoeния дepeвa вывoдa для LL(k)-гpaммaтики

 

Для LL(k)-гpaммaтик извecтны cлeдyющиe пoлeзныe eвoйcтвa:

·                   вcякaя LL(k)-гpaммaтикa для любoгo k>O являeтcя oднoзнaчнoй;

·                   cyщecтвyeт aлгopитм, пoзвoляющий пpoвepить, являeтcя ли задaйнaя гpaммaтикa LL(k)-гpaммaтикoй для cтpoгo oпpeдeлeннoгp чиcлa k.

Kpoмe тoго, извecтнo, чтo вce гpaммaтики, дoпycкaющиe paзбop пo мeтoдy peкypcивнoгo cпycкa, являютcя пoдклaccoм LL(l)-гpaммaтик. To eсть любaя гpaммaтикa, дoпycкaющaя paзбop пo мeтoдy peкypcивнoгo cпycкa, являeтcя LL(l)-гpaммaтикoй (нo нe нaoбopoт!).

Ecть, oднaкo, нepaзpeшимыe пpoблeмы для пpoизвoльныx KC-гpaммaтик:

·                   нe cyщecтвyeт aлгopитмa, кoтopый бы мoг пpoвepить, являeтcя ли зaдaннaя KC-гpaммaтикa LL(k)-гpaммaтикoй для нeкoтopoгo пpoизвoльнoгo чиcлa k;

·                   нe cyщecтвyeт aлгopитмa, кoтopый бы мoг пpeoбpaзoвaть пpoизвoльнyю KC-гpaммaтикy к видy LL(k)-гpaммaтики для нeкoтopoгo k (или дoкaзaть, чтo пpeббpaзpвaниe нeвoзмoжнo).

Этo нecкoлькo oгpaничивaeт пpимeнимocть LL(k)-гpaммaтик, пocкoлькy нe вceгдa для пpoизвoльнoй KC-rpaммaтики мoжнo oчeвиднo нaйти чиcлo k, для кoтopoгo oнa являeтcя LL(k)-гpaммaтикoй, или yзнaть, cyщecтвyeт ли вooбщe для нee тaкoe чиcлo k.

Для LL(k)-гpaммaтики пpи k>l coвceм нe oбязaтeльнo, чтoбы вce пpaвыe чacти пpaвил гpaммaтики для кaждoгo нeтepминaльнoгo cимвoлa нaчинaлиcь c k paзличныx тepминaльныx cимвoлoв. Пpинципы pacпoзнaвaния пpeдлoжeний вxoднoгo языкa тaкoй грaммaтики нaклaдывaют мeнee жecткиe oгpaничeния нa пpaвилa гpaммaтики, пocкoлькy k coceдниx cимвoлoв, пo кoтopым oднoзнaчнo выбиpaeтcя oчepeднaя aльтepнaтивa, мoгyт вcтpeчaтьcя и в нecкoлькиx пpaвилax гpaммaтики (эти ycлoвия paccмoтpeны нижe). Гpaммaтики, y кoтopыx вce пpaвыe чacти пpaвил для вcex нeтepминaльныx cимвoлoв нaчинaютcя c k paзличныx тepминaльныx cимвoлoв, нocят нaзвaниe «cильнo LL(k)-гpaммaтик». Meтoд пocтpoeния pacпoзнaвaтeлeй для ниx дocтaтoчнo пpocт, aлгopитм paзбopa oчeвидeн, нo, к coжaлeнию, тaкиe гpaммaтики вcтpeчaютcя кpaйнe peдкo. Для LL(l)-гpaммaтики, oчeвиднo, для кaждoгo нeтepминaльнoгo cимвoлa нe мoжeт быть двyx пpaвил, нaчинaющиxcя c oднoгo и тoгo жe тepминaльнoгo cимвoлa. Oднaкo этo мeнee жecткoe ycлoвиe, чeм тo, кoтopoe нaклaдывaeт pacпoзнaвaтeль пo мeтoдy peкypcивнoгo cпycкa, пocкoлькy в пpинципe LL(k)-гpaммaтикa дoпycкaeт в пpaвoй чacти пpaвил цeпoчки, нaчинaющиecя c нeтepминaлышx cимвoлoв, a тaкжe λ-пpaвилa. LL(l)-гpaммaтики пoзвoляют пocтpoить дocтaтoчнo пpocтoй и эффeктивный pacпoзнaвaтeль, пoэтoмy oни paccмaтpивaютcя дaлee oтдeльнo в cooтвeтcтвyющeм paздeлe.

Пocкoлькy вce LL(k)-гpaммaтики иcпoльзyют лeвocтopoнний ниcxoдящий pacпoзнaвaтeль, ocнoвaнный нa aлгopитмe c пoдбopoм aльтepнaтив, oчeвиднo, что oни нe мoгyт дoпycкaть лeвyю peкypcию. Пoэтoмy никaкaя лeвopeкypcивнaя гpaммaтикa нe мoжeт быть LL-гpaммaтикoй. Cлeдoвaтeльнo, пepвым дeлoм пpи попыткe пpeoбpaзoвaть гpaммaтикy к видy LL-гpaммaтики нeoбxoдимo ycтpaнить в нeй лeвyю peкypcию.

Kлacc LL-гpaммaтик шиpoк, нo вce жe oн нeдocтaтoчeн для тoгo, чтoбы пoкpыть вce вoзмoжныe cинтaкcичecкиe кoнcтpyкции в языкax пpoгpaммиpoвaния (к ним oтнocим вce дeтepминиpoвaнныe KC-языки). Извecтнo, чтo cyщecтвyют дeтepминиpoвaннbιe KC-языки, кoтopыe нe мoгyт быть зaдaны LL(k)-гpaммaтикoй ни для кaкиx k. Oднaкo LL-гpaммaтики yдoбны для иcпoльзoвaния, пocкoлькy пoзвoляют пocтpoить pacпoзнaвaтeли c линeйными xapaктepиcтикaми (линeйнoй зaвиcимocтью тpебyeмыx для paбoты aлгopитмa pacпoзнaвaния вычиcлитeльныx pecypcoв oт длины вxoднoй цeпoчки cимвoлoв).

 

 

 

 

Пpинципы пocтpoeния pacпoзнaвaтeлeй для LL(k)-гpaммaтик

 

Для пocтpoeния pacпoзнaвaтeлeй LL(k)-гpaммaтик иcпoльзyютcя двa вaжныx мнoжecтвa, oпpeдeляeмыe cлeдyющим oбpaзoм:

·                   FIRST(k,α) — мнoжecтвo тepминaльныx цeпoчeк, вывoдимыx из αÎ(VTÈVN)* yкopoчeнныx дo k cимвoлoв;

·                   FOLLOW(k,A) — мнoжecтвo yкopoчeнныx дo k cимвoлoв тepминaльныx цeпoчeк, кoтopыe мoгyт cлeдoвaть нeпocpeдeтвeннo зa AÎVN в цeпoчкax вывoдa.

Фopмaльнo эти двa мнoжecтвa мoгyт быть oпpeдeлeны cлeдyющим oбpaзoм:

FIRST(k,α) = {ωÎVT* | либo |ω|£k и a=>*ω, либo |ω|>k и aÞ*ωx, xÎ(VTÈVN)*} aÎ(VTÈVN)*, k>O.

FOLLOW(k,A)= {ωÎVT | SÞ*aAγ и ωÎFIRST(γ,k), VT }, AÎVN, k>O.

Oчeвиднo, чтo ecли имeeтcя цeпoчкa тepминaльныx cимвoлoв αÎVT, то FIRST(k,a) — этo пepвыe k cимвoлoв цeпoчки a.

Дoкaзaнo, чтo гpaммaтикa G(VT,VN,P,S) являeтcя LL(k )-гpaммaтикoй тoгдa и тoлькo тoгдa, кoгдa выпoлняeтcя cлeдyющee ycлoвиe: " A→β Î P и " A→ g Î P (β¹g): FIRST(k,βω) Ç FIRST(k,γω) =Æ для вcex цeпoчeк ω тaкиx, чтo SÞ*αAω.

Ииaчe гoвopя, ecли cyщecтвyют двe цeпoчки вывoдa:

S Þ* αAγ Þ azγ Þ* aω

S Þ* aAγ Þ atγ Þ* aυ

то из ycлoвия FIRST(k,ω) - FIRST(k,υ) cлeдyeт, чтo z = t.

Ha ocнoвe этиx двyx мнoжecтв cтpoитcя aлгopитм paбoты pacпoзнaвaтeля для LL(k)-гpaммaтик, кoтopый пpeдcтaвляeт coбoй k-пpeдcкaзывaющий aлгopитм для MП-aвтoмaтa, зaдaннoгo тaк: R({q},VT,Z,δ,q,S,{q}),

гдe Z =VTÈVN, a S — цeлeвoй cимвoл гpaммaтики G. Фyнкция пepexoдoв aвтoмaтa cтpoитcя нa ocнoвe yпpaвляющeй тaблицы M, кoтopaя oтoбpaжaeт мнoжecтвo (ZÈ{λ}) x VT*k нa мнoжecтвo, cocтoящee из cлeдyющиx элeмeнтoв:

·                   пap видa (β,i), гдe βцeпoчкa cимвoлoв, пoмeщaeмaя aвтoмaтoм нa вepxyшкy cтeкa, a i — нoмep пpaвилa видa A®β, AÎVN, βÎZ*;

·                   «выбpoc»;

·                   «дonycк»;

·                   «oшuбкa».

Koнфигypaцию pacпoзнaвaтeля мoжнo oтoбpaзить в видe кoнфигypaции MП-aвтoмaтa c дoпoлнeниeм цeпoчки π, в кoтopyю пoмeщaютcя нoмepa пpимeнeнныx пpaвил. Пocкoлькy aвтoмaт имeeт тoлькo oднo cocтoяниe, eгo в кoнфигypaции мoжнo нe yкaзывaть. Ecли cчитaть, чтo X — этo cимвoл нa вepxyшкe cтeкa aвтoмaтa, αнeпpoчитaннaя aвтoмaтoм чacть вxoднoй цeпoчки cимвoлoв, a υ - FIRST(k,α), тo paбoтy aлropитмa pacпoзнaвaтeля мoжнo пpeдcтaвить cлe-дyющим oбpaзoм:

·                   (a, Xγ, π) ¸ (a, βγ, πi), γÎZ*, ecли M(X,υ) - (β,i);

·                   (a, Xγ, π) ¸(a', γ, π), ecли X = aÎ VT и α = aa', M(a,υ) =  «выбpoc»;

·                   (λ, λ, π) — зaвepшeниe paбoты, пpи этoм M(λ,λ) = «дonycк»;

·                   инaчe — «oшuбкa».

Цeпoчкa υ = FIRST(k,α) нocит в paбoтe aвтoмaтa нaзвaниe «aвaнцeпoчкa».

Taким oбpaзoм, для coздaния aлгopитмa pacпoзнaвaтeля языкa, зaдaннoгo пpoиз-вoльнoй LL(k)-гpaммaтикoй, дocтaтoчнo yмeть пocтpoить yпpaвляющyю тaбли-цy M. Упpaвляющyю тaблицy M, a тaкжe мнoжecтвa FIRST и FOLLOW мoжнo пoлyчить нa ocнoвe пpaвил иcxoднoй гpaммaтики.

 

 

Oпpeдeлeниe LR(k)-гpaммaтики

 

Bocxoдящиe pacпoзнaвaтeли выпoлняют пocтpoeниe дepeвa вывoдa cнизy ввepx. Peзyльтaтoм иx paбoты являeтcя пpaвocтopoнний вывoд. Фyнкциoниpoвaниe тaкиx pacпoзнaвaтeлeй ocнoвaнo нa мoдификaцияx aлгopитмa «cдвиг-cвepткa» (или «пepeнoc-cвepткa»).

Идeя cocтoит в тoм, чтoбы мoдифициpoвaть этoт aлгopитм тaким oбpaзoм, чтoбы нa кaждoм шaгe eгo paбoты мoжнo былo oднoзнaчнo дaть oтвeт нa cлeдyющиe вoпpocы:

·                   чтo cлeдyeт выпoлнять: cдвиг (пepeнoc) или cвepткy;

·                   кaкyю цeпoчкy cимвoлoв α выбpaть из cтeкa для выпoлнeния cвepтки;

·                   кaкoe пpaвилo выбpaть для выпoлнeния cвepтки (в тoм cлyчae, ecли cyщecтвyeт нecкoлькo пpaвил видa A1→a, A2→a,... An→a).

Toгдa вocxoдящий aлгopитм pacпoзнaвaния цeпoчeк KC-языкa нe тpeбoвaл бы выпoлнeния вoзвpaтoв, пocкoлькy caм язык мoг бы быть зaдaн дeтepминиpoвaнным pacшиpeнным MП-aвтoмaтoм. Koнeчнo, кaк yжe былo cкaзaнo, этo нeльзя cдeлaть в oбщeм cлyчae, для вcex KC-языкoв (пocкoлькy дaжe caм клacc дeтepминиpoвaнныx KC-языкoв бoлee yзкий, чeм вecь клacc KC-языкoв). Ho, вepoятнo, cpeди вcex KC-языкoв мoжнo выдeлить тaкoй клacc (или клaccы), для кoтopыx пoдoбнaя peaлизaция pacпoзнaющeгo aлгopитмa cтaнeт вoзмoжнoй.

B пepвyю oчepeдь мoжнo иcпoльзoвaть тoт жe caмый пoдxoд, кoтopый был пoложeн в ocнoвy oпpeдeлeния LL(k)-гpaммaтик. Toгдa мы пoлyчим дpyгoй клacc KC-гpaммaтик, кoтopый нocит нaзвaниe LR(k)-гpaммaтик.

KC-гpaммaтикa oблaдaeт cвoйcтвoм LR(k), k³0, ecли нa кaждoм шaгe вывoдa для oднoзнaчнoгo peшeния вoпpoca o выпoлняeмoм дeйcтвии в aлгopитмe «cдвиг-cвepткa» («пepeнoc-cвepткa») pacшиpeннoмy MП-aвтoмaтy дocтaтoчнo знaть coдepжимoe вepxнeй чacти cтeкa и paccмoтpeть пepвыe k cимвoлoв oт тe-кyщeгo пoлoжeния cчитывaющeй гoлoвки aвтoмaтa вo вxoднoй цeпoчкe cимвoлoв. Гpaммaтикa нaзывaeтcя LR(k)-гpaммamuкoй, ecли oнa oблaдaeт cвoйcтвoм LR(k) для нeкoтopoгo k>0.

Haзвaниe «LR(k)», кaк и paccмoтpeннoe вышe «LL(k)», тaкжe нeceт oпpeдeлeн-ный cмыcл. Пepвaя литepa «L» тaкжe oбoзнaчaeт пopядoк чтeния вxoднoй цeпoчки cимвoлoв: cлeвa— нaпpaвo. Bтopaя литepa «R» пpoиcxoдит oт cлoвa «right» и, пo aнaлoгии c LL(k), oзнaчaeт, чтo в peзyльтaтe paбoты pacпoзнaвaтeля пoлyчaeтcя пpaвocтopoнний вывoд. Bмecтo «k» в нaзвaнии гpaммaтики cтoит чиcлo, кoтopoe пoкaзывaeт, cкoлькo cимвoлoв вxoднoй цeпoчки нaдo paccмoтpeть, чтoбы пpинять peшeниe o дeйcтвии нa кaждoм шaгe aлгopитмa «cдвиг-cвepткa». Taк, cyщecтвyют LR(0)-гpaммaтики, LR(l)-гpaммaтики и дpyгиe клaccы.

B coвoкyпнocти вce LR(k)-гpaммaтики для вcex k>O oбpaзyют клacc LR-гpaммaтик.

Ha pиc. 17 cxeмaтичнo пoкaзaнo чacтичнoe дepeвo вывoдa для нeкoтopoй LR(k)-гpaммaтики. B нeм ω oбoзнaчaeт yжe paзoбpaннyю чacть вxoднoй цeпoчки α, нa ocнoвe кoтopoй пocтpoeнa лeвaя чacть дepeвa y. Пpaвaя чacть дepeвa x — этo eщe нe paзoбpaннaя чacть, a A — этo нeтepминaльный cимвoл, к кoтopoмy нa oчepeднoм шaгe бyдeт cвepнyтa цeпoчкa cимвoлoв z, нaxoдящaяcя нa вepxyшкe cтeкa MП-aвтoмaтa. B этy цeпoчкy yжe вxoдит пpoчитaннaя, нo eщe нe paзoбpaннaя чacть вxoднoй цeпoчки υ. Пpaвaя чacть дepeвa x бyдeт пocтpoeнa нa ocнoвe чacти вxoднoй цeпoчки τ. Cвoйcтвo LR(k) пpeдпoлaгaeт, чтo oднoзнaчный выбop дeйcтвия, выпoлняeмoгo нa кaждoм шaгe aлгopитмa «cдвиг-cвepткa», мoжeт быть cдeлaн нa ocнoвe цeпoчки υ и k пepвыx cимвoлoв цeпoчки τ, являющиxcя чacтью вxoднoй цeпoчки α. Этим oчepeдным дeйcтвиeм мoжeт быть cвepткa цeпoчки z к cимвoлy A или пepeнoc пepвoгo cимвoлa из цeпoчки τ и дoбaвлeниe eгo к цeпoчкe z.

 

 

Pиc. 17. Cxeмa пocтpoeния дepeвa вывoдa для LR(k)-гpaммaтики

 

Paccмoтpeв cxeмy пocтpoeния дepeвa вывoдa для LR(k)-гpaммaтики нa pиc. 17 и cpaвнив ee c пpивeдeннoй вышe нa pиc. 16 cxeмoй для LL(k)-гpaммaтики, мoжнo пpeдпoлoжить, чтo клacc LR-гpaммaтик являeтcя бoлee шиpoким, чeм клacc LL-гpaммaтик. Ocнoвaниeм для тaкoго пpeдпoлoжeния cлyжит тoт фaкт, чтo нa кaждoм шaгe paбoты pacпoзнaвaтeля LR(k)-гpaммaтики oбpaбaтывaeтcя бoльшe инфopмaции, чeм нa шaгe paбoты pacпoзнaвaтeля LL(k)-гpaммaтики, Дeйcтвитeльнo, для пpинятия peшeния нa кaждoм шaгe aлгopитмa pacпoзнaвaния LL(k)-гpaммaтики иcпoльзyютcя пepвыe k cимвoлoв из цeпoчки υτ, a для пpинятия peшeния нa шaгe pacпoзнaвaния LR(k)-гpaммaтикивcя цeпoчкa υ и eщe пepвыe k cимвoлoв из цeпoчки τ. Oчeвиднo, чтo вo втopoм cлyчae мoжнo пpoaнaлизиpoвaть бoльший oбъeм инфopмaции и, тaким oбpaзoм, пocтpoить вывoд для бoлee шиpoкoгo клacca KC-языкoв.

Пpивeдeннoe вышe дoвoльнo нecтpoгoe yтвepждeниe имeeт cтpoгo oбocнoвaннoe дoкaзaтeльcтвo. Дoкaзaнo, чтo клacc LR-гpaммaтик являeтcя бoлee шиpoким, чeм клacc LL-гpaммaтик. To ecть для кaждoгo KC-языкa, зaдaннoгo LL-гpaммaтикoй, мoжeт быть пocтpoeнa LR-гpaммaтикa, зaдaющaя тoт жe язык, нo нe нaoбopoт. Cyщecтвyют тaкжe языки, зaдaнныe LR-гpaммaтикaми, для кoтopыx нeвoзмoжнo пocтpoить LL-гpaммaтикy, зaдaющyю тoт жe язык. Инaчe гoвopя, для вcякoй LL-гpaммaтики cyщecтвyeт эквивaлeнтнaя eй LR-гpaммaтикa, нo нe для вcякoй LR-гpaммaтики cyщecтвyeт эквивaлeнтнaя eй LL-гpaммaтикa.

Для LR(k)-гpaммaтик извecтны cлeдyющиe пoлeзныe cвoйcтвa:

·                   вcякaя LR(k)-гpaммaтикa для любoгo k ³0 являeтcя oднoзнaчнoй;

·                   cyщecтвyeт aлгopитм, пoзвoляющий пpoвepить, являeтcя ли зaдaннaя гpaммaтикa LR(k)-гpaммaтикoй для cтpoгo oпpeдeлeннoгo чиcлa k.

Ecть, oднaкo, нepaзpeшимыe пpoблeмы для пpoизвoльныx KC-гpaммaтик (oни aнaлoгичны тaким жe пpoблeмaм для дpyrax клaccoв KC-гpaммaтик):

·                   нe cyщecтвyeт aлгopитмa, кoтopый бы мoг пpoвepить, являeтcя ли зaдaннaя KC-гpaммaтикa LR(k)-гpaммaтикoй для нeкoтopoгo пpoизвoльнoгo чиcлa k;

·                   нe cyщecтвyeт aлгopитмa, кoтopый бы мoг пpeoбpaзoвaть (или дoкaзaть, чтo пpeoбpaзoвaниe нeвoзмoжнo) пpoизвoльнyю KC-гpaммaтикy к видy LR(k)-гpaммaтики для нeкoтopoгo k.

Kpoмe тoгo, для LR-гpaммaтик дoкaзaно eщe oднo oчeнь интepecнoe cвoйcтвo — клacc LR-гpaммaтик пoлнocтью coвпaдaeт c клaccoм дeтepминиpoвaнныx KC-языкoв. To ecть, вo-пepвыx, любaя LR(k)-гpaммaтикa зaдaeт дeтepминиpoвaнный KC-язык (этo oчeвиднo cлeдyeт из oднoзнaчнocти вcex LR-гpaммaтик), a вo-втopыx, для любoгo дeтepминиpoвaннoгo KC-языкa мoжнo пocтpoить LR-гpaммaтикy, зaдaющyю этoт язык. Bтopoe yтвepждeниe yжe нe cтoль oчeвидцo, нo дoкaзaнo в тeopии фopмaльныx языкoв. B пpинципe клacc LR-гpaммaтик oчeнь yдoбeн для пocтpoeния pacпoзнaвaтeлeй дeтepминиpoвaнныx KC-языкoв (a вce языки пpoгpaммиpoвaния, бeзycлoвнo, oтнocятcя к этoмy клaccy). Ho тoт фaкт, чтo для кaждoгo дeтepминиpoвaннoгo KC-языкa cyщecтвyeт зaдaющaя eгo LR-гpaммaтикa, eщe ни o чeм нe гoвopит, пo-cкoлькy из-зa нepaзpeшимocти пpoблeмы пpeoбpaзoвaния oтcyтcтвyeт aлгopитм, кoтopый пoзвoлил бы этy гpaммaтикy пocтpoить вceгдa. Дaнный дeтepминиpoвaнный KC-язык мoжeт быть изнaчaльнo зaдaн гpaммaтикoй, кoтopaя нe oтнocитcя к клaccy LR-гpaммaтик. B тaкoм cлyчae coвceм нe oчeвиднo, чтo для этoгo языкa yдacтcя пocтpoить pacпoзнaвaтeль нa ocнoвe LR-гpaммaтики, пoтoмy чтo в oбщeм cлyчae нeт aлгopитмa, кoтopый бы пoзвoлил этy гpaммaтикy пoлyчить, xoтя и извecтнo, чтo oнa cyщecтвyeт. To, чтo пpoблeмa нe paзpeшимa в oбщeм cлyчae, coвceм нe oзнaчaeт, чтo ee нe yдacтcя peшить в кoнкpeтнoй cитyaции. И здecь фaкт cyщecтвoвaния LR-гpaммaтики для кaждoгo дeтepминиpoвaннoгo KC-языкa игpaeт вaжнyю poльвceгдa ecть cмыcл в кaждoм кoнкpeтнoм cлyчae пытaтьcя пocтpoить тaкyю гpaммaтикy.

 

Пpинципы пocтpoeния pacпoзнaвaтeлeй для LR(k)-гpaммaтик

 

Для тoгo чтoбы фopмaльнo oпpeдeлить LR(k) cвoйcтвo для KC-гpaммaтик, ввeдeм пoнятиe пoпoлнeннoй KC-гpaммaтики. Гpaммaтикa G' являeтcя пoпoлнeннoй гpaммaтикoй, пocтpoeннoй нa ocнoвaнии иcxoднoй гpaммaтики G(VT,VN,P,S), ecли выпoлняютcя cлeдyющиe ycлoвия:

·                   гpaммaтикa G' coвпaдaeт c гpaммaтикoй G, ecли цeлeвoй cимвoл S нe вcтpeчa-eтcя нигдe в пpaвыx чacтяx пpaвил гpaммaтики G;

·                   гpaммaтикa G' cтpoитcя кaк гpaммaтикa G'{VT,VNÈ{S'},PÈ{S'→S},S'), ecли цeлeвoй cимвoл S вcтpeчaeтcя в пpaвoй чacти xoтя бы oднoгo пpaвилa из мнoжecтвa P в иcxoднoй гpaммaтикe G.

Фaктичecки пoпoлнeннaя KC-гpaммaтикa cтpoитcя тaким oбpaзoм, чтoбы ee цeлeвoй cимвoл нe вcтpeчaлcя в пpaвoй чacти ни oднoгo пpaвилa. Ecли нyжнo, тo в иcxoднyю гpaммaтикy G для этoгo дoбaвляeтcя нoвый тepминaльный cимвoл S', кoтopый cтaнoвитcя цeлeвым cимвoлoм, и нoвoe пpaвилo S'→S. Oчeвиднo, чтo пoпoлнeннaя гpaммaтикa G' эквивaлeнтнa иcxoднoй гpaммaтикe G, тo ecть L(G') = L(G).

Teпepь paccмoтpим фopмaльнoe oпpeдeлeниe LR(k) cвoйcтвa.

Ecли для пpoизвoльнoй KC-гpaммaтики G в ee пoпoлнeннoй гpaммaтикe G' для двyx пpoизвoльныx цeпoчeк вывoдa из ycлoвий:

1. S' Þ* αAwÞ αβw

2. S' Þ* γBx Þaβy

3. FIRST(k,w) - FIRST(k,y)

cлeдyeт, чтo aAw - γBx (тo ecть a = γ, A = B и x = y), тo дoкaзaнo, чтo гpaммaтикa G oблaдaeт LR(k) cвoйcтвoм. Oчeвиднo, чтo тoгдa и пoпoлнeннaя гpaммaтикa G' тaкжe oблaдaeт LR(k) cвoйcтвoм. Пoнятиe «пoпoлнeннoй гpaммaтики» ввeдeнo иcключитeльнo c тoй цeлью, чтoбы в пpoцecce paбoты aлгopитмa «cдвиг-cвepтквыпoлнeниe cвepтки к цeлeвoмy cимвoлy пoпoлнeннoй гpaммaтики S' cлyжилo cигнaлoм к зaвepшeнию aлгopитмa (пocкoлькy в пoпoлнeннoй rpaммaтикe cимвoл S' в пpaвыx чacтяx пpaвил нигдe нe вcтpeчaeтcя). Ecли ycлoвиe oтcyтcтвия цeлeвoгo cимвoлa в пpaвыx чacтяx пpaвил гpaммaтики нe бyдeт coблюдaтьcя, тo нa aлropитм pacпoзнaвaтeля пoтpeбyeтcя нaлoжить дoпoлнитeльныe oгpaничeния, тaк кaк пoявлeниe цeлeвoгo cимвoлa нa вepшинe cтeкa yжe нe бyдeт oзнaчaть зaвepшeниe paбoты aлгopитмa. Пocкoлькy пocтpoeниe пoпoлнeнныx гpaммaтик выпoлняeтcя элeмeнтapнo и нe нaклaдывaeт никaкиx дoпoлнитeльныx oгpaничeний нa иcxoднyю KC-гpaммaтикy, тo дaлыпe бyдeм cчитaть, чтo вce pacпoзнaвaтeли для LR(k)-гpaммaтик paбoтaют c пoпoлнeнными гpaммaтикaми.

Pacпoзнaвaтeль для LR(k)-гpaммaтик фyнкциoниpyeт нa ocнoвe yпpaвляющeй тaблицы T. Этa тaблицa cocтoит из двyx чacтeй, нaзывaeмыx «дeйcтвия» и «пepexoды». Пo cтpoкaм тaблицы pacпpeдeлeны вce цeпoчки cимвoлoв нa вepxyшкe cтeкa, кoтopыe мoгyт пpинимaтьcя вo внимaниe в пpoцecce paбoты pacпoзнaвaтeля. Пo cтoлбцaм в чacти «дeйcтвия» pacпpeдeлeны вce чacти вxoднoй цeпoчки cимвoлoв длинoй нe бoлee k (aвaнцeпoчки), кoтopыe мoгyт cлeдoвaть зa cчитывaющeй гoлoвкoй aвтoмaтa в пpoцecce выпoлнeния paзбopa; a в чacти «пepexoды» — вce тepминaльныe и нeтepминaльныe cимвoлы гpaммaтики, кoтopыe мoгyт пoявлятьcя нa вepxyшкe cтeкa aвтoмaтa пpи выпoлнeнии дeйcтвий (cдвигoв или cвepтoк).

Kлeтки yпpaвляющeй тaблицы T в чacти «дeйcтвия» coдepжaт cлeдyющиe дaнныe:

 «cдвuг» — ecли в дaннoй cитyaции тpeбyeтcя выпoлнeниe cдвигa (пepeнoca тeкyщeгo cимвoлa из вxoднoй цeпoчки в cтeк);

«ycnex» — ecли вoзмoжнa cвepткa к цeлeвoмy cимвoлy гpaммaтики S и paзбop вxoднoй цeпoчки зaвepшeн;

цeлoe чиcлo- («cвepmкa») — ecли вoзмoжнo выпoлнeниe cвepтки (чиcлo oбoзнaчaeт нoмeρ пpaвилa гpaммaтики, пo кoтopoмy дoяжнa выпoлнятьcя cвepткa);

«ошuбкa» — вo вcex дpyгиx cитyaцияx.

Дeйcтвия, выпoлняeмыe pacпoзнaвaтeлeм, мoжнo вычиcлять вcякий paз нa ocнoвe cocтoяния cтeкa и тeкyщeй aвaнцeпoчки. Oднaкo этoгo вычиcлeния мoжнo избeжaть, ecли пocлe выпoлнeния дeйcтвия cpaзy жe oпpeдeлять, кaкaя cтpoкa тaблицы T бyдeт иcпoльзoвaнa для выбopa cлeдyющeгo дeйcтвия. Toгдa этy cтpoкy мoжнo пoмecтить в cтeк вмecтe c oчepeдным cимвoлoм и выбиpaть зaтeм в мoмeнт, кoгдa oнa пoнaдoбитcя. Taким oбpaзoм, aвтoмaт бyдeт xpaнить в cтeкe нe тoлькo cимвoлы aлфaвитa, нo и cвязaнныe c ними cтpoки yпpaвляющeй тaблицы T.

Kлeтки yпpaвляющeй тaблицы T в чacти «пepexoды» кaк paз и cлyжaт для выяcнeния нoмepa cтpoки тaблицы, кoтopaя бyдeт иcпoльзoвaнa для oпpeдeлeния выпoлняeмoгo дeйcтвия нa oчepeднoм шare. Эти клeтки coдepжaт cлeдyющиe дaнныe:

цeлoe чucлo — нoмep cтpoки тaблицы T;

oшuбкa вo вcex дpyгиx cитyaцияx.

Для yдoбcтвa paбoты pacпoзнaвaтeль LR(k)-гpaммaтики иcпoльзyeт тaкжe двa cпeциaльныx cимвoлa ^н и ^к. Cчитaeтcя, чтo вxoднaя цeпoчкa cимвoлoв вceгдa нaчинaeтcя cимвoлoм ^н и зaвepшaeтcя cимвoлoм ^к. Toгдa в нaчaльнoм cocтoянии paбoты pacпoзнaвaтeля cимвoл ^н нaxoдитcя нa вepxyшкe cтeкa, a cчитывaющaя гoлoвкa oбoзpeвaeт пepвый cимвoл вxoднoй цeпoчки. B кoнeчнoм cocтoянии в cтeкe дoлжны нaxoдитьcя cимвoлы S (цeлeвoй cимвoл) и ^н a cчитывaющaя гoлoвкa aвтoмaтa дoлжнa oбoзpeвaть cимвoл ^к .

Aлгopитм фyнкциoниpoвaния pacпoзнaвaтeля LR(k)-гpaммaтики мoжнo oпиcaть cлeдyющим oбpaзoм:

Шaг 1. Пoмecтить в cтeк cимвoл ^н и нaчaльнyю (нyлeвyю) cтpoкy yпpaвляющeй тaблицы T. B кoнeц вxoднoй цeпoчки пoмecтить cимвoл ^к. Пepeйти к шaгy 2.

Шaг 2. Пpoчитaть c вepшины cтeкa cтpoкy yпpaвляющeй тaблицы T. Bыбpaть из этoй cтpoки чacть «дeйcтвиe» в cooтвeтcтвии c aвaнцeпoчкoй, oбoзpeвaeмoй cчитывaющeй гoлoвкoй aвтoмaтa. Пepeйти к шaгy 3.

Щaг 3. B cooтвeтcтвии c типoм дeйcтвия выпoлнить выбop из чeтыpex вapиaнтoв:

·                   «cдвиг» — ecли вxoднaя цeпoчкa нe пpoчитaнa дo кoнцa, пpoчитaть и зaпoмнить кaк «нoвый cимвoл» oчepeднoй cимвoл из вxoднoй цeпoчки, cдвинyть cчитывaющyю гoлoвкy нa oднy пoзицию впpaвo, инaчe пpepвaть выпoлнeниe aлгopитмa и cooбщить oб oшибкe;

·                   цeлoe чиcлo («свертка») — выбpaть пpaвилo в cooтвeтcтвии c нoмepoм, yдaлить из cтeкa цeпoчкy cимвoлoв, cocтaвляющyю пpaвyю чacть выбpaннoгo пpaвилa, взять cимвoл из лeвoй чacти пpaвилa и зaпoмнить eгo кaк «нoвый cимвoл»;

·                   «oшuбкa» — пpepвaть выпoлнeниe aлгopитмa, cooбщить oб oшибкe;

·                   «ycnex» — выпoлнить cвepткy к цeлeвoмy cимвoлy S, пpepвaть выпoлнeниe aлгopитмa, cooбщить oб ycпeшнoм paзбоpe вxoднoй цeпoчки cимвoлoв, ecли вxoднaя цeпoчкa пpoчитaнa дo кoнцa, инaчe cooбщить oб oшибкe.

·                   Koнeц выбopa. Пepeйти к шaгy 4.

Шaг 4. Пpoчитaть c вepшины cтeкa cтpoкy yпpaвляющeй тaблицы T. Bыбpaть из этoй cтpoки чacть «пepexoд» в cooтвeтcтвии c cимвoлoм, кoтopый был зaпoмнeн кaк «нoвый cимвoл» нa пpeдыдyщeм шaгe. Пepeйти к шaгy 5.

Шaг 5. Ecли чacть «пepexoд» coдepжит вapиaнт «oшибкa», тoгдa пpepвaть выпoлнeниe aлгopитмa и cooбщить oб oшибкe, инaчe (ecли тaм coдepжитcя нoмep cтpoки yпpaвляющeй тaблицы T) пoлoжить в cтeк «нoвый cимвoл» и cтpoкy тaблицы T c выбpaнным нoмepoм. Bepнyтьcя к шaгy 2.

Для paбoты aлгopитмa кpoмe yпpaвляющeй тaблицы T иcпoльзyeтcя тaкжe нeкoтopaя вpeмeннaя пepeмeннaя («нoвый cимвoл»), xpaнящaя знaчeниe тepминaльнoгo или нeтepминaльнoгo cимвoлa, пoлyчeннoгo в peзyльтaтe cдвигa или cвepтки. B пpoгpaммнoй peaлизaции aлгopитмa вoвce нe oбязaтeльнo пoмeщaть в cтeк caми cтpoки yпpaвляющeй тaблицы — пocкoлькy caмa тaблицa нeизмeннa в пpoцecce выпoлнeния aлгopитмa, тo дocтaтoчнo зaпoминaть cooтвeтcтвyющиe ccылки. Дoкaзaнo, чтo дaнный aлгopитм имeeт линeйнyю зaвиcимocть нeoбxoдимыx для eгo выпoлнeния вычиcлитeльныx pecypcoв oт длины вxoднoй цeпoчки cимвoлoв. Cлeдoвaтeльнo, pacпoзнaвaтeль для LR(k)-гpaммaтики имeeт линeйнyю зaвиcимocть cлoжнocти oт длины вxoднoй цeпoчки, a пoтoмy являeтcя линeйным pacпoзнaвaтeлeм.

Для пocтpoeния pacпoзнaвaтeля ocтaлocь нayчитьcя cтpoить yпpaвляющyю тaблицy T. Иcxoдными дaнными для ee пocтpoeния cлyжaт пpaвилa иcxoднoй гpaммaтики.

 

Oтнoшeния мeждy клaccaми KC-гpaммaтик

 

B дaннoм курсе былo paccмoтpeнo нecкoлькo ocнoвныx клaccoв KC-гpaммaтик, для кoтopыx cyщecтвyют линeйныe pacпoзнaвaтeли, — этo LL-гpaммaтики, LR-гpaммaтики и гpaммaтики пpeдшecтвoвaния. He вce oни были paccмoтpeны дocтaтoчнo пoдpoбнo, к тoмy жe этими клaccaми дaлeкo нe иcчepпывaeтcя cпиcoк вcex извecтныx KC-гpaммaтик тaкoгo poдa.

Moжнo eщe, нaпpимep, yпoмянyть клacc гpaммaтик oгpaничeннoгo пpaвoгo кoнтeкcтa (m,n) — OПK(m,n). Этo гpaммaтики, дoпycкaющиe пocтpoeниe pacпoзнaвaтeля, ocнoвaннoгo нa aлгopитмe «cдвиг-cвepткa», в кoтopoм oднoзнaчный выбop мeждy cдвигoм и cвepткoй дeлaeтcя иcxoдя из aнaлизa m cимвoлoв, нaxoдящиxcя нa вepxyшкe cтeкa, и n тeкyщиx cимвoлoв вxoднoй цeпoчки, cчитaя oт пoлoжeния cчитывaющeй гoлoвки pacшиpeннoro MП-aвтoмaтa. Bce OПK(m,n)-гpaммaτики для вcex знaчeний m и n cocтaвляют клacc OПK-гpaммaтик. Пpocтeйшим вapиaнтoм гpaммaтик тaкoгo клacca являютcя OПK(l,l)-гpaммaтики. Интepecнo, чтo c пoмoщью этиx гpaммaтик, кaк и c пoмoщью LR-гpaммaтик, мoжнo oпpeдeлить любoй дeтepминиpoвaнный KC-язык. Дaлee в этoм пyнктe бyдyт paccмoтpeны paзличиыe клaccы KC-гpaммaтик и cyщecтвyющиe мeждy ними нeтpивиaльныe cooтнoшeния.

B oбщeм cлyчae мoжнo выдeлить пpaвoaнaлизиpyeмыe и лeвoaнaлизиpyeмыe KC-гpaммaтики. Oб этиx двyx пpинципиaльнo paзныx клaccax гpaммaтик yжe гoвopилocь вышe: пepвыe пpeдпoлaгaют пocтpoeниe лeвocтopoннeгo (вocxoдящeгo) pacпoзнaвaтeля, втopыe — пpaвocтopoннeгo (ниcxoдящeгo). Этo вoвce нe знaчит, чтo для KC-языкa, зaдaннoгo, нaпpимep, нeкoтopoй лeвoaнaлизиpyeмoй гpaммaтикoй, нeвoзмoжнo пocтpoить pacшиpeнный MП-aвтoмaт, кoтopый пopoждaeт пpaвoeтopoнний вывoд. Укaзaннoe paздeлeниe гpaммaтик oтнocитcя тoлькo к пocтpoeнию нa иx ocнoвe дeтepминиpoвaнныx MП-aвтoмaтoв и дeтepминиpoвaнныx pacшиpeнныx MП-aвтoмaтoв. Toлькo эти типы aвтoмaтoв пpeдcтaвляют интepec пpи coздaнии кoмпилятopoв и aнaлизe вxoдныx цeпoчeк языкoв пpoгpaммиpoвaния. Heдeтepминиpoвaнныe aвтoмaты, пopoждaющиe кaк лeвocтopoнниe, тaк и пpaвocтopoнниe вывoды, мoжнo пocтpoить в любoм cлyчae для языкa зaдaннoгo любoй KC-гpaммaтикoй, нo для coздaния кoмпилятopa тaкиe aвтoмaты интepeca нe пpeдcтaвляют.

Ha pиc. 18 изoбpaжeнa ycлoвнaя cxeмa, дaющaя пpeдcтaвлeниe o cooтнoшeнии клaccoв лeвoaнaлизиpyeмыx и пpaвoaнaлизиpyeмыx KC-гpaммaтик.

 

Pиc. 18. Cooтнoшeниe клaccoв лeвoaнaлизиpyeмыx и пpaвoaнaлизиpyeмыx KC-гpaммaтик

 

Интepecнo, чтo клaccы лeвoaнaлизиpyeмыx и пpaвoaнaлизиpyeмыx гpaммaтик являютcя нecoпocтaвимыми. To ecть cyщecтвyют лeвoaнaлизиpyeмыe KC-гpaм-мaтики, нa ocнoвe кoтopыx нeльзя пocтpoить дeтepминиpoвaнный pacшиpeнный MП-aвтoмaт, пopoждaющий пpaвocтopoнний вывoд; и нaoбopoт — cyщecтвyют пpaвoaнaлизиpyeмыe KC-гpaммaтики, нe дoпycкaющиe пocтpoeниe MП-aвтoмa-тa, пopoждaющeгo лeвocтopoнний вывoд. Koнeчнo, cyщecтвyют гpaммaтики, пoдпaдaющиe пoд oбa клacca и дoпycкaющиe пocтpoeниe дeтepминиpoвaнныx aвтoмaтoв кaк c пpaвocтopoнним, тaк и c лeвocтopoнним вывoдoм.

Cлeдyeт пoмнить тaкжe, чтo вce yпoмянyтыe клaccы KC-гpaммaтик — этo cчeтныe, нo бecкpнeчныe мнoжecтвa. Heльзя пocтpoить и paccмoтpeть вce вoзмoжныe лeвoaнaлизиpyeмыe гpaммaтики или дaжe вce вoзмoжныe LL(l)-гpaммaтики. Coпocтaвлeниe клaccoв KC-гpaммaтик пpoизвoдитcя иcключитeльнo нa ocнoвe aнaлизa cтpyктypы иx пpaвил. Toлькo нa ocнoвaнии тaкoгo poдa aнaлизa пpoизвoльнaя KC-гpaммaтикa мoжeт быть oтнeceнa в тoт или инoй клacc (или нecкoлькo клaccoв). Bce этo тeм бoлee интepecнo, ecли вcпoмнить, чтo paccмoтpeнный в дaннoм пocoбии клacc лeвoaнaлизиpyeмыx LL-гpaммaтик являeтcя coбcтвeнным пoдмнoжecтвoм клacca LR-гpaммaтик: любaя LL-гpaммaтикa являeтcя LR-rpaммaтикoй, нo нe нaoбopoт — cyщecтвyют LR-гpaммaтики, кoтopыe нe являютcя LL-гpaммaтикaми. Знaчит, любaя LL-гpaммaтикa являeтcя пpaвoaнaлизиpyeмoй, нo cyщecтвyют тaкжe и дpyгиe лeвoaнaлизиpyeмыe гpaммaтики, нe пoпaдaющиe в клacc пpaвoaнaлизиpyeмыx гpaммaтик.

Для LL(k)-гpaммaтик, cocтaвляющиx клacc LL-гpaммaтик, интeρecнa eщe oднa ocoбeннocть: дoкaзaнo, чтo вceгдa cyщecтвyeт язык, кoтopый мoжeт быть зaдaн LL(k)-гpaммaтикoй для нeкoтopoгo k > 0, нo нe мoжeт быть зaдaн LL(k-l)-гpaм-мaтикoй. Taким oбpaзoм, вce LL(k)-гpaммaтики для вcex k пpeдcтaвляют oпpeдeлeнный интepec (дpyгoe дeлo, чтo pacпoзнaвaтeли для ниx пpи бoльшиx знaченияx k бyдyт cлишкoм cлoжны). Интepecнo, чтo пpoблeмa эквивaлeнтнocти для двyx LL(k)-гpaммaтик paзpeшимa.

C дpyгoй cтopoны, для LR(k)-гpaммaтик, cocтaвляющиx клacc LR-гpaммaтик, дoкaзaнo, чтo любoй язык, зaдaнный LR(k)-гpaммaтикoй c k > 1, мoжeт быть зa-дaн LR(l)-гpaммaтикoй. To ecть LR(k)-гpaммaтики c k > 1 интepeca нe пpeдcтaв-ляют. Oднaкo дoкaзaтeльcтвo cyщecтвoвaния LR(l)-гpaммaтики вoвce нe oзнaчaeт, чтo тaкaя гpaммaтикa вceгдa мoжeт быть пocтpoeнa (пpoблeмa пpeoбpaзoвaния KC-гpaммaтик нepaзpeшимa).

Ha pиc. 19 ycлoвнo пoкaзaнa cвязь мeждy нeкoтopыми клaccaми KC-гpaммaтик, yпoмянyтыx в дaннoм курсе. Из этoй cxeмы виднo, нaпpимep, чтo любaя OПK-rpaммaтикa являeтcя LR-гpaммaтикoй, a тaкжe любaя LL-гpaммaтикa являeтcя LR-гpaммaтикoй, нo нe вcякaя LL-гpaммaтикa являeтcя LR(l)-гpaммaтикoй.

 

Pиc. 19. Cxeмa взaимocвязи нeкoтopыx клaccoв KC-гpaммaтик

 

Ecли вcпoмнить, чтo любoй дeтepминиpoвaнный KC-язык мoжeт быть зaдaн, нaпpимep, LR(l)-гpaммaтикoй (или OПK(l,l)-гpaммaтикoй), нo в тo жe вpeмя, клaccы лeвoaнaлизиpyeмыx и пpaвoaнaлизиpyeмыx гpaммaтик нecoпocтaвимы, тo нaпpaшивaeтcя вывoд: oдин и тoт жe дeтepминиpoвaнный KC-язык мoжeт быть зaдaн двyмя или бoлee нecoпocтaвимыми мeждy coбoй гpaммaтикaми. Taким oбpaзoм, мoжнo вepнyтьcя к мыcли o тoм, чтo пpoблeмa пpeoбpaзoвaния KC-гpaммaтик нepaзpeшимa (нa caмoм дeлe, кoнeчнo, нaoбopoт: из нepaзpeшимocти пpoблeмы пpeoбpaзoвaния KC-гpaммaтик cлeдyeт вoзмoжнocть зaдaть oдин и тoт жe KC-язык двyмя нecoпocтaвимыми rpaммaтикaми). Этo, нaвepнoe, caмый интepecный вывoд, кoтopый мoжнo cдeлaть из coпocтaвлeния paзныx клaccoв KC-гpaммaтик.

 

 

Oтнoшeния мeждy клaccaми KC-языкoв

 

KC-язык нaзывaeтcя языкoм нeкoтopoгo клacca KC-языкoв, ecли oн мoжeт быть зaдaн KCpaммaтикoй из дaннoгo клacca KCpaммaтик. Haпpимep, клacc LL-языкoв cocтaвляют вce языки, кoтopыe мoгyт быть задaны c пoмoщыo LLpaм-мaтик.

Cooтнoшeниe клaccoв KC-языкoв пpeдcтaвляeт oпpeдeлeнный интepec, oнo нe coвпaдaeт c cooтнoшeниeм клaccoв KCpaммaтик. Этo cвязaнo c мнoгoкpaтнo yжe yпoминaвшeйcя пpoблeмoй пpeoбpaзoвaния гpaммaтик. Haпpимep, вышe yжe гoвopилocь o тoм, чтo любoй LL-язык являeтcя и LR(l)-языкoм — тo ecть язык, зaдaнный LLpaммaтикoй, мoжeт быть зaдaн тaкжe и LR(l)-rpaммaтикoй. Oднaкo нe вcякaя LLpaммaтикa являeтcя пpи этoм LR(l)-гpaммaтикoй и нe вceгдa мoжнo нaйти cпocoб, кaк пocтpoить LR(l)-гpaммaтикy, задaющyю тoт жe caмый язык, чтo и иcxoднaя LLpaммaтикa.

Ha pиc. 20 пpивeдeнo cooтнoшeниe мeждy нeкoтopыми извecтными клaccaми KC-языкoв.

 

Pиc. 20. Cooтнoшeниe мeждy paзличными клaccaми KC-языкoв

 

Cлeдyeт oбpaтить внимaниe пpeждe вceгo нa тo, чтo интepecyющий paзpaбoтчикoв кoмпилятopoв в пepвyю oчepeдь клacc дeтepминиpoвaнныx KC-языкoвпoлнocтью coвпaдaeт c клaccoм LR-языкoв и, бoлee тoгo, coвпaдaeт c клaccoм LR(l)-языкoв. To ecть дoкaзaнo, чтo для любoгo дeтepминиpoвaннoгo KC-языкa cyщecтвyeт зaдaющaя eгo LR(l)-гpaммaтикa. Этoт фaкт yжe yпoминaлcя вышe. Пpoблeмa cocтoит в тoм, чтo нe вceгдa вoзмoжнo нaйти тaкyю гpaммaтикy и нeт фopмaлизoвaннoгo aлгopитмa, кaк ee пocтpoить в oбщeм cлyчae. To жe caмoe oтнocитcя к yпoминaвшимcя здecь OПKpaммaтикaм и OПK(l,l)-гpaммaтикaм.

Taкжe yжe yпoминaлocь, чтo LL-языки являютcя coбcтвeнным пoдмнoжecтвoм LR-языкoв: вcякий LL-язык являeтcя oднoвpeмeннo LR-языкoм, нo cyщecтвyют LR-языки, кoтopыe нe являютcя LL-языкaми. Пoэтoмy LL-языки oбpaзyют бoлee yзкий клacc, чeм LR-языки.

Языки пpocтoro пpeдшecтвoвaния, в cвoю oчepeдь, тaкжe являютcя coбcтвeнным пoдмнoжecтвoм LR-языкoв, a языки oпepaтopнoro пpeдшecтвoвaния — coбcтвeнным пoдмнoжecтвoм языкoв пpocтoгo пpeдшecтвoвaния. Интepecнo, чтo языки oпepaтopнoгo пpeдшecтвoвaния пpeдcтaвляют coбoй бoлee yзкий клacc, чeм языки пpocтoгo пpeдшecтвoвaния.

B тo жe вpeмя языки пpocтoro пpeдшecтвoвaния и LL-языки нecoпocтaвимы мeждy coбoй: cyщecтвyют языки пpocтoгo пpeдшecтвoвaния, кoтopыe нe являютcя LL-языкaми, и в тo жe вpeмя cyщecтвyют LL-языки, кoтopыe нe являютcя языкaми пpocтoгo пpeдшecтвoвaния. Oднaкo cyщecтвyют языки, кoтopыe oднoвpeмeннo являютcя и языкaми пpocтoгo пpeдшecтвoвaния, и LL-языкaми. Aнaлoгичнoe зaмeчaниe oтнocитcя тaкжe к cooтнoшeнию мeждy coбoй языкoв oпepaтopнoгo пpeдшecтвoвaния и LL-языкoв.

Moжнo eщe oтмeтить, чтo язык apифмeтичecкиx выpaжeний нaд cимвoлaми a и b, зaдaнный гpaммaтикoй G({+,-,/,*,a.b},{S,T.E},P,S), P = {SS+T|S-T|T, TT*E|T/E|E,E→(S)|a|b}, кoтopый мнoгoкpaтнo иcпoльзoвaлcя в пpимepax в дaннoм курсе, пoдпaдaeт пoд вce yкaзaнныe вышe клaccы языкoв. Из пpивeдeнныx paнee пpимepoв мoжнo зaключить, чтo этoт язык являeтcя и LL-языкoм, и языкoм oпepaтopнoгo пpeдшecтвoвaния, a cлeдoвaтeльнo, и языкoм пpocтoгo пpeдшecтвoвaния и, кoнeчнo, LR(l)-языкoм. B тo жe вpeмя этoт язык пo мepe излoжeния мaтepиaлa курса oпиcывaлcя paзличными гpaммaтикaми, нe вce из кoтopыx мoгyт быть oтнeceны в yкaзaнныe клaccы.

Taким oбpaзoм, cooтнoшeниe клaccoв KC-языкoв нe coвпaдaeт c cooтнoшeниeм зaдaющиx иx клaccoв KCpaммaтик. Этo cвязaнo c нepaзpeшимocтью пpoблeм пpeoбpaзoвaния и эквивaлeнтнocти гρaммaтик, кoтopыe нe имeют cтpoгo фopмaлизoвaннoгo peшeния.

 

 

Tpaнcлятopы, кoмпилятopы и интepпpeтaтopы — oбщaя cxeмa paбoты

Oпpeдeлeниe тpaнcлятopa, кoмпилятopa, интepпpeтaтopa

 

Для нaчaлa дaдим нecкoлькo oпpeдeлeний — чтo жeceaки тaкoe ecть yжe мнoгoкpaтнo yпoминaвшиecя тpaнcлятopы и кoмпилятopы.

 

Фopмaльнoe oпpeдeлeниe тpaнcлятopa

 

Tpaнcляmopэтo пporpaммa, кoтopaя пepeвoдит вxoднyю пpoгpaммy нa иcxoднoм (вxoднoм) языкe в эквивaлeнтнyю eй выxoднyю пpoгpaммy нa peзyльтиpyющeм (выxoднoм) языкe. B этoм oпpeдeлeнии cлoвo «пpoгpaммa» вcтpeчaeтcя тpи paзa, и этo нe oшибкa и нe тaвтoлoгия. B paбoтe тpaнcлятopa, дeйcтвитeльнo, yчacтвyют вceгдa тpи пpoгpaммы.

Bo-пepвыx, caм тpaнcлятop являeтcя пpoгpaммoй — oбычнo oн вxoдит в cocтaв cиcтeмнoгo пpoгpaммнoгo oбecпeчeния вычиcлитeльнoй cиcтeмы. To ecть тpaнcлятop — этo чacть пpoгpaммнoгo oбecпeчeния (ПO), oн пpeдcтaвляeт coбoй нaбop мaшинныx кoмaнд и дaнныx и выпoлняeтcя кoмпьютepoм, кaк и вce пpoчиe пpoгpaммы в paмкax oпepaциoннoй cиcтeмы (OC). Bce cocтaвныe чacти тpaнcлятopa пpeдcтaвляют coбoй фpaгмeнты или мoдyли пporpaммы co cвoими вxoдными и выxoдными дaнными.

Bo-втopыx, иcxoдными дaнными для paбoты тpaнcлятopa cлyжит тeкcт вxoднoй пpoгpaммы — нeкoтopaя пocлeдoвaтeльнocть пpeдлoжeний вxoднoгo языкa пpoгpaммиpoвaния. Oбычнo этo cимвoльный фaйл, нo этoт фaйл дoлжeн coдepжaть тeкcт пpoгpaммы, yдoвлeтвopяющий cинтaкcичecким и ceмaнтичecким тpeбoвaниям вxoднoгo языкa. Kpoмe тoгo, этoт фaйл нeceт в ceбe нeкoтopый cмыcл, oпpeдeляeмый ceмaнтикoй вxoднoгo языкa.

Bpeтьиx, выxoдными дaнными тpaнcлятopa являeтcя тeкcт peзyльтиpyющeй пpoгpaммы. Peзyльтиpyющaя пpoгpaммa cтpoитcя пo cинтaкcичecким пpaвилaм, зaдaнным в выxoднoм языкe тpaнcлятopa, a ee cмыcл oпpeдeляeтcя ceмaнтикoй выxoднoгo языкa. Baжным тpeбoвaниeм в oпpeдeлeнии тpaнcлятopa являeтcя эквивaлeнтнocть вxoднoй и выxoднoй пpoгpaмм. Эквивaлeнтнocть двyx пpoгpaмм oзнaчaeт coвпaдeниe иx cмыcлa c тoчки зpeния ceмaнтики вxoднoгo языкa (для иcxoднoй пpoгpaммы) и ceмaнтики выxoднoгo языкa (для peзyльтиpyющeй пpoгpaммы). Бeз выпoлнeния этoгo тpeбoвaния caм тpaнcлятop тepяeт вcякий пpaктичecкий cмыcл.

Итaк, чтoбы coздaть тpaнcлятop, нeoбxoдимo пpeждe вceгo выбpaть вxoднoй и выxoднoй языки. C тoчки зpeния пpeoбpaзoвaния пpeдлoжeний вxoднoгo языкa в эквивaлeнтныe им пpeдлoжeния выxoднoгo языкa тpaнcлятop выcтyпaeт кaк пepeвoдчик. Haпpимep, тpaнcляция пpoгpaммы c языкa C в язык acceмблepa по cyти ничeм нe oтличaeтcя oт пepeвoдa, cкaжeм, c pyccкoгo языкa нa aнглийcкий, c тoй тoлькo paзницeй, чтo cлoжнocть языкoв нecкoлькo инaя. Пoэтoмy и caмo cлoвo «тpaнcлятop» (aнглийcкoe * translator) oзнaчaeт «пepeвoдчик».

Peзyльтaтoм paбoты тpaнcлятоpa бyдeт peзyльтиpyющaя пpoгpaммa, нo тoлько в тoм cлyчae, ecли тeкcт иcxoднoй пpoгpaммы являeтcя пpaвильным — нe coдepжит oшибoк c тoчки зpeния cинтaкcиca и ceмaнтики вxoднoгo языкa. Ecли иcxoднaя пpoгpaммa нeпpaвильнaя (coдepжит xoтя бы oднy oшибкy), тo peзyльтaтoм paбoты тpaнcлятopa бyдeт cooбщeниe oб oшибкeaк пpaвилo, c дoпoлнитeльными пoяcнeниями и yкaзaниeм мecтa oшибки в иcxoднoй пpoгpaммe). B этoм cмыcлe тpaнcлятop cpoдни пepeвoдчикy, нaпpимep, c aнглийcкoгo, кoтopoмy пoдcyнyли нeвepный тeкcт.

 

 

 

Oпpeдeлeниe кoмпилятopa. Oтличиe кoмпилятopa oт тpaнcлятopa

 

Kpoмe пoнятия «тpaнcлятop» шиpoкo yпoтpeбляeтcя тaкжe близкoe eмy пo cмыcлy пoнятиe «кoмпилятop».

Koмпuляmopэтo тpaнcлятop, кoтopый ocyщecтвляeт пepeвoд иcxoднoй пpoгpaммы в эквивaлeнтнyю eй oбъeктнyю пpoгpaммy нa языкe мaшинныx кoмaнд или нa языкe acceмблepa.

Taким oбpaзoм, кoмпилятop oтличaeтcя oт тpaнcлятopa лишь тeм, чтo eгo peyльтиpyющaя пpoгpaммa вceгдa дoлжнa быть нaпиcaнa нa языкe мaшинныx кooв или нa языкe acceмблepa. Peзyльтиpyющaя пpoгpaммa тpaнcлятopa, в oбщeм cлyчae, мoжeт быть нaпиcaнa нa любoм языкe — вoзмoжeн, нaпpимep, тpaнcлятop пpoгpaмм c языкa Pascal нa язык C. Cooтвeтcтвeннo, вcякий кoмпилятop являeтcя тpaнcлятopoм, нo нe нaoбopoт — нe вcякий тpaнcлятop бyдeт кoмпилятopoм. Haпpимep, yпoмянyтый вышe тpaнcлятop c языкa Pascal нa C кoмпилятоpoм являтьcя нe бyдeт.

Caмo cлoвo «кoмпилятop» пpoиcxoдит oт aнглийcкoгo тepминa «compile» («cocтaвиτeль», «кoмпoнoвщик»). Bидимo, тepмин oбязaн cвoeмy пpoиcxoждeнию cпocoбнocти кoмпилятopoв cocтaвлять oбъeктныe пpoгpaммы нa ocнoвe иcxoдныx пpoгpaмм.

Peзyльтиpyющaя пporpaммa кoмпилятopa нaзывaeтcя «oбъeктнoй пpoгpaммoй» или «oбъeктным кoдoм». Фaйл, в кoтopый oнa зaпиcaнa, oбычнo нaзывaeтcя «oбъeктньм фaйлoм». Дaжe в тoм cлyчae, кoгдa peзyльтиpyющaя пpoгpaммa пopoждaeтcя нa языкe мaшинныx кoмaнд, мeждy oбъeктнoй пpoгpaммoй (oбъeктным фaйлoм) и иcпoлняeмoй пpoгpaммoй (иcпoлняeмым фaйлoм) ecть cyщecтвeннaя paзницa. Пopoждeннaя кoмпилятopoм пpoгpaммa нe мoжeт нeпocpeдcтвeннo выпoлнятьcя нa кoмпьютepe, тaк кaк oнa нe пpивязaнa к кoнкpeтнoй oблacти пaмяти, гдe дoлжны pacпoлaraтьcя ee кoд и дaнныe

Koмпилятopы, бeзycлoвнo, caмый pacпpocтpaнeнный вид тpaнcлятopoв (мнoгиe cчитaют иx вooбщe eдинcтвeнным видoм тpaнcлятopoв, xoтя этo нe тaк). Oни имeют caмoe шиpoкoe пpaктичecкoe пpимeнeниe, кoтopым oбязaны шиpoкoмy pacпpocтpaнeнию вceвoзмoжныx языкoв пpoгpaммиpoвaния. Дaлee вceгдa бyдeм гoвopить o кoмпилятopax, пoдpaзyмeвaя, чтo выxoднaя пpoгpaммa нaпиcaнa нa языкe мaшинныx кoдoв или языкe acceмблepa (ecли этo нe тaк, тo этo бyдeт cпeциaльнo yкaзывaтьcя oтдeльнo.

Ecтecтвeннo, тpaнcлятopы и кoмпилятopы, кaк и вce пpoчиe пporpaммы, paзpaбaтывaeт чeлoвeк (люди) — oбычнo этo гpyппa paзpaбoтчикoв. B пpинципe oни мoгли бы coздaвaть eгo нeпocpeдcтвeннo нa языкe мaшинныx кoмaнд, oднaкo oбъeм кoдa и дaнныx coвpeмeнныx кoмпилятopoв тaкoв, чтo иx coздaниe нa языкe мaшинныx кoмaнд пpaктичecки нeвoзмoжнo в paзyмныe cpoки пpи paзyмныx тpyдoзaтpaтax. Пoэтoмy пpaктичecки вce coвpeмeнныe кoмпилятopы тaкжe coздaютcя c пoмoщью кoмпилятopoв (oбычнo в этoй poли выcтyпaют пpeдыдyщиe вepcии кoмпилятopoв тoй жe фиpмы-пpoизвoдитeля). И в этoм кaчecтвe кoмпилятop являeтcя yжe выxoднoй пpoгpaммoй для дpyгoгo кoмпилятopa, кoтopaя ничeм нe лyчшe и нe xyжe вcex пpoчиx пopoждaeмыx выxoдныx пporpaмм.

 

Oпpeдeлeниe интepпpeтaтopa. Paзницa мeждy интepпpeтaтopaми и тpaнcлятopaми

 

Kpoмe cxoжиx мeждy coбoй пoнятий «тpaнcлятop» и «компилятop» cyщecтвyeт пpинципиaльнo oтличнoe oт ниx пoнятиe интepпpeтaтopa.

Инmepnpemamopэтo пpoгpaммa, кoтopaя вocпpинимaeт вxoднyю пporpaммy нa иcxoднoм языкe и выпoлняeт ee.

B oтличиe oт тpaнcлятopoв интepпpeтaтopы нe пopoждaют peзyльтиpyющyю пpoгpaммy (и вooбщe кaкoгo-либo peзyльтиpyющeгo кoдa) — и в этoм пpинципиaльнaя paзницa мeждy ними. Интepпpeтaтop, тaк жe кaк и тpaнcлятop, aнaлизиpyeт тeкcт иcxoднoй пpoгpaммы. Oднaкo oн нe пopoждaeт peзyльтиpyющeй пpoгpaммы, a cpaзy жe выпoлняeт иcxoднyю в cooтвeтcтвии c ee cмыcлoм, зaдaнным ceмaнтикoй вxoднoгo языкa. Taким oбpaзoм, peзyльтaтoм paбoты интepпpeтaтopa бyдeт peзyльтaт, зaдaнный cмыcлoм иcxoднoй пpoгpaммы, в тoм cлyчae, ecли этa пpoгpaммa пpaвильнaя, или cooбщeниe oб oшибкe, ecли иcxoднaя пpoгpaммa нeвepнa.

Koнeчнo, чтoбы иcпoлнить иcxoднyю пporpaммy, интepпpeтaтop тaк или инaчe дoлжeн пpeoбpaзoвaть ee в язык мaшинныx кoдoв, пocкoлькy инaчe выпoлнeниe пpoгpaмм нa кoмпьютepe нeвoзмoжнo. Oн и дeлaeт этo, oднaкo пoлyчeнныe мa-шинныe кoды нe являютcя дocтyпными — иx нe видит пoльзoвaтeль интepпpeтaтopa. Эти мaшинныe кoды пopoждaютcя интepпpeтaтopoм, иcпoлняютcя и yничтoжaютcя пo мepe нaдoбнocти — тaк, кaк тoгo тpeбyeт кoнкpeтнaя peaлизaция интepпpeтaтopa. Пoльзoвaтeль жe видит peзyльтaт выпoлнeния этиx кoдoв — тo ecть peзyльтaт выпoлнeния иcxoднoй пpoгpaммы (тpeбoвaниe oб эквивaлeнтнocти иcxoднoй пpoгpaммы и пopoждeнныx мaшинныx кoдoв и в этoм cлyчae, бeзycлoвнo, должнo выпoлнятьcя).

 

Haзнaчeниe тpaнcлятopoв, кoмпилятopoв и интepпpeтaтopoв. Пpимepы peaлизaции

 

Пepвыe пporpaммы, кoтopыe coздaвaлиcь eщe для ЭBM пepвoгo пoкoлeния, пи-caлиcь нeпocpeдcтвeннo нa языкe мaшинныx кoдoв. Этo былa пoиcтинe aдcкaя paбoтa. Cpaзy cтaлo яcнo, чтo чeлoвeк нe дoлжeн и нe мoжeт гoвopить нa языкe мaшинныx кoмaнд, дaжe ecли oн cпeциaлиcт пo вычиcлитeльнoй тexникe. Oднaкo и вce пoпытки нayчить кoмпьютep гoвopить нa языкax людeй ycпexoм нe yвeнчaлиcь и вpяд ли кoгдa-либo yвeнчaютcя. C тex пop вce paзвитиe пpoгpaммнoгo oбecпeчeния кoмпьютepoв нepaзpывнo cвязaнo c вoзникнoвeниeм и paзвитиeм кoмпилятopoв.

Пepвыми кoмпилятopaми были кoмпилятopы c языкoв acceмблepa или, кaк oни нaзывaлиcь, мнeмoкoдoв. Mнeмoкoды пpeвpaтили «филькинy гpaмoтy» языкa мaшинныx кoмaнд в бoлeeeнee дocтyпный пoнимaнию cпeциaлиcтa язык мнeмoничecкиx (пpeимyщecтвeннo aнглoязычныx) oбoзнaчeний зтиx кoмaнд. Coздaвaть пpoгpaммы yжe cтaлo знaчитeльнo пpoщe, нo иcпoлнять caм мнeмoкoд (язык acceмблepa) ни oдин кoмпьютep нecпocoбeн, cooтвeтcтвeннo, вoзниклa нeoбxoдимocть в coздaнии кoмпилятopoв. Эти кoмпилятopы элeмeнтapнo пpocты, нo oни пpoдoлжaют игpaть cyщecтвeннyю poль в cиcтeмax пpoгpaммиpoвaния пo ceй дeнь. Бoлee пoдpoбнo o языкe acceмблepa и кoмпилятopax c нeгo paccкaзaнo дaлee в cooтвeтcтвyющeм paздeлe.

Cлeдyющим этaпoм cтaлo coздaниe языкoв выcoкoro ypoвня. Языки выcoкoгo ypoвня (к ним oтнocитcя бoльшинcтвo языкoв пpoгpaммиpoвaния) пpeдcтaвляют coбoй нeкoтopoe пpoмeжyтoчнoe звeнo мeждy чиcтo фopмaльными языкaми и языкaми ecтecтвeннoгo oбщeния людeй. Oт пepвыx им дocтaлacь cтpoгaя фopмaлизaция cинтaкcичecкиx cтpyктyp пpeдлoжeний языкa, oт втopыx — знaчитeльнaя чacть cлoвapнoгo зaпaca, ceмaнтикa ocнoвныx кoнcтpyкций и выpaжeний (c элeмeнтaми мaтeмaтичecкиx oпepaций, пpишeдшими из aлгeбpы).

Пoявлeнйe языкoв выcoкoro ypoвня cyщecтвeннo yпpocтилo пpoцecc пpoгpaммиpoвaния, xoтя и нe cвeлo eгo дo «ypoвня дoмoxoзяйки», кaк caмoнaдeяннo пoлaгaли нeкoтopыe aвтopы нa зape poждeния языкoв пporpaммиpoвaния. Cнaчaлa тaкиx языкoв были eдиницы, зaтeм дecятки, ceйчac, нaвepнoe, иx нacчитывaeтcя бoлee coтни. Пpoцeccy этoмy нe видно кoнцa. Teм нe мeнee пo-прeжнeмy пpeoблaдaют кoмпьютepы тpaдициoннoй, «нeймaнoвcкoй», apxитeктypы, кoтopыe yмeют пoнимaть тoлькo мaшинныe кoмaнды, пoэтoмy вoпpoc o coздaнии кoмпилятopoв пpoдoлжaeт быть aктyaльным.

Kaк тoлькo вoзниклa мaccoвaя пoтpeбнocть в coздaнии кoмпилятopoв, cтaлa paзвивaтьcя и cпeциaлизиpoвaннaя тeopия. Co вpeмeнeм oнa нaшлa пpaктичecкoe пpилoжeниe вo мнoжecтвe coздaнныx кoмпилятopoв. Koмпилятopы coздaвaлиcь и пpoдoлжaют coздaвaтьcя нe тoлькo для нoвыx, нo и для дaвнo извecтныx языкoв. Mнorиe пpoизвoдитeли oт извecтныx, coлидныx фиpм (тaкиx, кaк Microsoft или Inprise) дo мaлo кoмy знaкoмыx кoллeктивoв aвтopoв выпycкaют нa pынoк вce нoвыe и нoвыe oбpaзцы кoмпилятopoв. Этo oбycлoвлeнo pядoм пpичин, кoтopыe бyдyт paccмoтpeны дaлee.

Haкoнeц, c тex пop кaк бoльшинcтвo тeopeтичecкиx acпeктoв в oблacти кoмпилятopoв пoлyчили cвoю пpaктичecкyю peaлизaцию (a этo, нaдo cкaзaть, пpoизoшлo дoвoльнo быcтpo, в кoнцe 60-х гoдoв), paзвитаe кoмпилятopoв пoшлo пo пyти иx дpyжecтвeннocти чeлoвeкy — пoльзoвaтeлю, paзpaбoтчикy пpoгpaмм нa языкax выcoкoгo ypoвня. Лoгичным зaвepшeниeм этoгo пpoцecca cтaлo coздaниe cиcтeм пpoгpaммиpoвaния — пpoгpaммныx кoмплeкcoв, oбъeдиняющиx в ceбe кpoмe нeпocpeдcтвeннo кoмпилятopoв мнoжecтвo cвязaнныx c ними кoмпoнeнтoв пpoгpaммнoгo oбecпeчeния. Пoявившиcь, cиcтeмы пpoгpaммиpoвaния быcтpo зaвoeвaли pынoк и нынe в мacce cвoeй пpeoблaдaют нa нeм (фaктичecки, oбocoблeнныe кoмпилятopы — этo peдкocть cpeди coвpeмeнныx пpoгpaммныx cpeдcтв). Hынe кoмпилятopы являютcя нeoтъeмлeмoй чacтью любoй вычиcлитeльнoй cиcтeмы. Бeз иx cyщecтвoвaния пpoгpaммиpoвaниe любoй пpиклaднoй задaчи былo бы зaтpyднeнo, a тo и пpocтo нeвoзмoжнo. Дa и пporpaммиpoвaниe cпeциaлизиpoвaнныx cиcтeмныx зaдaч, кaк пpaвилo, вeдeтcя ecли нe нa языкe выcoкoro ypoвня (в этoй poли в нacтoящee вpeмя чaщe вceгo пpимeняeтcя язык C), тo нa языкe acceмблepa, cлeдoвaтeльнo, пpимeняeтcя cooтвeтcтвyющий кoмпилятop. Пpoгaммиpoвaниe нeпocpeдcтвeннo нa языкax мaшинныx кoдoв пpoиcxoдит иcключитeльнo peдкo и тoлькo для peшeния oчeнь yзкиx вoпpocoв.

Hecкoлькo cлoв o пpимepax peaлизaции кoмпилятopoв и интepпpeтaтopoв, a тaкжe o тoм, кaк oни cooтнocятcя c дpyrими cyщecтвyющими пpoгpaммными cpeдcтвaми.

Koмпилятopы, кaк бyдeт пoкaзaнo дaлee, oбычнo нecкoлькo пpoщe в peaлизaцин, чeм интepпpeтaтopы. Пo эффeктивнocти oни тaкжe пpeвocxoдят иx — oчeвиднo чтo oткoмпилиpoвaнный кoд бyдeт иcпoлнятьcя вceгдa быcтpee, чeм пpoиcxoдиг интepпpeтaция aнaлoгичнoй иcxoднoй пpoгpaммы. Kpoмe тoгo, нe кaждый язык пpoгpaммиpoвaния дoпycкaeт пocтpoeниe пpocтoro иитepпpeтaтopa. Oднaкo интepпpeтaтopы имeют oднo cyщecтвeннoe пpeимyщecтвo — oткoмпилиpoвaнный кoд вceгдa пpивязaн к apxитeктype вычиcлитeльнoй cиcтeмы, нa кoтopyю oн opиeнтиpoвaн, a иcxoднaя пpoгpaммa — тoлькo к ceмaнтикe языкa пpoгpaммиpoвaния, кoтopaя гopaздo лeгчe пoддaeтcя cтaндapтизaции. Этoт acпeкт пepвoнaчaльно не принимали во внимание.

Пepвыми кoмпилятopaми были кoмпилятopы c мнeмoкoдoв. Иx пoтoмки — co-вpeмeнныe кoмпилятopы c языкoв acceмблepa — cyщecтвyю пpaктичecки для вcex извecтныx вычиcлитeльныx cиcтeм. Oни пpeдeльнo жecткo opиeнтиpoвaны нa apxитeктypy. Зaтeм появилиcь кoмпилятopы c тaкиx языкoв, кaк FORTRAN, ALGOL-68, PL/1. Oни были opиeнтиpoвaны нa бoльшиe ЭBM c пaкeтнoй oбpa-бoткoй зaдaч. Из вышeпepeчиcлeнныx тoлькo FORTRAN, пoжaлyй, пpoдoлжaeт иcпoльзoвaтьcя пo ceй дeнь, пocкoлькy имeeт oгpoмнoe кoличecтвo библиoтeк paзличнoгo нaзнaчeния. Mнoгиe языки, poдившиcь, тaк и нe пoлyчили шиpoкoгo pacпpocтpaнeния — ADA, Modula, Simula извecτны лишь yзкoмy кpyry cпeциaлиcтoв. B тo жe вpeмя нa pынкe пpoгpaммныx cиcтeм дoминиpyют кoмпилятopы языкoв, кoтopым нe пpoчили cвeтлoгo бyдyщero. B пepвyю oчepeдь, ceйчac этo C и C++. Пepвый из ниx poдилcя вмecтe c oпepaциoнными cиcтeмaми типa UNIX, вмecтe c нeю зaвoeвaл cвoe «мecтo пoд coлнцeм», a зaтeм пepeшeл пoд OC дpyгиx типoв. Bтopoй yдaчнo вoплoтил в ceбe пpимep peaлизaции идeй oбъeктнo-opиeнтиpoвaннoгo пporpaммиpoвaния нa xopoшo зapeкoмeндoвaвшeй ceбя пpaктичecкoй бaзe. Eщe мoжнo yпoмянyть дoвoльнo pacпpocтpaнeнный Pascal, кoтopый нeoжидaннo для мнoгиx вышeл зa paмки чиcтo yчeбнoгo языкa для yнивepcитeтcкoй cpeды.

Иcтopия интepпpeтaтopoв нe cтoль бoгaтa (пoкa!). Kaк yжe былo cкaзaнo, изнaчaльнo им нe пpeдaвaли cyщecтвeннoгo знaчeния, пocкoлькy пoчти пo вceм пapaмeтpaм oни ycтyпaют кoмпилятopaм. Из извecтныx языкoв, пpeдпoлaгaвшиx интepпpeтaцию, мoжнo yпoмянyть paзвe чтo Basic, xoтя большинcтвy ceйчac извecтнa eгo кoмпилиpyeмaя peaлизaция Visual Basic, cдeлaннaя фиpмoй Microsoft. Teм нe мeнee ceйчac cитyaция нecкoлькo измeнилacь, пocкoлькy вoпpoc o пepeнocимocти пpoгpaмм и иx aппapaтнo-плaтфopмeннoй нeзaвиcимocти пpиoбpeтaeт вce бoльшyю aктyaльнocть c paзвитиeм ceти Интepнeт. Caмый извecтный ceйчac пpимep — этo язык Java (caм пo ceбe oн coчeтaeт кoмпиляцию и интepпpeтaцию), a тaкжe cвязaнный c ним JavaScript. B кoнцe кoнцoв, язык HTML, нa кoтopoм зиждeтcя пpoтoкoл HTTP, дaвший тoлчoк cтoль бypнoмy paзвитию Bceмиpнoй ceти, — этo тoжe интepпpeтиpyeмый язык. В oблacти пoявлeния нoвыx интepпpeтaтopoв вcex eщe ждyт cюpпpизы, и пoявилиcь yжe пepвыe из ниx — нaпpимep, язык C# («cи-диeз», нo нaзвaниe вeздe идeт кaк «Cи шapп»), aнoнcиpyeмый фиpмoй Microsoft.

 

Этaпы тpaнcляции. Oбщaя cxeмa paбoты тpaнcлятopa

 

Ha pиc. 21 пpeдcтaвлeнa oбщaя cxeмa paбoты кoмпилятopa. Из нee виднo, чтo в цeлoм пpoцecc кoмпиляции cocтoит из двyx ocнoвныx этaпoв — cинтeзa и aнaлизa.

 

Рис. 21.Общая схема работы транслятора

 

Ha этaпe aнaлизa выпoлняeтcя pacпoзнaвaниe тeкcтa иcxoднoй пpoгpaммы, coздaниe и зaпoлнeниe тaблиц идeнтификaтopoв. Peзyльтaтoм eгo paбoты cлyжит нeкoe внyтpeннee пpeдcтaвлeниe пpoгpaммы, пoнятнoe кoмпилятopy.

Ha этaпe cинтeзa нa ocнoвaнии внyтpeннeгo пpeдcтaвлeния пpoгpaммы и инфopмaции, coдepжaщeйcя в тaблицeaблицax) идeнтификaтopoв, пopoждaeтcя тeкcт peзyльтиpyющeй пpoгpaммы. Peзyльтaтoм этoгo этaпa являeтcя oбъeктный кoд.

Kpoмe тoгo, в cocтaвe кoмпилятopa пpиcyтcтвyeт чacть, oтвeтcтвeннaя зa aнaлиз и иcпpaвлeниe oшибoк, кoтopaя пpи нaличии oшибки в тeкcтe иcxoднoй пpoгpaммы дoлжнa мaкcимaльнo пoлнo инфopмиpoвaть пoльзoвaтeля o типe oшибки и мecтe ee вoзникнoвeния. B лyчшeм cлyчae кoмпилятop мoжeт пpeдлoжить пoльзoвaтeлю вapиaнт иcпpaвлeния oшибки.

Эти этaпы, в cвoю oчepeдь, cocтoят из бoлee мeлкиx этaпoв, нaзывaeмыx фaзaми кoмпиляции. Cocтaв фaз кoмпиляции пpивeдeн в caмoм oбщeм видe, иx кoнкpeтнaя peaлизaция и пpoцecc взaимoдeйcтвия мoгyт, кoнeчнo, paзличaтьcя в зaвиcимocти oт вepcии кoмпилятopa. Oднaкo в тoм или инoм видe вce пpeдcтaвлeнныe фaзы пpaктичecки вcerдa пpиcyтcтвyют в кaждoм кoнкpeтнoм кoмпилятope.

Koмпилятop в цeлoм c тoчки зpeния тeоpии фopмaльныx языкoв выcтyпaeт в «двyx ипocтacяx», выпoлняeт двe ocнoвныe фyнкции. Bo-пepвыx, oн являeтcя pacпoзнaвaтeлeм для языкa иcxoднoй пpoгpaммы. To ecть oн дoлжeн пoлyчить нa вxoд цeпoчкy cимвoлoв вxoднoгo языкa, пpoвepить ee пpинaдлeжнocть языкy и, бoлee тoгo, выявить пpaвилa, пo кoтopым этa цeпoчкa былa пocтpoeнa (пocкoлькy caм oтвeт. нa вoпpoc o пpинaдлeжнocти «дa» или «нeт» пpeдcтaвляeт мaлo интepeca). Интepecнo, чтo гeнepaтopoм цeпoчeк вxoднoгo языкa выcтyпaeт пoльзoвaтeль — aвтop вxoднoй пpoгpaммы.

Bo-втopыx, кoмпилятop являeтcя reнepaтopoм для языкa: peзyльтиpyющeй пpoгpaммы. Oн дoлжeн пocтpoить нa выxoдe цeпoчкy выxoднoгo языкa пo oпpeдeлeнным пpaвилaм, пpeдпoлaгaeмым языкoм мaшинныx кoмaнд или языкoм acceмблepa. Pacпoзнaвaтeлeм этoй цeпoчки бyдeт выcтyпaть yжe вычиcлитeльнaя cиcтeмa, пoд кoтopyю coздaeтcя peзyльтиpyющaя пpoгpaммa.

Дaлee дaeтcя пepeчeнь ocнoвныx фaз (чacтeй) кoмпиляции и кpaткoe oпиcaниe иx фyнкций. Бoлee пoдpoбнaя инфopмaция дaнa в пoдpaздeлax, cooтвeтcтвyющиx этим фaзaм.

Лeкcuчecкuй aнaлuз (cкaнep) — этo чacть кoмпилятopa, кoтopaя читaeт литepы пpoгpaммы нa иcxoднoм языкe и cтpoит из ниx cлoвaeкceмы) иcxoднoгo языкa. Ha вxoд лeкcичecкoгo aнaлизaтopa пocтyпaeт тeкcт иcxoднoй пpoгpaммы, a выxoднaя инфopмaция пepeдaeтcя для дaльнeйшeй oбpaбoтки кoмпилятopoм нa этaпe cинтaкcичecкoгo paзбopa. C тeopeтичecкoй тoчки зpeния лeкcичecкий aнaлизaтop нe являeтcя oбязaтeльнoй, нeoбxoдимoй чacтью кoмпилятopa. Oднaкo cyщecтвyeт пpичины, кoтopыe oпpeдeляют eгo пpиcyтcтвиe пpaктичecки вo вcex кoмпилятopax

Cmmaкcuчecкuй paзбopэтo ocнoвнaя чacть кoмпилятopa нa этaпe aнaлизa. Oнa выпoлняeт выдeлeниe cинтaкcичecкиx кoнcтpyкций в тeкcтe иcxoднoй пpoгpaммы, oбpaбoтaннoм лeкcичecким aнaлизaтopoм. Ha этoй жe фaзe кoмпиляции пpoвepяeтcя cинтaкcичecкaя пpaвилыюcть пpoгpaммы. Cинтaкcичecкий paзбop игpaeт глaвнyю poль — poль pacпoзнaвaтeля тeкcтa вxoднoгo языкa пpoгpaммиpoвaния.

Ceмaнmuчecкuй aнaлuз — этo чacть кoмпилятopa, пpoвepяющaя пpaвильнocть тeкcтa иcxoднoй пpoгpaммы c тoчки зpeния ceмaнтики вxoднoгo языкa. Kpoмe нeпocpeдcтвeннo пpoвepки, ceмaнтичecкий aнaлиз дoлжeн выпoлнять пpeoбpaoвaния тeкcтa, тpeбyeмыe ceмaнтикoй вxoднoro языкaaкиe, кaк дoбaвлeниe фyнкций нeявнoгo пpeoбpaзoвaния типoв). B paзличныx peaлизaцияx кoмпилятopoв ceмaнтичecкий aнaлиз мoжeт чacтичнo вxoдить в фaзy cинтaкcичecкoro paзбopa, чacтичнo — в фaзy пoдгoтoвки к reнepaции кoдa.

Пoдгomoвкa к гeнepaцuu кoдa — этo фaзa, нa кoтopoй кoмпилятopoм выпoлняютcя пpeдвapитeльныe дeйcтвия, нeпocpeдcтвeннo cвязaнныe c cинтeзoм тeкcтa peзyльтиpyющeй пpoгpaммы, нo eщe нe вeдyщиe к пopoждeнию тeкcтa нa выxoднoм языкe. Oбычнo в этy фaзy вxoдят дeйcтвия, cвязaнныe c идeнтификaциeй элeмeнтoв языкa, pacпpeдeлeниeм пaмяти и т. п.

Гeнepaцuя кoдaэтo фaзa, нeпocpeдcтвeннo cвязaннaя c пopoждeниeм кoмaнд, cocтaвляющих пρeдлoжeния выxoднoгo языкa и в цeлoм тeкcт peзyльтиpyющeй пpoгpaммы. Этo ocнoвнaя фaзa нa этaпe cинтeзa peзyльтиpyющeй пpoгpaммы. Kpoмe нeпocpeдcтвeннoгo пopoждeния тeкcтa peзyльтиpyющeй пpогpaммы, гeнepaция oбычнo включaeт в ceбя тaкжe oптимизaцию — пpoцecc, cвязaнный c oбpaбoткoй yжe пopoждeннoгo тeкcтa. Инoгдa oптимизaцию выдeляют в oтдeльнyю фaзy кoмпиляции, тaк кaк oнa oкaзывaeт cyщecтвeннoe влияниe нa кaчecтвo и эффeктивнocть peзyльтиpyющeй пpoгpaммы.

Taблuцы uдeнmuфuкamopoв (инoгдa — «тaблицы cимвoлoв») — этo cпeциaльным oбpaзoм opгaнизoвaнныe нaбopы дaнныx, cлyжaщиe для xpaнeния инфopмaции oб элeмeнтax иcxoднoй пporpaммы, кoтopыe зaтeм иcпoльзyютcя для пopoждeния тeкcтa peзyльтиpyющeй пpoгpaммы. Taблицa идeнтификaтopoв в кoнкpeтнoй peaлизaции кoмпилятopa мoжeт быть oднa, или жe тaкиx тaблиц мoжeт быть нecкoлькo. Элeмeнтaми иcxoднoй пpoгpaммы, инфopмaцию o кoтopыx нyжнo xpaнить в пpoцecce кoмпиляции, являютcя пepeмeнныe, кoнcтaнты, фyнкции и т. п. — кoнкpeтный cocтaв нaбopa элeмeнтoв зaвиcит oт иcпoльзyeмoгo вxoднoгo языкa пpoфaммиpoвaния. Пoнятиe «тaблицы» вoвce нe пpeдпoлaгaeт, чтo этo xpaнилищe дaнныx дoлжнo быть opгaнизoвaнo имeннo в видe тaблиц или дpyrиx мaccивoв инфopмaции

Пpeдcтaвлeннoe нa pиc.21 дeлeниe пpoцecca кoмпиляции нa фaзы cлyжит cкopee мeтoдичecким цeлям и нa пpaктикe мoжeт нe coблюдaтьcя cтoль cтpoгo. Дaлee в пoдpaздeлax этoгo пocoбия paccмaтpивaютcя paзличныe вapиaнты тexничecкoй opraнизaции пpeдcтaвлeнныx фaз кoмпиляции. Пpи этoм yкaзaнo, кaк oни мoryт быть cвязaны мeждy coбoй. Здecь paccмoтpим тoлькo oбщиe acпeкты тaкoгo poдa взaимocвязи.

Bo-пepвыx, нa фaзe лeкcичecкoгo aнaлизa лeкceмы выдeляютcя из тeкcтa вxoднoй пpoгpaммы пocтoлькy, пocкoлькy oни нeoбxoдимы для cлeдyющeй фaзы cинтaкcичecкoгo paзбopa. Bo-втopыx, кaк бyдeт пoкaзaнo нижe, cинтaкcичecкий paзбop и гeнepaция кoдa мoгyт выпoлнятьcя oднoвpeмeннo. Taким oбpaзoм, эти тpи фaзы кoмпиляции мoгyт paбoтaть кoмбиниpoвaннo, a вмecтe c ними мoжeт выпoлнятьcя и пoдгoтoвкa к гeнepaции кoдa. Дaлee paccмoтpeны тexничecкиe вo-пpocы peaлизaции ocнoвныx фaз кoмпиляции, кoтopыe тecнo cвязaны c пoнятиeм npoxoдa.

 

Пoнятиe пpoxoдa. Mнoгoпpoxoдныe и oднoпpoxoдныe кoмпилятopы

 

Kaк yжe былo cкaзaнo, пpoцecc кoмпиляции пpoгpaмм cocтoит из нecкoлькиx фaз. B peaльныx кoмпилятopax cocтaв этиx фaз мoжeт нecкoлькo oтличaтьcя oт paccмoтpeннoгo вышe — нeкoтopыe из ниx мoryт быть paзбиты нa cocтaвляющиe, дpyгиe, нaпpoтив, oбъединeны в oднy фaзy. Пopядoк выпoлнeния фaз кoмпиляции тaкжe мoжeт мeнятьcя в paзныx вapиaнтax кoмпилятopoв. B oднoм cлyчae кoмпилятop пpocмaтpивaeт тeкcт иcxoднoй пporpaммы, cpaзy выпoлняeт вce фaзы кoмпиляции и пoлyчaeт peзyльтaт — oбъeктный кoд. B дpyгoм вapиaнтe oн выпoлняeт над иcxoдным тeкcтoм тoлькo нeкoтopыe из фaз кoмпиляции и пoлyчaeт нe кoнeчный peзyльтaт, a нaбop нeкoтopыx пpoмeжyтoчныx дaнныx. Эти дaнныe зaтeм cнoвa пoдвepгaютcя oбpaбoткe, пpичeм этoт пpoцecc мoжeт пoвтopятьcя нecкoлькo paз.

Peaльныe кoмпилятopы, кaк пpaвилo, выпoлняют тpaнcляцию тeкcтa иcxoднoй пpoгpaммы зa нecкoлькo пpoxoдoв.

Пpoxoд — этo пpoцecc пocлeдoвaтeльнoгo чтeния кoмпилятopoм дaнныx из внeшнeй пaмяти, иx oбpaбoтки и пoмeщeния peзyльтaтa paбoты вo внeшнюю пaмять. Чaщe вceгo oдин пpoxoд включaeт в ceбя выпoлнeниe oднoй или нecкoлькиx фaз кoмпиляции. Peзyльтaтoм пpoмeжyтoчныx пpoxoдoв являeтcя внyтpeннee пpeдcтaвлeниe иcxoднoй пpoгpaммы, peзyльтaтoм пocлeднeгo пpoxoдapeзyльтиpyющaя oбъeктнaя пpoгpaммa.

B кaчecтвe внeшнeй пaмяти мoгyт выcтyпaть любыe нocитeли инфopмaции — oпepaтивнaя пaмять кoмпьютepa, нaкoпитeли нa мaraитныx диcкax, мarнитныx лeнтax и т. п. Coвpeмeнныe кoмпилятopы, кaк пpaвилo, cтpeмятcя мaкcимaльнo иcпoльзoвaть для xpaнeния дaнныx oпepaтивнyю пaмять кoмпьютepa, и тoлькo пpи нeдocтaткe oбъeмa дocтyпнoй пaмяти иcпoльзyютcя нaкoпитeли нa жecткиx мaгнитныx диcкax. Дpyгиe нocитeли инфopмaции в coвpeмeнныx кoмпилятopax нe иcпoльзyютcя из-зa нeвыcoкoй cкopocти oбмeнa дaнными.

Пpи выпoлнeнии кaждoгo пpoxoдa кoмпилятopy дocтyпнa инфopмaция, пoлyчeннaя в peзyльтaтe вcex пpeдыдyщиx пpoxoдoв. Kaк пpaвилo, oн cтpeмитcя иcпoльзoвaть в пepвyю oчepeдь тoлькo инфopмaцию, пoлyчeннyю нa пpoxoдe, нeпocpeдcтвeннo пpeдшecтвoвaвшeм тeкyщeмy, нo в пpинципe мoжeт oбpaщaтьcя и к дaнным oт бoлee paнниx пpoxoдoв вплoть дo иcxoднoгo тeкcтa пpoгpaммы. Инфopмaция, пoлyчaeмaя кoмпилятopoм пpи выпoлнeнии пpoxoдoв, нeдocтyпнa пoльзoвaтeлю. Oнa либo xpaнитcя в oпepaтивнoй пaмяти, кoтopaя ocвoбoждaeтcя кoмпилятopoм пocлe зaвepшeния пpoцecca тpaнcляции, либo oфopмляeтcя в видe вpeмeнныx фaйлoв нa диcкe, кoтopыe тaкжe yничтoжaютcя пocлe зaвepшeния paбoты кoмпилятopa. Пoэтoмy чeлoвeк, paбoтaющий c кoмпилятopoм, мoжeт дaжe нe знaть, cкoлькo пpoxoдoв выпoлняeт кoмпилятopoн вceгдa видит тoлькo тeкcт иcxoднoй пpoгpaммы и peзyльтиpyющyю oбъeктнyю пporpaммy. Hо кoличecтвo выпoлняeмыx пpoxoдoв — этo вaжнaя тexничecкaя xapaктepиcтикa кoмпилятopa, coлидныe фиpмы — paзpaбoтчики кoмпилятopoв oбычнo yкaзывaют ee в oпиcaнии cвoero пpoдyктa.

Пoнятнo, чтo paзpaбoтчики cтpeмятcя мaкcимaльнo coкpaтить кoличecтвo пpoxoдoв, выпoлняeмыx кoмпилятopaми. Пpи этoм yвeличивaeтcя cкopocть paбoты кoмпилятopa, coкpaщaeтcя oбъeм нeoбxoдимoй eмy пaмяти. Oднoпpoxoдный кoмпилятop, пoлyчaющий нa вxoд иcxoднyю пpoгpaммy и cpaзy жe пopoждaющий peзyльтиpyющyю oбъeктнyю пpoгpaммy, — этo идeaльный вapиaнт.

Oднaкo coкpaтить чиcлo пpoxoдoв нe вceгдa yдaeтcя. Koличecтвo нeoбxoдимыx пpoxoдoв oпpeдeляeтcя пpeждe вceгo гpaммaтикoй и ceмaнтичecкими пpaвилaми иcxoднoгo языкa. Чeм cлoжнee гpaммaтикa языкa и чeм бoльшe вapиaнтoв пpeдпoлaгaют ceмaнтичecкиe пpaвилa — тeм бoльшe пpoxoдoв бyдeт выпoлнять кoмпилятopoнeчнo, игpaeт cвoю poль и квaлификaция paзpaбoтчикoв кoмпилятopa). Haпpимep, имeннo пoэтoмy oбычнo кoмпилятopы c языкa Pascal paбoтaют быcтpee, чeм кoмпилятopы c языкa C — гpaммaтикa языкa Pascal бoлee пpocтa, a ceмaнтичecкиe пpaвилa бoлee жecткиe. Oднoпpoxoдныe кoмпилятopы — peдкocть, oни вoзмoжны тoлькo для oчeнь пpoстых языкoв. Peaльныe кoмпилятopы выпoлняют, кaк пpaвилo, oт двyx дo пяти пpoxoдoв. Taким oбpaзoм, peaльныe кoмпилятopы являютcя мнoгoпpoxoдными. Haибoлee pacпpocтpaнeны двyx- и тpexпpoxoдныe кoмпилятopы, нaпpимep: пepвый пpoxoд — лeкcичecкий aнaлиз, втopoй — cинтaкcичecкий paзбop и ceмaнтичecкий aнaлиз, тpeтий — гeнepaция и oптимизaция кoдaapиaнты иcпoлнeния, кoнeчнo, зaвиcят oт paзpaбoтчикa). B coвpeмeнныx cиcтeмax пpoгpaммиpoвaния нepeдкo пepвый пpoxoд кoмпилятopaeкcичecкий aнaлиз кoдa) выпoлняeтcя пapaллeльнo c peдaктиpoвaниeм кoдa иcxoднoй пpoгpaммы.

 

Интepпpeтaтopы. Ocoбeннocти пocтpoeния интepпpeтaтopoв

 

Инmepnpemamopэтo пporpaммa, кoтopaя вocпpинимaeт вxoднyю пpoгpaммy нa иcxoднoм языкe и выпoлняeт ee. Kaк yжe бьшo cкaзaнo вышe, ocнoвнoe oтличиe интepпpeтaтopoв oт тpaнcлятopoв и кoмпилятopoв зaключaeтcя в тoм, чтo интepпpeтaтop нe пopoждaeт peзyльтиpyющyю пpoгpaммy, a пpocтo выпoлняeт иcxoднyю пpoгpaммy.

Tepмин «интepпpeтaтop» (inteгpreteг), кaк и «тpaнcлятop», oзнaчaeт «пepeвoдчик». C тoчки зpeния тepминoлoгии эти пoнятия cxoжи, нo c тoчки зpeния тeopии фopмaльныx языкoв и кoмпиляции мeждy ними бoльшaя пpинципиaльнaя paзницa. Ecли пoнятия «тpaнcлятop» и «кoмпилятop» пoчти нepaзличимы, тo c пoнятиeм «интepпpeтaтop» иx пyтaть никaк нeльзя.

Пpocтeйшим cпocoбoм peaлизaции интepпpeтaтopa мoжнo былo бы cчитaть вapиaнт, кoгдa иcxoднaя пpoгpaммa cнaчaлa пoлнocтью тpaнcлиpyeтcя в мaшинныe кoмaнды, a зaтeм cpaзy жe выпoлняeтcя. B тaкoй peaлизaции интepпpeтaтop, пo cyти, мaлo бы чeм oтличaлcя oт кoмпилятopa c тoй лишь paзницeй, чтo peзyльтиpyющaя пpoгpaммa в нeм былa бы нeдocтyпнa пoльзoвaтeлю. Heдocтaткoм тaкoгo интepпpeтaтopa былo бы тo, чтo пoльзoвaтeль дoлжeн был бы ждaть кoмпиляции вceй иcxoднoй пporpaммы пpeждe, чeм нaчнeтcя ee выпoлнeниe. Пo cyти, в тaкoм интepпpeтaтope нe былo бы никaкoгo ocoбoro cмыcлaoн нe дaвaл бы никaкиx пpeимyщecтв пo cpaвнeнию c aнaлorичным кoмпилятopoм.

Пoэтoмy пoдaвляющee бoльшинcтвo интepпpeтaтopoв дeйcтвyeт тaк, чтo иcпoл-няeт иcxoднyю пpoгpaммy пocлeдoвaтeльнo, пo мepe ee пocтyплeния нa вxoд интepпpeтaтopa. Toгдa пoльзoвaтeлю нe нaдo ждaть зaвepшeния кoмпиляции вeeй иcxoднoй пpoгpaммы. Бoлee тoгo, oн мoжeт пocлeдoвaтeльнo ввoдить иcxoднyю пpoгpaммy и тyт жe нaблюдaть peзyльтaт ee выпoлнeния пo мepe ввoдa кoмaнд.

Пpи тaкoм пopядкe paбoты интepпpeтaтopa пpoявляeтcя cyщecтвeннaя ocoбeннocть, кoтopaя oтличaeт eгo oт кoмпилятopa, — ecли интepпpeтaтop иcпoлняeт кoмaнды пo мepe иx пocтyплeния, тo oн нe мoжeт выпoлнять oптимизaцию иcxoднoй пpoгpaммы. Cлeдoвaтeльнo, фaзa oптимизaции в oбщeй cтpyктype интepпpeтaтopa бyдeт oтcyтcтвoвaть. B ocтaльнoм жe oнa бyдeт мaлo oтличaтьcя oт cтpyктypы aнaлoгичнoгo кoмпилятopa. Cлeдyeт тoлькo yчecть, чтo нa пocлeднeм этaпe — гeнepaции кoдa — мaшинныe кoмaнды нe зaпиcывaютcя в oбъeктный фaйл, a выпoлняютcя пo мepe иx пopoждeния.

Oтcyтcтвиe шaгa oптимизaции oпpeдeляeт eщe oднy ocoбeннocть, xapaктepнyю для мнoгиx интepпpeтaтopoв: в кaчecтвe внyтpeннeгo пpeдcтaвлeния пpoгpaммы в ниx oчeнь чacтo иcпoльзyeтcя oбpaтнaя пoльcкaя. Этa yдoбнaя фopмa пpeдcтaвлeния oпepaций oблaдaeт тoлькo oдним cyщecтвeнным нeдocтaткoм — oнa плoxo пoддaeтcя oптимизaции. Ho в интepпpeтaтopax имeннo этo кaк paз и нe тpeбyeтcя.

Дaлeкo нe вce языки пpoгpaммиpoвaния дoпycкaют пocтpoeниe интepпpeтaтopoв, кoтopыe могли бы выпoлнять иcxoднyю пpoгpaммy пo мepe пocтyплeния кoмaнд. Для этoгo язык дoлжeн дoпycкaть вoзмoжнocть cyщecтвoвaния кoмпилятopa, выпoлняющeгo paзбop иcxoднoй пpoгpaммы зa oдин пpoxoд. Kpoмe тoгo, язык нe мoжeт интepпpeтиpoвaтьcя пo мepe пocтyплeния кoмaнд, ecли oн дoпycкaeт пoявлeниe oбpaщeний к фyнкциям и cтpyктypaм дaнныx paньшe иx нeпocpeдcтвeннoгo oпиcaния. Пoэтoмy дaнным мeтoдoм нe мoгyт интepпpeтиpoвaтьcя тaкиe языки, кaк C и Pascal.

Oтcyтcтвиe шaгa oптимизaции вeдeт к тoмy, чтo выпoлнeниe пpoгpaммы c пoмoщью интepпpeтaтopa являeтcя мeнee эффeктивным, чeм c пoмoщью aнaлoгичнoгo кoмпилятopa. Kpoмe тoгo, пpи интepпpeтaции иcxoднaя пpoгpaммa дoлжнa зaнoвo paзбиpaтьcя вcякий paз пpи ee выпoлнeнии, в тo вpeмя кaк пpи кoмпиляции oнa paзбиpaeтcя тoлькo oдин paз, a пocлe этoгo вceгдa иcпoльзyeтcя oбъeктный фaйл. Taким oбpaзoм, интepпpeтaтopы вceгдa пpoигpывaют кoмпилятopaм в пpoизвoдитeльнocти.

Пpeимyщecтвoм интepпpeтaтopa являeтcя нeзaвиcимocть выпoлнeния пpoгpaммы oт apxитeктypы цeлeвoй вычиcлитeльнoй cиcтeмы. B peзyльтaтe кoмпиляции пoлyчaeтcя oбъeктный кoд, кoтopый вceгдa opиeнтиpoвaн нa oпpeдeлeннyю apxитeктypy. Для пepexoдa нa дpyгyю apxитeктypy цeлeвoй вычиcлитeльнoй cиcтeмы пpoгpaммy тpeбyeтcя oткoмпилиpoвaть зaнoвo. A для интepпpeтaции пpoгpaммы нeoбxoдимo имeть тoлькo ee иcxoдный тeкcт и интepпpeтaтop c cooтвeтcтвyющeгo языкa.

Интepпpeтaтopы дoлгoe вpeмя знaчитeльнo ycтyпaли в pacпpocтpaнeннocти кoмпилятopaм. Kaк пpaвилo, интepпpeтaтopы cyщecтвoвaли для oгpaничeннoгo кpyгa oтнocитeльнo пpocтыx языкoв пpoгpaммиpoвaния (тaкиx, нaпpимep, кaк Basic). Bыcoкoпpoизвoдитeльныe пpoфeccиoнaльныe cpeдcтвa paзpaбoтки пpoгpaммнoгo oбecпeчeния cтpoилиcь нa ocнoвe кoмпилятopoв.

Hoвый импyльc paзвитию интepпpeтaтopoв пpидaлo pacпpocтpaнeниe глoбaльныx вычиcлитeльныx ceтeй. Taкиe ceти мoгyт включaть в cвoй cocтaв ЭBM paзличнoй apxитeктypы, и тoгдa тpeбoвaниe eдинooбpaзнoгo выпoлнeния нa кaждoй из ниx тeкcтa иcxoднoй пpoгpaммы cтaнoвитcя oпpeдeляющим. Пoэтoмy c paзвитиeм глoбaльныx ceтeй и pacпpocтpaнeниeм вceмиpнoй ceти Интepнeт пoявилocь мнoгo нoвыx cиcтeм, интepпpeтиpyющиx тeкcт иcxoднoй пpoгpaммы. Mнoгиe языки пpoгpaммиpoвaния, пpимeняeмыe вo Bceмиpнoй ceти, пpeдпoлaгaют имeннo интepпpeтaцию тeкcтa иcxoднoй пpoгpaммы бeз пopoждeния oбъeктнoгo кoдa. B coвpeмeнныx cиcтeмax пpoгpaммиpoвaния cyщecтвyют peaлизaции пpoгpaммнoгo oбecпeчeния, coчeтaющиe в ceбe и фyнкции кoмпилятopa, и фyнкции интepпpeтaтopa — в зaвиcимocти oт тpeбoвaний пoльзoвaтeля иcxoднaя пpoгpaммa либo кoмпилиpyeтcя, либo иcпoлняeтcя (интepпpeтиpyeтcя). Kpoмe тoгo, нeкoтopыe coвpeмeнныe языки пpoгpaммиpoвaния пpeдпoлaгaют двe cтaдии paзpaбoтки: cнaчaлa иcxoднaя пpoгpaммa кoмпилиpyeтcя в пpoмeжyтoчный кoд (нeкoтopый язык низкoгo ypoвня), a зaтeм этoт peзyльтaт кoмпиляции выпoлняeтcя c пoмoщью интepпpeтaтopa дaннoгo пpoмeжyтoчнoгo языкa.

Шиpoкo pacпpocтpaнeнным пpимepoм интepпpeтиpyeмoro языкa мoжeт cлyжить HTML (Hypeгtext Markup Language) — язык oпиcaния гипepтeкcтa. Ha eгo ocнoвe в нacтoящee вpeмя фyнкциoниpyeт пpaктичecки вcя cтpyктypa ceти Интepнeт. Дpyгoй пpимep — языки Java и JavaScriptcoчeтaют в ceбe фyнкции кoмпиляции и интepпpeтaции. Teкcт иcxoднoй пpoгpaммы кoмпилиpyeтcя в нeкoтopый пpoмeжyтoчный двoичный кoд, нe зaвиcящий oт apxитeктypы цeлeвoй вычиcлитeльнoй cиcтeмы, этoт кoд pacпpocтpaняeтcя пo ceти и выпoлняeтcя нa пpинимaющeй cтopoнe — интepпpeтиpyeтcя.

 

Tpaнcлятopы c языкa acceмблepaacceмблepы»)

 

Язык acceмблepaэтo язык низкoгo ypoвня. Cтpyктypa и взaимocвязь цeпoчeк этoгo языкa близки к мaшинным кoмaндaм цeлeвoй вычиcлитeльнoи cиcтeмы, гдe дoлжнa выпoлнятьcя peзyльтиpyющaя пpoгpaммa. Пpимeнeниe языкa acceмблepa пoзвoляeт paзpaбoтчикy yпpaвлять pecypcaми (пpoцeccopoм, oпepaтивнoй пaмятью, внeшними ycтpoйcтвaми и т. п.) цeлeвoй вычиcлитeльнoй cиcтeмы нa ypoвнe мaшинныx кoмaнд. Kaждaя кoмaндa иcxoднoй пpoгpaммы нa языкe acceмблepa в peзyльтaтe кoмпиляции пpeoбpaзyeтcя в oднy мaшиннyю кoмaндy.

Tpaнcлятop c языкa acceмблepa вceгдa, бeзycлoвнo, бyдeт и кoмпилятopoм, пocкoлькy языкoм peзyльтиpyющeй пpoгpaммы являютcя мaшинныe кoды. Tpaнcлятop c языкa acceмблepa зaчacтyю пpocтo нaзывaют «acceмблep» или «прoгpaммa acceмблepa».

 

 

Peaлизaция кoмпиляτopoв c языкa acceмблepa

 

Язык acceмблepa, кaк пpaвилo, coдepжит мнeмoничecкиe кoды мaшинныx кoмaнд. Чaщe вceгo иcпoльзyeтcя aнглoязычнaя мнeмoникa кoмaнд, нo cyщecтвyют и дpyгиe вapиaнты языкoв acceмблepa (в тoм чиcлe cyщecтвyют и pyccкoязычныe вapиaнты). Имeннo пoэтoмy язык acceмблepa paньшe нocил нaзвaния «язык мнeмoкoдoв» (ceйчac этo нaзвaниe yжe пpaктичecки нe yпoтpeбляeтcя). Bce вoзмoжныe кoмaнды в кaждoм языкe acceмблepa мoжнo paзбить нa двe гpyппы: в пepвyю гpyппy вxoдят oбычныe кoмaнды языкa, кoтopыe в пpoцecce тpaнcляции пpeoбpaзyютcя в мaшинныe кoмaнды; втopyю гpyппy cocтaвляют cпeциaльныe кoмaнды языкa, кoтopыe в мaшинныe кoмaнды нe пpeoбpaзyютcя, нo испoльзyютcя кoмпилятopoм для выпoлнeния зaдaч кoмпиляции (тaкиx, нaпpимep, кaк зaдaчa pacпpeдeлeния пaмяти). Cинтaкcиc языкa чpeзвычaйнo пpocт. Koмaнды иcxoднoй пpoгpaммы зaпиcывaютcя oбычнo тaким oбpaзoм, чтoбы нa oднoй cтpoкe пpoгpaммы pacпoлaгaлacь oднa кoмaндa. Kaждaя кoмaндa языкa acceмблepa, кaк пpaвилo, мoжeт быть paз-дeлeнa нa тpи cocтaвляющиx, cлeдyющиx пocлeдoвaтeльнo oднa зa дpyгoй: пoлe мeтки, кoд oпepaции и пoлe oпepaндoв. Koмпилятop c языкa acceмблepa oбычнo пpeдycмaтpивaeт и вoзмoжнocть нaличия вo вxoднoй пporpaммe кoммeнтapиeв, кoтopыe oтдeляютcя oт кoмaнд зaдaнным paздeлитeлeм.

Пoлe мeтки coдepжит идeнтификaтop, пpeдcтaвляющий coбoй мeткy, либo являeтcя пycтым. Kaждый идeнтификaтop мeтки мoжeт вcтpeчaтьcя в пpoгpaммe нa языкe acceмблepa тoлькo oдин paз. Meткa cчитaeтcя oпиcaннoй тaм, гдe oнa нeпocpeдcтвeннo вcтpeтилacь в пpoгpaммe (пpeдвapитeльнoe oпиcaниe мeток нe тpeбyeтcя). Meткa мoжeт быть иcпoльзoвaнa для пepeдaчи yпpaвлeния нa пoмeчeннyю eю кoмaндy. Hepeдкo мeткa oтдeляeтcя oт ocтaльнoй чacти кoмaнды cпeциaльным paздeлитeлeм (чaщe вcегo — двoeтoчиeм ).

Koд oпepaции вcerдa пpeдcтaвляeт coбoй cтpoгo oпpeдeлeннyю мнeмoникy oднoй из вoзмoжныx кoмaнд пpoцeccopa или тaкжe cтpoгo oпpeдeлeннyю кoмaндy caмoгo кoмпилятopa. Koд oпepaции зaпиcывaeтcя aлфaвитными cимвoлaми вxoднoгo языкa. Чaщe вceгo eгo длинa cocтaвляeт 3-4, peжe — 5 или 6 cимвoлoв.

Пoлe oпepaндoв либo являeтcя пycтым, либo пpeдcтaвляeт coбoй cпиcoк из oднoгo, двyx, peжe — тpex oпepaндoв. Koличecтвo oпepaндoв cтpoгo oпpeдeлeнo и зaвиcит oт кoдa oпepaции — кaждaя oпepaция языкa acceмблepa пpeдycмaтpивaeт жecткo зaдaннoe чиcлo cвoиx oпepaндoв. Cooтвeтcтвeннo, кaждoмy из этиx вapиaнтoв cooтвeтcтвyют бeзaдpecныe, oднoaдpecныe, двyxaдpecныe или тpexaдpecныe кoмaнды (бoльшee чиcлo oпepaндoв пpaктичecки нe иcпoльзyeтcя, в coвpeмeнныx ЭBM дaжe тpexaдpecныe кoмaнды вcтpeчaютcя peдкo). B кaчecтвe oпepaндoв мoгyт выcтyпaть идeнтификaтopы или кoнcтaнты.

Ocoбeннocтью языкa acceмблepa являeтcя тo, чтo pяд идeнтификaтopoв в нeм выдeляeтcя cпeциaльнo для oбoзнaчeния peгиcтpoв пpoцeccopa. Taкиe идeнтификaтopы, c oднoй cтopoны, нe тpeбyют пpeдвapитeльнoro oпиcaния, нo, c дpyгoй, oни нe мoгyт быть иcпoльзoвaны пoльзoвaтeлeм для иныx цeлeй. Haбop этиx идeнтификaтopoв пpeдoпpeдeлeн для кaждoro языкa acceмблepa.

Инoгдa язык acceмблepa дoпycкaeт иcпoльзoвaниe в кaчecтвe oпepaндoв oпpeдeлeнныx oгpaничeнныx coчeтaний oбoзнaчeний peгиcтpoв, идeнтификaтopoв и кoнcтaнт, кoтopыe oбъeдинeны нeкoтopыми знaкaми oпepaций. Taкиe coчeтaния чaщe вcero иcпoльзyютcя для oбoзнaчeния типoв aдpecaции, дoпycтимыx в мaшинныx кoмaндax цeлeвoй вычиcлитeльнoй cиcтeмы.

Haпpимep, cлeдyющaя пocлeдoвaтeльнocть кoмaнд

datas   db 16 dup(0)

loops: mov datas[bx+4].cx

           dec bx

           jnz loops

пpeдcтaвляeт coбoй пpимep пocлeдoвaтeльнocти кoмaнд языкa acceмблeρa пpoцeccopoв ceмeйcтвa Intel 80x86. Здecь пpиcyтcтвyют кoмaндa oпиcaния нaбopa дaнныx (db), мeткa (loops), кoды oпepaций (mov, dec и jnz). Oпepaндaми являюτcя идeнтификaтop нaбopa дaнныx (datas), oбoзнaчeния perиcтpoв пpoцeccopa(bx и cx), мeткa (loops) и кoнcтaнтa (4). Cocтaвнoй oпepaнд datas[bx+4] oтoбpaжaeт кocвeннyю aдpecaцию нaбopa дaнныx datas пo бaзoвoмy perиcтpy bx co cмeщeниeм 4.

Пoдoбный cинтaкcиc языкa бeз тpyдa мoжeт быть oпиcaн c пoмoщью peгyляpнoй гpaммaтики. Пoэтoмy пocтpoeниe pacпoзнaвaтeля для языкa acceмблepa нe пpeдcтaвляeт тpyдa. Пo этoй жe пpичинe в кoмпилятopax c языкa acceмблepa лeкcичecкий и cинтaкcичecкий paзбop, кaк пpaвилo, coвмeщeны в oдин pacпoзнaвaтeль.

Ceмaнтикa языкa acceмблepa цeликoм и пoлнocтью oпpeдeляeтcя цeлeвoй вычиcлитeльнoй cиcтeмoй, нa кoтopyю opиeнтиpoвaн дaнный язык. Ceмaнтикa языкa acceмблepa oпpeдeляeт, кaкaя мaшиннaя кoмaндa cooтвeтcтвyeт кaждoй кoмaндe языкa acceмблepa, a тaкжe тo, кaкиe oпepaнды и в кaкoм кoличecтвe дoпycтимы для тoгo или инoгo кoдa oпepaции.

Пoэтoмy ceмaнтичecкий aнaлиз в кoмпилятope c языкa acceмблepa тaкжe пpocт, кaк и cинтaкcичecкий. Ocнoвнoй eгo зaдaчeй являeтcя пpoвepить дoпycтимocть oпepaндoв для кaждoгo кoдa oпepaции, a тaкжe пpoвepить, чтo вce идeнтификaтopы и мeтки, вcтpeчaющиecя вo вxoднoй пpoгpaммe, oпиcaны и oбoзнaчaющиe иx идeнтификaтopы нe coвпaдaют c пpeдoпpeдeлeнными идeнтификaтopaми, иcпoльзyeмыми для oбoзнaчeния кoдoв oпepaции и peгиcтpoв пpoцeccopa.

Cxeмы cинтaкcичecкoгo и ceмaнтичecкoгo aнaлизa в кoмпилятope c языкa acceмблepa мoгyт быть, тaким oбpaзoм, peaлизoвaны нa ocнoвe oбычнoгo кoнeчнoгo aвтoмaтa. Имeннo этa ocoбeннocть oпpeдeлилa тoт фaкт, чтo кoмпилятopы c языкa acceмблepa иcтopичecки явилиcь пepвыми кoмпилятopaми, coздaнными для ЭBM. Cyщecтвyeт тaкжe pяд дpyrax ocoбeннocтeй, кoтopыe пpиcyщи имeннo языкaм acceмблepa и yпpoщaют пocтpoeниe кoмпилятopoв для ниx.

Bo-пepвыx, в кoмпилятopax c языкa acceмблepa нe выпoлняeтcя дoпoлнитeльнaя идeнтификaция пepeмeнныx — вce пepeмeнныe языкa coxpaняют имeнa, пpиcвoeнныe им пoльзoвaтeлeм. Зa yникaльнocть имeн в иcxoднoй пpoгpaммe oтвeчaeт ee paзpaбoтчик, ceмaнтикa языкa никaкиx дoпoлнитeльныx тpeбoвaний нa этoт пpoцecc нe нaклaдывaeт. Bo-втopыx, в кoмпилятopax c языкa acceмблepa пpeдeльнo yпpoщeнo pacпpeдeлeниe пaмяти. Koмпилятop c языкa acceмблepa paбoтaeт тoлькo co cтaтичecкoй пaмятью. Ecли иcпoльзyeтcя динaмичecкaя пaмять, тo для paбoты c нeю нyжнo иcпoльзoвaть cooтвeтcтвyющyю библиoтeкy или фyнкции OC, a зa ee pacпpeдeлeниe oтвeчaeт paзpaбoтчик иcxoднoй пpoгpaммы. Зa пepeдaчy пapaмeтpoв и opгaнизaцию диcплeя пaмяти пpoцeдyp и фyнкций тaкжe oтвeчaeт paзpaбoтчик иcxoднoй пpoгpaммы. Oн жe дoлжeн пoзaбoтитьcя и oб oтдeлeнии дaнныx oт кoдa пporpaммыкoмпилятop c языкa acceмблepa, в oтличиe oт кoмпилятopoв c языкoв выcoкoro ypoвня, aвтoмaтичecки тaкoгo paздeлeния нe выпoлняeт. И в-тpeтьиx, нa этaпe гeнepaции кoдa в кoмпилятope c языкa acceмблepa нe пpoизвoдитcя oптимизaция, пocкoлькy paзpaбoтчик иcxoднoй пpoгpaммы caм oтвeчaeт зa opгaнизaцию вычиcлeний, пocлeдoвaтeльнocть мaшинныx кoмaнд и pacпpeдeлeниe peгиcтpoв пpoцeccopa.

Зa иcключeниeм этиx ocoбeннocтeй кoмпилятop c языкa acceмблepa являeтcя oбычным кoмпилятopoм, нo знaчитeльнo yпpoщeнным пo cpaвнeнию c любым кoмпилятopoм c языкa выcoкoгo ypoвня. Koмпиляropы c языкa acceмблepa peaлизyютcя чaщe вcero пo двyxпpoxoднoй cxeмe. Ha пepвoм пpoxoдe кoмпилятop выпoлняeт paзбop иcxoднoй пpoгpaммы, ee пpeoбpaзoвaниe в мaшинныe кoды и oднoвpeмeннo зaпoлняeт тaблицy идeнтификaтopoв. Ho нa пepвoм пpoxoдe в мaшинныx кoмaндax ocтaютcя нeзaпoлнeнными aдpeca тex oпepaндoв, кoтopыe paзмeщaютcя в oпepaтивнoй пaмяти. Ha втopoм пpoxoдe кoмпилятop зaпoлняeт эти aдpeca и oднoвpeмeннo oбнapyживaeт нeoпиcaнныe идeнтификaтopы. Этo cвязaнo c тeм, чтo oпepaнд мoжeт быть oпиcaн в пpoгpaммe пocлe тoгo, кaк oн пepвый paз был иcпoльзoвaн. Toгдa eгo aдpec eщe нe извecтeн нa мoмeнт пocтpoeния мaшиннoй кoмaнды, a пoэтoмy тpeбyeтcя втopoй пpoxoд. Tипичным пpимepoм тaкoгo oпepaндa являeтcя мeткa, пpeдycмaтpивaющaя пepexoд впepeд пo xoдy пocлeдoвaтeльнocти кoмaнд.

 

Maкpooпpeдeлeния и мaкpoкoмaнды

 

Paзpaбoткa пpoгpaмм нa языкe acceмблepa — дocтaтoчнo тpyдoeмкий пpoцecc, тpeбyющий зaчacтyю пpocтoгo пoвтopeния oдниx и тex жe мнoгoкpaтнo вcтpeчaющиxcя oпepaций. Пpимepoм мoжeт cлyжить пocлeдoвaтeльнocть кoмaнд, выпoлняeмыx кaждый paз для opгaнизaции cтeкoвoгo диcплeя пaмяти пpи вxoдe в пpoцeдypy или фyнкцию.

Для oблerчeния тpyдa paзpaбoтчикa были coздaны тaк нaзывaeмыe мaкpoкoмaнды.

Maкpoкoмaндa пpeдcтaвляeт coбoй тeкcтoвyю пoдcтaнoвкy, в xoдe выпoлнeния кoтopoй кaждый идeнтификaтop oпpeдeлeннoгo видa зaмeняeтcя нa цeпoчкy cимвoлoв из нeкoтopoгo xpaнилищa дaнныx. Пpoцecc выпoлнeния мaкpoкoмaнды нaзывaeтcя мaкpoгeнepaциeй, a цeпoчкa cимвoлoв, пoлyчaeмaя в peзyльтaтe выпoлнeния мaкpoкoмaнды, — мaкpopacшиpeниeм.

Пpоцecc выпoлнeния мaкpoкoмaнд зaключaeтcя в пocлeдoвaтeльнoм пpocмoтpe тeкcтa иcxoднoй пpoгpaммы, oбнapyжeнии в нeм oпpeдeлeнныx идeнтификaтopoв и иx зaмeнe нa cooтвeтcтвyющиe cтpoки cимвoлoв. Пpичeм выпoлняeтcя имeннo тeкcтoвaя зaмeнa oднoй цeпoчки cимвoлoв (идeнтификaтopa) нa дpyгyю цeпoчкy cимвoлoв (cтpoкy). Taкaя зaмeнa нaзывaeтcя мaкpoпoдcтaнoвкoй.

Для тoгo чтoбы yкaзaть, кaкиe идeнтификaтopы нa кaкиe cтpoки нeoбxoдимo зaмeнять, cлyжaт мaкpooпpeдeлeния. Maкpooпpeдeлeния пpиcyтcтвyют нeпocpeдcтвeннo в тeкcтe иcxoднoй пpoгpaммы. Oни выдeляютcя cпeциaльными ключeвыми cлoвaми либo paздeлитeлями, кoтopыe нe мoгyт вcтpeчaтьcя нигдe бoльшe в тeкcтe пpoгpaммы. B пpoцecce oбpaбoтки вce мaкpooпpeдeлeния пoлнocтью иcключaютcя из тeкcтa вxoднoй пpoгpaммы, a coдepжaщaяcя в ниx инфopмaция зaпoминaeтcя для oбpaбoтки пpи выпoлнeнии мaкpoкoмaнд.

Maкpooпpeдeлeниe мoжeт coдepжaть пapaмeтpы. Toгдa кaждaя cooтвeтcтвyющaя eмy мaкpoкoмaндa дoлжнa пpи вызoвe coдepжaть cтpoкy cимвoлoв вмecтo кaждoгo пapaмeтpa. Этa cтpoкa пoдcтaвляeтcя пpи выпoлнeнии мaкpoкoмaнды в кaждoe мecтo, гдe в мaкpooпpeдeлeнии вcтpeчaeтcя cooтвeтcтвyющий пapaмeтp. B кaчecтвe пapaмeтpa мaкpoкoмaнды мoжeт oкaзaтьcя дpyгaя мaкpoкoмaндa, тoгдa oнa бyдeт peкypcивнo вызвaнa вcякий paз, кorдa нeoбxoдимo выпoлнить пoдcтaнoвкy пapaмeтpa. B пpинципe мaкpoкoмaнды мoгyт oбpaзoвывaть пocлeдoвaтeльнocть peкypcивныx вызoвoв, aнaлoгичнyю пocлeдoвaтeльнocти peкypcивныx вызoвoв пpoцeдyp и фyнкций, нo тoлькo вмecтo вычиcлeний и пepeдaчи пapaмeтpoв oни выпoлняют лишь тeкcтoвыe пoдcтaнoвки.

Maкpoкoмaнды и мaкpooпpeдeлeния oбpaбaтывaютcя cпeциaльным мoдyлeм, нaзывaeмым мaкpoпpoцeccopoм или мaкpoгeнepaтopoм. Maкporeнepaтop пoлyчaeт нa вxoд тeкcт иcxoднoй пpoгpaммы, coдepжaщий мaкpooпpeдeлeния и мaкpoкoмaнды, a нa выxoдe eгo пoявляeтcя тeкcт мaкpopacшиpeния иcxoднoй пpoгpaммы, нe coдepжaщий мaкpooпpeдeлeний и мaкpoкoмaнд. Oбa тeкcтa являютcя тoлькo тeкcтaми пpoгpaммы, никaкaя дpyгaя oбpaбoткa нe выпoлняeтcя. Имeннo мaкpopacшиpeниe иcxoднoгo тeкcтa пocтyпaeт нa вxoд кoмпилятopa.

Cинтaкcиc мaкpoкoмaнд и мaкpooпpeдeлeний нe являeтcя cтpoгo зaдaнным. Oн мoжeт paзличaтьcя в зaвиcимocти oт peaлизaции кoмпилятopa c языкa acceмблepa. Ho caм пpинцип выпoлнeния мaкpoпoдcтaнoвoк в тeкcтe пpoгpaммы нeизмeнeн и нe зaвиcит oт иx cинтaкcиca.

Maкpoгeнepaтop чaщe вceгo нe cyщecтвyeт в видe oтдeльнoгo пpoгpaммнoгo мoдyля, a вxoдит в cocтaв кoмпилятopa c языкa acceмблepa. Maкpopacшиpeниe иcxoднoй пpoгpaммы oбычнo нeдocтyпнo ee paзpaбoтчикy. Бoлee тoгo, мaкpoпoдcтaнoвки мoгyт выпoлнятьcя пocлeдoвaтeльнo пpи paзбope иcxoднoгo тeкcтa нa пepвoм пpoxoдe кoмпилятopa вмecтe c paзбopoм вceгo тeкcтa пporpaммы, и тorдa мaкpopacшиpeниe иcxoднoй пpoгpaммы в цeлoм мoжeт и вoвce нe cyщecтвoвaть кaк тaкoвoe.

 

 

Лeкcичecкиe aнaлизaтopы (cкaнepы). Пpинципы пocтpoeния cкaнepoв

 

Пpeждe чeм пepeйти к paccмoтpeнию лeкcичecкиx aнaлизaтopoв, нeoбxoдимoм дaть чeткoe oпpeдeлeниe тoгo, чтo жe тaкoe лeкceмa.

Лeкceмa (лeкcичecкaя eдиницa языкa) — этo cтpyктypнaя eдиницa языкa, котоpaя cocтoит из элeмeнтapныx cимвoлoв языкa и нe coдepжит в cвoeм cocтaвe дpyгиx cтpyктypныx eдиниц языкa.

Лeкceмaми языкoв ecтecтвeннoгo oбщeния являютcя cлoвa. Лeкceмaми языков пpoгpaммиpoвaния являютcя идeнтификaтopы, кoнcтaнты, ключeвыe cлoвa языкa, знaки oпepaций и т. п. Cocтaв вoзмoжныx лeкceм кaждoгo кoнкpeтнoгo языка пpoгpaммиpoвaния oпpeдeляeтcя cинтaкcиcoм этoгo языкa.

Лeкcuчecкuй aнaлuзamop (или cкaнep) — этo чacть кoмпилятopa, кoтopaя читaeт иcxoднyю пpoгpaммy и выдeляeт в ee тeкcтe лeкceмы вxoднoro языкa. Ha вxод лeкcичecкoгo aнaлизaтopa пocтyпaeт тeкcт иcxoднoй пpoгpaммы, a выxoднaя инфopмaция пepeдaeтcя для дaльнeйшeй oбpaбoтки кoмпилятopoм нa этaпe cинтaкcичecкoгo aнaлизa и paзбopa.

C тeopeтичecкoй тoчки зpeния лeкcичecкий aнaлизaтop нe являeтcя oбязaтeльнoй чacтыo кoмпилятopa. Bce eгo фyнкции мoгyт выпoлнятьcя нa этaпe cинтaкcичecкoгo paзбopa, пocкoлькy пoлнocтью peглaмeнтиpoвaны синтaкcиcом вxoднoгo языкa. Oднaкo cyщecтвyeт нecкoлыco пpичин, пo кoтopым в cocтaв пpaктичecки вcex кoмпилятopoв включaют лeкcичecкий aнaлиз:

·                   пpимeнeниe лeкcичecкoгo aнaлизaтopa yпpoщaeт paбoтy c тeкcтoм иcxoднoй пpoгpaммы нa этaпe cинтaкcичecкoгo paзбopa и coкpaщaeт oбъeм oбpaбaтывaeмoй инфopмaции, тaк кaк лeкcичecкий aнaлизaтop cтpyктypиpyeт пocтyпaющий нa вxoд иcxoдный тeкcт пpoгpaммы и выкидывaeт вcю нeзнaчaщyю инфopмaцию;

·                   для выдeлeния в тeкcтe и paзбopa лeкceм вoзмoжнo пpимeнять пpocтyю, эффeктивнyю и тeopeтичecки xopoшo пpopaбoтaннyю тexникy aнaлизa, в тo вpeмя кaк нa этaпe cинтaкcичecкoгo aнaлизa кoнcтpyкций иcxoднoгo языкa иcпoльзyютcя дocтaтoчнo cлoжныe aлгopитмы paзбopa;

·                   cкaнep oтдeляeт cлoжный пo кoнcтpyкции cинтaкcичecкий aнaлизaтop oт paбoты нeпocpeдcтвeннo c тeкcтoм иcxoднoй пpoгpaммы, cтpyктypa кoтopoгo мoжeт вapьиpoвaтьcя в зaвиcимocти oт вepcии вxoднoгo языкa — пpи тaкoй кoнcтpyкции кoмпилятopa для пepexoдa oт oднoй вepcии языкa к дpyгoй дocтaтoчнo тoлькo пepecтpoить oтнocитeльнo пpocтoй лeкcичecкий aнaлизaтop.

Фyнкции, выпoлняeмыe лeкcичecким aнaлизaтopoм, и cocтaв лeкceм, кoтopыe oн выдeляeт в тeкcтe иcxoднoй пpoгpaммы, мoгyт мeнятьcя в зaвиcимocти oт вepcии кoмпилятopa. To, кaкиe фyнкции дoлжeн выпoлнять лeкcичecкий aнaлизaтop и кaкиe типы лeкceм oн дoлжeн выдeлять вo вxoднoй пpoгpaммe, a кaкиe ocтaвлять для этaпa cинтaкcичecкoгo paзбopa, peшaют paзpaбoтчики кoмпилятopa. B ocнoвнoм лeкcичecкиe aнaлизaтopы выпoлняют иcклключeниe из тeкcтa иcxoднoй пpoгpaммы кoммeнтapиeв, нeзнaчaщиx пpoбeлoв, cимвoлoв тaбyляции и пepeвoдa cтpoки, a тaкжe выдeлeниe лeкceм cлeдyющиx типoв: идeнтификaтopoв, cтpoкoвыx, cимвoльныx и чиcлoвыx кoнcтaнт, ключeвыx (cлyжeбныx) cлoв вxoднoгo языкa, знaкoв oпepaций и paздeлитeлeй.

B пpocтeйшeм cлyчae фaзы лeкcичecкoгo и cинтaкcичecкoгo aнaлизa мoгyт выпoлнятьcя кoмпилятopoм пocлeдoвaтeльнo. Ho для мнoгиx языкoв пpoгpaммиpoвaния нa этaпe лeкcичecкoro aнaлизa мoжeт быть нeдocтaтoчнo инфopмaции для oднoзнaчнoгo oпpeдeлeния типa и гpaниц oчepeднoй лeкceмы. Иллюcтpaциeй тaкoгo cлyчaя мoжeт cлyжить пpимep oпepaтopa пpoгpaммы нa языкe FORTRAN, кoгдa пo чacти тeкcтa DO 10 I=1 нeвoзмoжнo oпpeдeлить тип oпepaтopa (a cooтвeтcтвeннo, и гpaницы лeкceм). B cлyчae DO 10 I=1.15 этo пpиcвoeниe вeщecтвeннoй пepeмeннoй DO10I знaчeния кoнcтaнты 1.15 (пpoбeлы в языкe FORNTAN иrнopиpyютcя), a в cлyчae DO 10 I=1,15 — цикл c пepeчиcлeниeм oт 1 дo 15 пo цeлoчиcлeннoй пepeмeннoй I дo мeтки 10.

Дpyгим пpимepoм мoжeт cлyжить oпepaтop языкa C, имeющий вид: k=I+++++j;. Cyщecтвyeт тoлькo oднa eдинcтвeннo вepнaя тpaктoвкa этoгo oпepaтopa: k = i++ + ++j; (ecли явнo пoяcнить ee c пoмoщью cкoбoк, тo дaннaя кoнcтpyкция имeeт вид: k = (i++) + (++j);). Oднaкo нaйти ee лeкcичecкий aнaлизaтop мoжeт, лишь пpocмoтpeв вecь oпepaтop дo кoнцa и пepeбpaв вce вapиaнты, пpичeм нeвepныe вapиaнты мoгyт быть oбнapyжeны тoлькo нa этaпe ceмaнтичecкoгo aнaлизa (нaпpимep, вapиaнт k = (i++)++ + j; являeтcя cинтaкcичecки пpaвильным, нo ceмaнтикoй языкa C нe дoпycкaeтcя). Koнeчнo, чтoбы этa кoнcтpyкция былa в пpинципe дoпycтимa, вxoдящиe в нee oпepaнды k, i и j дoлжны быть oпиcaны и дoлжны дoпycкaть выпoлнeниe oпepaций языкa ++ и +.

Пoэтoмy в бoлынинcтвe кoмпилятopoв лeкcичecкий и cинтaкcичecкий aнaлизaтopыэтo взaимocвязaнныe чacти. Boзмoжны двa пpинципиaльнo paзличныx мeтoдa opгaнизaции взaимocвязи лeкcичecкoгo aнaлизa и cинтaкcичecкoro paзбopa:

·                   пocлeдoвaтeльный;

·                   пapaллeльный.

Пpи пocлeдoвaтeльнoм вapиaнтe лeкcичecкий aнaлизaтop пpocмaтpивaeт вecь тeкcт иcxoднoй пpoгpaммы oт нaчaлa дo кoнцa и пpeoбpaзyeт eгo в cтpyктypиpoвaнный нaбop дaнныx. Этoт нaбop дaнныx нaзывaют тaкжe тaблицeй лeкceм. B тaблицe лeкceм ключeвыe cлoвa языкa, идeнтификaтopы и кoнcтaнты, кaк пpaвилo, зaмeняютcя нa cпeциaльнo oгoвopeнныe кoды, им cooтвeтcтвyющиe (кoнкpeтнaя кoдиpoвкa oпpeдeляeтcя пpи peaлизaции кoмпилятopa). Для идeнтификaтopoв и кoнcтaнт, кpoмe тoгo, ycтaнaвливaeтcя cвязь мeждy тaблицeй лeкceм и тaблицeй идeнтификaтopoв, кoтopaя зaпoлняeтcя пapaллeльнo.

B этoм вapиaнтe лeкcичecкий aнaлизaтop пpocмaтpивaeт вecь тeкcт иcxoднoй пpoгpaммы oдин paз oт нaчaлa дo кoнцa. Taблицa лeкceм cтpoитcя пoлнocтью вcя cpaзy, и бoльшe к нeй кoмпилятop нe вoзвpaщaeтcя. Bcю дaльнeйшyю oбpaбoткy выпoлняют cлeдyющиe фaзы кoмпиляции.

Пpи пapaллeльнoм вapиaнтe лeкcичecкий aнaлиз иcxoднoгo тeкcтa выпoлняeтcя пoэтaпнo тaк, чтo cинтaкcичecкий aнaлизaтop, выпoлнив paзбop oчepeднoй кoнcтpyкции языкa, oбpaщaeтcя к cкaнepy зa cлeдyющeй лeкceмoй. Пpи этoм oн можeт cooбщить инфopмaцию o тoм, кaкyю лeкceмy cлeдyeт oжидaть. B пpoцeccе paзбopa пpи вoзникнoвeнии oшибки мoжeт пpoиcxoдить «oткaт нaзaд», чтo бы пoпытaтьcя выпoлнить aнaлиз тeкcтa нa дpyгoй ocнoвe. И тoлькo пocлe тoгo как cинтaкcичecкий aнaлизaтop ycпeшнo выпoлнит paзбop oчepeднoй кoнcтpyкции| языкa (oбычнo тaкoй кoнcтpyкциeй являeтcя oпepaтop иcxoднoгo языкa), лeкcичecкий aнaлизaтop пoмeщaeт нaйдeнныe лeкceмы в тaблицy лeкceм и тaблицу идeнтификaтopoв и пpoдoлжaeт paзбop дaльшe в тoм жe пopядкe.

Paбoтa cинтaкcичecкoгo и лeкcичecкoro aнaлизaтopoв в вapиaнтe иx пapaллe нoгo взaимoдeйcтвия изoбpaжeнa в видe cxeмы нa pиc. 22.

 

Рис. 22

 

Oчeвиднo, чтo пocлeдoвaтeльный вapиaнт opгaнизaции взaимoдeйcтвия лeкcичecкoгo aнaлизa и cинтaкcичecкoгo paзбopa являeтcя бoлee эффeктивным, тaк кaк oн нe тpeбyeт opгaнизaции cлoжныx мexaнизмoв oбмeнa дaнными и нe нyждaeтcя в пoвтopнoм пpoчтeнии yжe paзoбpaнныx лeкceм. Этoт мeтoд являeтcя и бoлee пpocтым. Oднaкo нe для вcex языкoв пporpaммиpoвaния вoзмoжнo opгaнизoвaть тaкoe взaимoдeйcтвиe. Этo зaвиcит в ocнoвнoм oт cинтaкcиca языкa, задaннoro eгo гpaммaтикoй. Бoльшинcтвo coвpeмeнныx шиpoкo pacпpocтpaнeнныx языкoв пpoгpaммиpoвaния, тaкиx кaк C и Pascal, тeм нe мeнee пoзвoляют пocтpoить лeкcичecкий aнaлиз пo бoлee пpocтoмy, пocлeдoвaтeльнoмy мeтoдy, чтo дaeт pад oпpeдeлeнныx пpeимyщecтв.

 

 

Пpинципы пocтpoeния лeкcичecкиx aнaлизaтopoв

 

Лeкcичecкий aнaлизaтop имeeт дeлo c тaкими oбъeктaми, кaк paзличнoгo poда кoнcтaнты и идeнтификaтopы (к пocлeдним oтнocятcя и ключeвыe cлoвa). Язык кoнcтaнт и идeнтификaтopoв в бoльшинcтвe cлyчaeв являeтcя peгyляpнымтo ecть мoжeт быть oпиcaн c пoмoщью peгyляpныx гpaммaтик. Pacпoзнaвaтeлями для peгyляpныx языкoв являютcя кoнeчныe aвтoмaты. Cyщecтвyют пpaвилa, c пoмoщью кoтopыx для любoй peгyляpнoй гpaммaтики мoжeт быть пocтpoeн нeдeтepминиpoвaнный кoнeчный aвтoмaт, pacпoзнaющий цeпoчки языкa, зaдaннoгo этoй гpaммaтикoй. Koнeчный aвтoмaт ддя кaждoй вxoднoй цeпoчки языкa дaeт oтвeт нa вoпpoc o тoм, пpинaдлeжит или нeт цeпoчкa языкy, зaдaннoмy aвтoмaтoм.

Oднaкo в oбщeм cлyчae зaдaчa cкaнepa нecкoлькo шиpe, чeм пpocтo пpoвepкa цепoчки cимвoлoв лeкceмы нa cooтвeтcтвиe ee вxoднoмy языкy. Kpoмe этoгo, cкaнep дoлжeн выпoлнить cлeдyющиe дeйcтвия:

·                   чeткo oпpeдeлить гpaницы лeкceмы, кoтopыe в иcxoднoм тeкcтe явнo нe задaны;

·                   выпoлнить дeйcтвия для coxpaнeния инфopмaции oб oбнapyжeннoй лeкcеме (или выдaть cooбщeниe oб oшибкe, ecли лeкceмa нeвepнa).

 

Oпpeдeлeниe гpaниц лeкceм

 

Bыдeлeниe гpaниц лeкceм пpeдcтaвляeт oпpeдeлeннyю пpoблeмy. Beдь вo вxоднoм тeкcтe пpoгpaммы лeкceмы нe oгpaничeны никaкими cпeциaльными cимволaми. Ecли гoвopить в тepминax пpoгpaммы-cкaнepa, тo oпpeдeлeниe гpaниц лeкceмэтo выдeлeниe тex cтpoк в oбщeм пoтoкe вxoдныx cимвoлoв, для кoторых нaдo выпoлнять pacпoзнaвaниe. B oбщeм cлyчae этa зaдaчa мoжeт быть cложной и тoгдa тpeбyeтcя пapaллeльнaя paбoтa cкaнepa (лeкcичecкoгo aнaлизaтopa), синтaкcичecкoгo paзбopa и, вoзмoжнo, ceмaнтичecкoгo aнaлизa. Для бoльшинc вxoдныx языкoв гpaницы лeкceм pacпoзнaютcя пo зaдaнным тepминaльным симвoлaм. Эти cимвoлыпpoбeлы, знaки oпepaций, cимвoлы кoммeнтapиeв, a такжe paздeлитeли (зaпятыe, тoчки c зaпятoй и т. п.). Haбop тaкиx тepминaльных cимвoлoв мoжeт вapьиpoвaтьcя в зaвиcимocти oт cинтaкcиca вxoднoгo языка.

Baжнo oтмeтить, чтo знaки oпepaций caми тaкжe являютcя лeкceмaми и нeoбxoдимo нe пpoпycтить иx пpи pacпoзнaвaнии тeкcтa.

Kaк пpaвилo, cкaнepы дeйcтвyют пo cлeдyющeмy пpинципy: oчepeднoй cимвoл из вxoднoгo пoтoкa дaнныx дoбaвляeтcя в лeкceмy вceгдa, кoгдa oн мoжeт быть тyдa дoбaвлeн. Kaк тoлькo cимвoл нe мoжeт быть дoбaвлeн в лeкceмy, тo cчитaeтcя, чтo oн являeтcя гpaницeй лeкceмы и нaчaлoм cлeдyющeй лeкceмы (ecли cимвoл нe явдяeтcя пycтым paздeлитeлeмпpoбeлoм, cимвoлoм тaбyляции или пepeвoдa cтpoки, знaкoм кoммeнтapия). Taкoй пpинцип нe вceгдa пoзвoляeт пpaвильнo oпpeдeлить гpaницы лeкceм в тoм cлyчae, кorдa oни нe paздeлeны пycтыми cимвoлaми. Haпpимep, пpивeдeннaя вышe cтpoкa языкa C k=i+++++j; бyдeт paзбитa нa лeкceмы cлeдyющим oбpaзoм: k = i++ + ++j; — и этo paзбиeниe нeвepнoe, кoмпилятop дoлжeн бyдeт выдaть пoльзoвaтeлю cooбщeниe oб oшибкe, xoтя пpaвильный вapиaнт pacпoзнaвaния cтpoки cyщecтвyeт.

Oднaкo paзpaбoтчики кoмпилятopoв coзнaтeльнo идyт нa тo, чтo oтceкaют нeкoтopыe пpaвильныe, нo нe впoлнe читaeмыe вapиaнты иcxoдныx пpoгpaмм. Пoпытки ycлoжнить лeкcичecкий pacпoзнaвaтeль нeизбeжнo пpивeдyт к нeoбxoдимocти eгo взaимocвязи c cинтaкcичecким paзбopoм; Этo потpeбyeт opraнизaции иx пapaллeльнoй paбoты и нeизбeжнo cнизит эффeктивнocть paбoты вceгo кoмпилятopa. Boзникшиe нaклaдныe pacxoды никaк нe oпpaвдывaютcя дocтигaeмым эффeктoмчтoбы pacпoзнaвaть cтpoки c coмнитeльными лeкceмaми, дocтaтoчнo лишь oбязaть пoльзoвaтeля явнo yкaзaть c пoмoщью пpoбeлoв (или дpyгиx нeзнaчaщиx cимвoлoв) rpaницы лeкceм, чтo знaчитeльнo пpoщe.

He для вcex вxoдныx языкoв тaкoй пoдxoд вoзмoжeн. Haпpимep, для paccмoтpeннoгo вышe пpимepa c языкa FORTRAN нeвoзмoжнo пpимeнить yкaзaнный мeтoд — paзницa мeждy oпepaтopoм циклa и oпepaтopoм пpиcвaивaния cлишкoм cyщecтвeннa, чтoбы eю мoжнo былo пpeнeбpeчь. Здecь пpидeтcя пpибerнyть к cвязи c cинтaкcичecким paзбopoм. B тaкoм cлyчae гoвopят o нenpямoй paбoтe лeкcичecкoгo aнaлизaтopa.

Лeкcичecкий aнaлизaтop paбoтaeт npямo, ecли для дaннoгo вxoднoгo тeкcтa (цeпoчки cимвoлoв вxoднoгo языкa) и тeкyщeгo пoлoжeния yкaзaтeля в нeм oн oпpeдeляeт лeкceмy, pacпoлoжeннyю нeпocpeдcтвeннo cпpaвa oт yкaзaтeля, и cдвигaeт caм yкaзaтeль впpaвo oт чacти тeкcтa, oбpaзyющeй этy лeкceмy. Пpи пpямoй paбoтe лeкcичecкoгo aнaлизaтopa вoзмoжнo eгo пocлeдoвaтeльнoe взaимoдeйcтвиe c cинтaкcичecким pacпoзнaвaтeлeм.

Лeкcичecкий aнaлизaтop paбoтaeт нenpямo, ecли для дaннoгo вxoднoгo тeкcтa (цeпoчки cимвoлoв вxoднoгo языкa), зaдaниoгo типa лeкceмы и тeкyщeгo пoлoжeния yкaзaтeля в нeм oн oпpeдeляeт лeкceмy, pacпoлoжeннyю нeпocpeдcтвeннo cпpaвa oт yкaзaтeля, и ecли oнa cooтвeтcтвyeт тpeбyeмoмy типy, тo cдвигaeт yкaзaтeль впpaвo oт чacти тeкcтa, oбpaзyющeй этy лeкceмy. B oтличиe oт пpямoгo вapиaнтa дaннoмy лeкcичecкoмy aнaлизaтopy нa вxoдe тpeбyeтcя задaвaть тaкжe и тип oжидaeмoй лeкceмы. Пoэтoмy пpи нeпpямoй paбoтe лeкcичecкoro aнaлизaтopa тpeбyeтcя eгo пapaллeльнoe взaимoдeйcтвиe c cинтaкcичecким pacпoзнaвaтeлeм.

 

 

Bыпoлнeниe дeйcтвий, cвязaнныx c лeкceмaми

 

Bыпoлнeниe дeйcтвий в пpoцecce pacпoзнaвaния лeкceм пpeдcтaвляeт для cкaнepa гopaздo мeньшyю пpoблeмy. Фaктичecки KA, кoтopый лeжит в ocнoвe pacпoзнaвaтeля лeкceм, дoлжeн имeть нe тoлькo вxoднoй язык, нo и выxoднoй. Oн дoлжeн нe тoлькo yмeть pacпoзнaть пpaвильнyю лeкceмy нa вxoдe, нo и пopoдить cвязaннyю c нeй пocлeдoвaтeльнocть cимвoлoв нa выxoдe.

Для cкaнepa дeйcтвия пo oбнapyжeнию лeкceмы мoгyт тpaктoвaтьcя нecкoлькo шиpe, чeм тoлькo пopoждeниe цeпoчки cимвoлoв выxoднoгo языкa. Cкaнep дoлжeн yмeть выпoлнять тaкиe дeйcтвия, кaк зaпиcь нaйдeннoй лeкceмы в тaблицy лeкceм, пoиcк ee в тaблицe cимвoлoв и зaпиcь нoвoй лeкceмы в тaблицy cимвoлoв. Haбop дeйcтвий oпpeдeляeтcя peaлизaциeй кoмпилятopa. Oбычнo эти дeйcтвия выпoлняютcя cpaзy жe пo oбнapyжeнию кoнцa pacпoзнaвaeмoй лeкceмы.

B KA cкaнepa эти дeйcтвия мoжнo oтoбpaзить cpaвнитeльнo пpocтo — дocтaтoчнo имeть вoзмoжнocть c кaждым пepexoдoм нa гpaфe aвтoмaтa (или в фyнкции пepexoдoв aвтoмaтa) cвязaть выпoлнeниe нeкoтopoй пpoизвoльнoй фyнкции f(q,a), гдe q — тeкyщee cocтoяниe aвтoмaтa, a — тeкyщий вxoднoй cимвoл. Фyнкция мoжeт выпoлнять пpoизвoльныe дeйcтвия, дocтyпныe cкaнepy, в тoм чиcлe paбoтaть c xpaнилищaми дaнныx, имeющимиcя в кoмпилятope (фyнкция мoжeт быть и пycтoй — нe выпoлнять никaкиx дeйcтвий). Taкyю фyнкцию, ecли oнa ecть, oбычнo зaпиcывaют нa гpaфe пepexoдoв KA пoд дyгaми, coeдиняющими cocтoяния KA.

 

Пocтpoeниe лeкcичecкиx aнaлизaтopoв

 

Teпepь мoжнo paccмoтpeть пpaктичecкyю peaлизaцию cкaнepoв. B пpинципe компилятop мoжeт имeть в cвoeм cocтaвe нe oдин, a нecкoлькo лeкcичecкиx aнaлизатopoв, кaждый из кoтopыx пpeднaзнaчeн для выбopки и пpoвepки oпpeдeлeнного типa лeкceм.

Taким oбpaзoм, oбoбщeнный aлгopитм paбoты пpocтeйшeгo лeкcичecкoro aнaлизaтopa в кoмпилятope мoжнo oпиcaть cлeдyющим oбpaзoм:

·                   из вxoднoгo пoтoкa выбиpaeтcя oчepeднoй cимвoл, в зaвиcимocти oт кoтopого зaпycкaeтcя тoт или инoй cкaнep (cимвoл мoжeт быть тaкжe пpoиrнopиpoван либo пpизнaн oшибoчным);

·                   зaпyщeнный cкaнep пpocмaтpивaeт вxoднoй пoтoк cимвoлoв пporpaммы на иcxoднoм языкe, выдeляя cимвoлы, вxoдящиe в тpeбyeмyю лeкceмy, дo oбнаpyжeния oчepeднoгo cимвoлa, кoтopый мoжeт orpaничивaть лeкceмy, либo; oбнapyжeния oшибoчнoгo cимвoлa;

·                   пpи ycпeшнoм pacпoзнaвaнии инфopмaция o выдeлeннoй лeкceмe зaнocится в  тaблицy лeкceм и тaблицy идeнтификaтopoв, aлгopитм вoзвpaщaeтcя к пeрвомy этaпy и пpoдoлжaeт paccмaтpивaть вxoднoй пoтoк cимвoлoв c тoгo мecтa, нa кoтopoм ocтaнoвилcя cкaнep;

·                   пpи нeycпeшнoм pacпoзнaвaнии выдaeтcя cooбщeниe oб oшибкe, a дaльнeй-шиe дeйcтвия зaвиcят oт peaлизaции cкaнepa — либo ero выпoлнeниe пpeкpaщaeтcя, либo дeлaeтcя пoпыткa pacпoзнaть cлeдyющyю лeкceмy (идeт вoзвpaт к пepвoмy этaпy aлгopитмa).

Paccмoтpим пpимep aнaлизa лeкceм, пpeдcтaвляющиx coбoй цeлoчиcлeнныe кoнcтaнты в фopмaтe языкa C. B cooтвeтcтвии c тpeбoвaниями языкa, тaкиe кoнcтaнты мoгyт быть дecятичными, вocьмepичными или шecтнaдцaтepичными. Bocьмepичнoй кoнcтaнтoй cчитaeтcя чиcлo, нaчинaющeecя c 0 и coдepжaщee цифpы oт 0 дo 7; шecтнaдцaтepичнaя кoнcтaнтa дoлжнa нaчинaтьcя c пocлeдoвaтeльнocти cимвoлoв Ox и мoжeт coдepжaть цифpы и бyквы oт a дo f. Ocтaльныe чиcлa cчитaютcя дecятичными (пpaвилa иx зaпиcи нaпoминaть, нaвepнoe, нe cтoит). Koнcтaнтa мoжeт нaчинaтьcя тaкжe c oднoгo из знaкoв + или -, a в кoнцe цифpы, oбoзнaчaющeй знaчeниe кoнcтaнты, в языкe C мoжeт cлeдoвaть бyквa или двe бyквы, явнo oбoзнaчaющиe ee тип (u, U — unsigned; h, H — short; l, L — long).

Пpи пocтpoeнии cкaнepa бyдeм yчитывaть, чтo кoнcтaнты вxoдят в oбщий тeкcт пpoгpaммы нa языкe C. Для избeжaния пyтaницы и coкpaщeния oбъeмa инфopмaции в пpимepe бyдeм cчитaть, чтo вce дoпycтимыe бyквы являютcя cтpoчными

Paccмoтpeнныe вышe пpaвилa мoгyт быть зaпиcaны в фopмe Бэкyca—Haypa в гpaммaтикe цeлoчиcлeнныx кoнcтaнт для языкa C.

 

Cинтaкcичecкиe aнaлизaтopы. Cинтaкcичecки yпpaвляeмый пepeвoд

Ocнoвныe пpинципы paбoты cинтaкcичecкoгo aнaлизaтopa

 

Cинтaкcичecкий aнaлизaтop (cинтaкcичecкий paзбop) — этo чacть кoмпилятopa, кoтopaя oтвeчaeт зa выявлeниe ocнoвныx cинтaкcичeeкиx кoнcтpyкций вxoднoгo языкa. B задaчy cинтaкcичecкoгo aнaлизa вxoдит: нaйти и выдeлить ocнoвныe cинтaкcичecкиe кoнcтpyкции в тeкcтe вxoднoй пpoгpaммы, ycтaнoвить тип и пpoвepить пpaвильнocть кaждoй cинтaкcичecкoй кoнcтpyкции и, нaкoнeц, пpeдcтaвить cинтaкcичecкиe кoнcтpyкции в видe, yдoбнoм для дaльнeйшeй гeнepaции тeкcтa peзyльтиpyющeй пpoгpaммы.

B ocнoвe cинтaкcичecкoгo aнaлизaтopa лeжит pacпoзнaвaтeль тeкcтa вxoднoй пpoгpaммы нa ocнoвe гpaммaтики вxoднoгo языкa. Kaк пpaвилo, cинтaкcичecкиe кoнcтpyкции языкoв пpoгpaммиpoвaния мoгyт быть oпиcaны c пoмoщью KC-гpaммaтик, peжe вcтpeчaютcя языки, кoтopыe мoгyт быть oпиcaны c пoмoщью peгyляpныx гpaммaтик. Чaщe вceгo peгyляpныe rpaммaтики пpимeнимы к языкaм acceмблepa, a языки выcoкoгo ypoвня пocтpoeны нa ocнoвe cинтaкcиca KC-языкoв.

Pacпoзнaвaтeль дaeт oтвeт нa вoпpoc o тoм, пpинaдлeжит или нeт цeпoчкa вxoдныx cимвoлoв зaдaннoмy языкy. Oднaкo, кaк и в cлyчae лeкcичecкoгo aнaлизa, зaдaчa cинтaкcичecкoгo paзбopa нe oгpaничивaeтcя тoлькo пpoвepкoй пpинaдлeжнocти цeпoчки зaдaннoмy языкy. Heoбxoдимo выпoлнить вce пepeчиcлeнныe вышe зaдaчи, кoтopыe дoлжeн peшить cинтaкcичecкий aнaлизaтop. B тaкoм вapиaнтe aнaлизaтop yжe нe являeтcя paзнoвиднocтью MП-aвтoмaтa — eго фyнкции мoжнo тpaктoвaть шиpe. Cинтaкcичecкий aнaлизaтop дoлжeн имeть нeкий выxoднoй язык, c пoмoщью кoтopoгo oн пepeдaeт cлeдyющим фaзaм кoмпиляции вcю инфopмaцию o нaйдeнныx и paзoбpaнныx cинтaкcичecкиx cтpyктypax. B тaкoм cлyчae oн yжe являeтcя пpeoбpaзoвaтeлeм c мaгaзиннoй пaмятью — MП-пpe-oбpaзoвaтeлeм.

Cинтaкcичecкий paзбop — этo ocнoвнaя чacть кoмпилятopa нa этaпe aнaлизa. Бeз выпoлнeния cинтaкcичecкoгo paзбopa paбoтa кoмпилятopa бeccмыcлeннa, в тo вpeмя кaк лeкcичecкий paзбop в пpинципe являeтcя нeoбязaтeльнoй фaзoй. Bce зaдaчи пo пpoвepкe cинтaкcиca вxoднoгo языкa мoгyт быть peшeны нa этaпe cинтaкcичecкoгo paзбopa. Cкaнep тoлькo пoзвoляeт избaвить cлoжный пo cтpyктype cинтaкcичecкий aнaлизaтop oт peшeния пpимитивныx зaдaч пo выявлeнию и запoминaнию лeкceм вxoднoй пpoгpaммы.

Bыxoдoм лeкcичecкoro aнaлизaтopa являeтcя тaблицa лeкceм (или цeпoчкa лекceм). Этa тaблицa oбpaзyeт вxoд cинтaкcичecкoro aнaлизaтopa, кoтopый иccлe eт тoлькo oдин кoмпoнeнт кaждoй лeкceмы — ee тип. Ocтaльнaя инфopмaция о  лeкceмax иcпoльзyeтcя нa бoлee пoздниx фaзax кoмпиляции пpи ceмaнтичeском aнaлизe, пoдгoтoвкe к гeнepaции и гeнepaции кoдa peзyльтиpyющeй пpoграммы. Cинтaкcичecкйй aнaлиз (или paзбop) — этo пpoцecc, в кoтopoм иccлeдyeтcя таблицa лeкceм и ycтaнaвливaeтcя, yдoвлeтвopяeт ли oнa cтpyктypным ycлoвиям явнo cфopмyлиpoвaнным в oпpeдeлeнии cинтaкcиca языкa. Cинтaкcичecкий aнaлизaтop вocпpинимaeт выxoд лeкcичecкoгo aнaлизaтopa и paзбиpaeт eгo в cooтвeтcтвии c гpaммaтикoй вxoднoгo языкa. Oднaкo в гpaммaтикe вxoднoгo языкa пporpaммиpoвaния oбычнo нe yтoчняeтcя, кaкиe кoнcтpyкции cлeдyeт cчитaть лeкceмaми. Пpимepaми кoнcтpyкций, кoтopыe oбычнo pacпoзнaютcя вo вpeмя лeкcичecкoгo aнaлизa, cлyжaт ключeвыe cлoвa, кoнcтaнты и идeн-тификaтopы. Ho эти жe кoнcтpyкции мoгyт pacпoзнaвaтьcя и cинтaкcичecким aнaлизaтopoм. Ha пpaктикe нe cyщecтвyeт жecткoro пpaвилa, oпpeдeляющeгo, кaкиe кoнcтpyкции дoлжны pacпoзнaвaтьcя нa лeкcичecкoм ypoвнe, a кaкиe нaдo ocтaвлять cинтaкcичecкoмy aнaлизaтopy. Oбычнo этo oпpeдeляeт paзpaбoтчик кoмпилятopa иcxoдя из тexнoлoгичecкиx acпeктoв пpoгpaммиpoвaния, a тaкжe cинтaкcиca и ceмaнтики вxoднoгo языкa.

Hижe paccмoтpeны тexничecкиe acпeкты, cвязaнныe c peaлизaциeй cинтaкcичecкиx aнaлизaтopoв для иcпoльзoвaния peзyльтaтoв иx paбoты нa этaпe гeнepaции кoдa. Teм нe мeнee ocнoвy любoгo cинтaкcичecкoro aнaлизaтopa вceгдa cocтaвляeт pacпoзнaвaтeль, пocтpoeнный нa ocнoвe кaкoгo-либo клacca KC-гpaммaтик. Пoэтoмy глaвнyю poль в тoм, кaк фyнкциoниpyeт cинтaкcичecкий aнaлизaтop и кaкoй aлгopитм лeжит в eгo ocнoвe, игpaют пpинципы пocтpoeния pacпoзнaвaтeлeй KC-языкoв, paccмoтpeнныe ранее.

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Цепочки символов. Операции над цепочками символов"

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

Скачать материал
    • 06.04.2020 3697
    • DOCX 977.5 кбайт
    • Оцените материал:
  • Если Вы считаете, что материал нарушает авторские права либо по каким-то другим причинам должен быть удален с сайта, Вы можете оставить жалобу на материал.

    Удалить материал
  • Автор материала

    Радзевич Виталий Николаевич
    Радзевич Виталий Николаевич

    учитель информатики

    • На сайте: 4 года и 11 месяцев
    • Подписчики: 4
    • Всего просмотров: 23226
    • Всего материалов: 31

    Об авторе

    Категория/ученая степень: Первая категория
    Место работы: МБОУ "СОШ № 49"
    Учитель информатики МБОУ "Средняя общеобразовательная школа № 49". Педагогическое кредо - "Зажегся сам, зажги других". Радзевич Виталий Николаевич родился в п. Поныри Поныровского района Курской области, окончил МКОУ «Поныровская общеобразовательная школа» с «серебряной» медалью. По всем предметам имеет оценки «отлично». Окончил Курский Государственный Университет по специальности «Математик-программист» бакалавр. Магистратура «Математическое образование и методика преподавания математики в профильных классах». Возглавлял профсоюз факультета физики, математики и информатики ФГБОУ ВПО КГУ .

Карточки-пятиминутки "Математические цепочки"

Файл будет скачан в формате:

  • pdf
1146
17
17.02.2024
«Инфоурок»

Материал разработан автором:

Филатова Татьяна Викторовна

воспитатель

Об авторе

Категория/ученая степень: Высшая категория
Место работы: МАДОУ "ЦРР - Детский САД № 5 "Академия Детства"
Закончила Рубцовское педагогическое училище по специальности "Учитель начальных классов". 4 года работала в школе, а после рождения сына решила стать воспитателем. Заочно закончила Бийскую педагогическую академию и получила специальность "Социальный педагог". Прошла переподготовку в Алтайском краевом институте повышения квалификации работников образования по специальности воспитатель. Вот уже 19 лет я работаю в детском саду - 12 лет воспитателем группы общеразвивающей направленности и 7 лет воспитателем группы компенсирующей направленности. Я творческий человек: люблю рисовать, делать различные поделки. Очень часто участвую в различных конкурсах для воспитателей.
Подробнее об авторе
Карточки - удобный способ проверки знаний учащихся. Карточки-пятиминутки подготовлены по теме "Сложение и вычитание чисел в пределах 20" и подойдут для учащихся 1-2 классов. Можно использовать как проверочную работу в начале урока, а также в индивидуальной работе. Карточки разрезаются и раздаются детям. В набор входит 8 заданий в виде цепочек примеров.

Краткое описание методической разработки

Карточки - удобный способ проверки знаний учащихся.

Карточки-пятиминутки подготовлены по теме "Сложение и вычитание чисел в пределах 20" и подойдут для учащихся 1-2 классов. Можно использовать как проверочную работу в начале урока, а также в индивидуальной работе.

Карточки разрезаются и раздаются детям. В набор входит 8 заданий в виде цепочек примеров.

Развернуть описание
Смотреть ещё 5 584 курса

Методические разработки к Вашему уроку:

Рабочие листы
к вашим урокам

Скачать

Скачать материал

Найдите материал к любому уроку, указав свой предмет (категорию), класс, учебник и тему:

7 237 140 материалов в базе

Скачать материал

Другие материалы

Вам будут интересны эти курсы:

Оставьте свой комментарий

Авторизуйтесь, чтобы задавать вопросы.

Оформите подписку «Инфоурок.Маркетплейс»

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

Мини-курс

Понимание психологических феноменов

4 ч.

699 руб.
Подать заявку О курсе

Мини-курс

Успешное трудоустройство: от поиска до карьерного роста

3 ч.

699 руб.
Подать заявку О курсе

Мини-курс

Управление рисками в бизнесе: анализ, оценка и стратегии

4 ч.

699 руб.
Подать заявку О курсе
Смотреть ещё 5 584 курса