Общая характеристика системы

Учебно-исследовательская система конструирования формальных языков (ФЯ) "Грамматика" предназначена для автоматизированной раз­работки предметно-ориентированных языков. Система предлагает мето­дологию и набор программных средств, позволяющих существенно со­кратить объем работ по программированию при создании трансляторов. В учебном процессе система может быть полезна при изучении теории формальных языков и грамматик, теории компиляции, а также в приоб­ретении практических навыков разработки языков. Данные методические указания содержат описание компонент системы "Грамматика" и прин­ципов ее использования. Основы теории формальных языков и грамма­тик и теории компиляции изложены в [1,2,3,4,5,6].

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

"Образцом" является грамматика ФЯ, полностью описывающая множество разнообразных фразовых структур, которые могут быть ис­пользованы в "Описании".

Анализатор в этой схеме является универсальной программой, функ­ционирующей с использованием любого Образца. Смена Образца фор­мально приводит к определению нового ФЯ.

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

Если рассматривать Описание как программу на ФЯ, то План будет определять результат трансляции этой программы.

Описание, Образец и План определяют структуры соответствую­щих файлов.

Описанная упрощенная схема реализуется в системе "Грамматика" следующими компонентами:

• подсистемой спецификации ФЯ,

• подсистемой анализа описаний на ФЯ и формирования результатов такого анализа.

Подсистема спецификации ФЯ включает в себя:

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

• анализатор корректности спецификации формального языка. Подсистема анализа описаний на ФЯ включает в себя:

• лексический анализатор предложения,

• синтаксический анализатор предложения.

2. СПЕЦИФИКАЦИЯ ФОРМАЛЬНОГО ЯЗЫКА

Спецификация ФЯ, именуемая грамматикой, представляет собой текст, содержащийся в некотором файле; файл может иметь любое имя и расширение, по умолчанию используется расширение "grm". Специфика­ция выполняется на метаязыке, в основе которого лежит расширенный формализм Бэкуса-Наура.

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

имя_продукции::= тело_продукции **

Здесь имя_продукции - идентификатор, определяющий уточняемое поня­тие (нетерминал),

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

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

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

А::=...<_ В _>...**

В::=....**

Могут быть два исключения из этого правила:

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

2) Используемый в теле продукции нетерминал является предопре­деленным, т.е. внесенным в библиотеку уточняемых понятий системы.

В качестве ключевого слова языка может выступать любой иденти­фикатор, принадлежащий конструируемому языку. Он определяется по­следовательностью букв латинского и/или русского алфавита, арабских цифр, символа пробела, начинающейся с буквы, например procedure, begin, end. Идентификатор может иметь любую длину, однако отметим, что описываемая система анализирует только первые 32 символа, про­писные буквы равнозначны строчным.

Разделителем является последовательность символов, не являю­щихся буквами латинского или русского алфавитов, цифрами, символа­ми пробела, табуляции, конца строки. К разделителям относятся, напри­мер,:;, >= <> =! @. Система различает разделители по первым 8 симво­лам.

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

<_ и _> - скобки нетерминала. Любой текст, используемый внутри скобок нетерминала, интерпретируется системой как имя продукции, на­пример, <_Список_параметров_>.

[_ и _] - скобки факультативного элемента грамматики. Такой эле­мент определяет синтаксическую структуру, которая может отсутство­вать в описаниях на ФЯ. Например, элемент [_ (ABC) _] означает, что образец (ABC) может быть использован для анализа текущего фрагмента описания, а может быть, и нет.

{_ и _} - скобки итеративного элемента, т.е. элемента, который мо­жет повторяться в описании на ФЯ 0,1 или более раз. Например, элемент {_ <_АВС _> _} означает, что образец (ABC) может последовательно ис­пользоваться для анализа фрагмента описания 0, 1, 2,... раз. Другими словами, этот элемент допускает следующие строки фрагмента описания:

-пустая строка

-(ABC)

-(ABC) (ABC)

-(ABC) (ABC) (ABC)

?_ и _|_ и _? - скобки и разделитель списка альтернатив. Данная кон­струкция используется при анализе строки описания на соответствие од­ному из указанных вариантов. Например, конструкция?_ + _|_ - _|_ * _|_ / _? означает символ + или - или * или /.

(_ и _) - скобки семантики. Между скобками должно быть указано целое число в диапазоне 0..65535, означающее номер семантической про­цедуры, например, (_15_). Сведения, необходимые для разработки набора этих процедур, реализующего семантический анализ текста на ФЯ, изло­жены в разделе "Анализ текста на формальном языке".

(* и *) - скобки комментария. Текст, заключенный между этими скобками в грамматике ФЯ, при анализе игнорируется.

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

Система содержит три предопределенных нетерминала: Name, Numb, Real, порождающих соответственно множество идентификаторов произвольной длины с 32 первыми значащими символами, множество целых чисел без знака в диапазоне от 0 до 65535, множество веществен­ных чисел без знака в диапазоне от 2.9е-39 до 1.7е38.

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

1) Отсутствие левосторонней рекурсии.

Продукции видов

А::=<_А_>... **,

А::= [ _<_А_>... и т.п.

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

А::=?_ <_ А_> а _|_ а_? **

может быть заменена эквивалентной продукцией, свободной от "левой" рекурсии:

А::=а{_а_}** Возможны и другие эквивалентные преобразования.

2) Упорядочение альтернатив.

Рассмотрим грамматику:

А::= [_<_B_> _] <_С_> **

В::= abc **

С::= abc **

Если применить ее к анализу строки "abc", то результатом будет FALSE - "строка не соответствует грамматике". Это обусловлено тем, что факультатив [_ <_ В _> _] эквивалентен альтернативе с пустой второй ча­стью:?_ <_ В _> _|_ _?. Использование такой грамматики при анализе строки "abc" приводит к заключению:

(<_ В _>"abc" = TRUE) AND (<_ С _>" " = FALSE) = FALSE; (здесь "" - пустая строка). Если же заменить продукцию

A::=[_<_B_>_] <_C_> ** на эквивалентную (только для этого примера!)

А::=<_С_>[_<_В_>_]** то результатом сопоставления строки "abc" с образцом А будет

(<_ С _>"abc" = TRUE) AND (<_ В _>" " = TRUE) = TRUE. Такие коллизии возникают при использовании альтернатив с иден­тичными начальными частями вариантов. Например,

А::=?_ ab _|_ abc _|_ abce _? d **

Анализ входной строки "abcd" по этой продукции приведет к ре­зультату FALSE, поскольку первый вариант альтернативы (ab) дает ре­зультат TRUE, а оставшаяся подстрока "cd" дает результат FALSE при сопоставлении с образцом d. Переупорядочение вариантов по принципу "длинные вперед" приведет к правильному результату.

Любая правильно оформленная грамматика должна быть провере­на на корректность. Анализ грамматики на корректность связан с выяв­лением ошибок в спецификации языка. Простейшие из них:

1) неопределенные нетерминалы (нетерминалы, не принадлежащие к предопределенным и не имеющие эквивалентов среди имен продукций);

2)недостижимые нетерминалы (имя нетерминала не используется в телах продукций);

3)ошибки следования метасимволов.

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

По результатам анализа грамматики система выдает следующие со­общения:

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

2) для некорректной грамматики выдается список выявленных ошибок.

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

Программа::= program <_Name_>;

[_ <_ Константы _> _]

[_ <_ Переменные _> _] begin

{_ <_ Операция _> _} end. **

Константы::= const {_ <_Name_> = <_Число_>; _} **

Переменные::= var {_ <_Name_> {_,<_Name_>_}:.

<_Стандартный_тип_>; _} **

Число::=?_ <_Numb_> _|_ <_Real_> _? **

Стандартный_тип::=?_ word _|_ byte _|_ char _|_ real _? **

Операция::= <_Name_>:= <_ Выражение_> **

Выражение::= <_Операнд_> {_ <_Знак_Операции _> <_Операнд_> _}; **

Операнд::=?_ <_Name_> _|_ <_Numb_> _|_ <_Real_> _? **

Знак_Операции::=?_ + _|_-_|_ *_|_/_? **

Данная грамматика определяет язык, допускающий предложения типа

program Example;

const pi=3.14; r=2.0;

var len, r: real; begin

len:=2*pi*r; end.


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



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