Представление грамматик
В лекциях "Грамматика" и "Описание формальных грамматик" давалось определение грамматик, операций над символами, вывод на основе грамматик и т.д., но ничего не говорилось о представлении грамматик, т.е. об их компактной записи. В этом разделе мы восполним этот пробел в описании грамматик
12.1. Другие регулярные выражения
Мы рассмотрели основные области применения регулярных выражений:
- Командные оболочки операционных систем;
- Текстовые редакторы;
- "Скриптовые" языки текстовых редакторов и операционных систем.
Однако существуют и другие области применения регулярных выражений. Об одной из них автор расскажет ниже.
Определения синтаксиса документов XML
Язык XML (eXtended Markup Language - "расширенный язык разметки"). Этот язык предназначен для создания других языков разметки. Разметка служит для "отделения" структуры документа от его содержания. Но для того, чтобы определить структуру самого XML файла, необходимо создать DTD файл.
DTD расшифровывается как: "document type definition" (определение типа документа). Все допустимые для языка, описываемого XML, компоненты (элементы и атрибуты) и все правила (иерархия вложенности и т.п.) записываются в файл DTD. Более подробно об DTD и XML см. [43]. Здесь будет рассказано только часть, которая касается регулярных выражений.
Все объявления типов документов должны начинаться с набора символов: <!DOCTYPE . Следующее слово - это имя документа, оно должно соответствовать корневому элементу документа.
В документе на XML-совместимом языке могут использоваться только те элементы, которые были заранее объявлены в DTD. Синтаксис объявления элемента следующий:
<!ELEMENT Имя_Элемента Указание_на_тип>Листинг 12.1.
Тут мы подходим к самому главному: элемент <Указание_на_тип> может быть не только предопределенным в ЭВМ типом, но и регулярным выражением, включающий в себя другие элементы!
В качестве индикаторов вхождений используются следующие символы:
- ? - Ноль или один раз (необязательное вхождение);
- * - Ноль или несколько раз (необязательное повторяющееся вхождение);
- + - Один или несколько раз (обязательное повторное вхождение).
[Пример 01]
<!ELEMENT JDATA (OBJECT)+>
означает, что элемент JDATA должен содержать хотя бы один элемент OBJECT ;
<!ELEMENT OBJECT (PRIMITIVE | OBJECT | ARRAY)+>
этот пример показывает, что элемент OBJECT должен включать в себя, по крайней мере, один из следующих элементов: PRIMITIVE, OBJECT или ARRAY ;
<!ELEMENT PRIMITIVE (#PCDATA)>
элемент PRIMITIVE может содержать только первичные (символьные)данные и не может - вложенные субэлементы. PCDATA расшифровывается как "parsed character data" ("анализируемые символьные данные");
<!ELEMENT ARRAY (PRIMITIVE+ | OBJECT+ | ARRAY)>
расшифруйте это определение сами;
<!ELEMENT FOO ((PRIMITIVE, ARRAY) | (ARRAY, PRIMITIVE))>
последний пример показывает, каким образом можно использовать группы субэлементов. В нашем случае элемент FOO может содержать вложенные элементы PRIMITIVE и ARRAY, причем в любой последовательности.
Как можно убедиться, что нотация РБНФ и нотация DTD имеет много общего. Но, если РБНФ порождает собой грамматику и основанный на ней язык, то DTD служит только для определения формата XML файла.
[Пример 02]
Рассмотрим "программную запись" адресной книги. В ней будут следующие записи:
- Фамилия
- Имя
- Адрес
- Телефон
При этом адрес содержит:
- Улица/дом
- Город
- Область
- Страна
- Индекс
В этом случае РБНФ для адресной книги будет следующая:
<адресная книга> ::= {<адресная запись>}* <адресная запись> ::= <Фамилия><Имя><Адрес><Телефон> <Фамилия> ::= #PCDATA <Имя> ::= #PCDATA <Телефон> ::= #PCDATA <Адрес> ::= {<Улица>}+<Город>[<Область>]<Страна><Индекс> <Улица> ::= #PCDATA <Город> ::= #PCDATA <Область> ::= #PCDATA <Страна> ::= #PCDATA <Индекс> ::= #PCDATA
Та же запись на DTD будет:
<?xml version="1.0"?> <!DOCTYPE ADDRESS_BOOK SYSTEM "a_book.dtd"> <!ELEMENT ADDRESS_BOOK (ADDR)*> <!ELEMENT ADDR (SURNAME, NAME, ADDRESS, PHONE)> <!ELEMENT ADDRESS ((STREET)+, CITY, (REGION)?, ZIP)> <!ELEMENT SURNAME (#PCDATA)> <!ELEMENT NAME (#PCDATA)> <!ELEMENT PHONE (#PCDATA)> <!ELEMENT STREET (#PCDATA)> <!ELEMENT CITY (#PCDATA)> <!ELEMENT REGION (#PCDATA)> <!ELEMENT ZIP (#PCDATA)>
Пример структуры записи в адресной книге:
<ADDRESS_BOOK> <ADDR> <SURNAME></SURNAME> <NAME></NAME> <ADDRESS> <STREET></STREET> <STREET></STREET> <CITY></CITY> <ZIP></ZIP> </ADRESS> <PHONE></PHONE> </ADDR> </ADDRESS_BOOK>
Как и грамматику, так и XML-документы проверяют на однозначность.
Основное применение XML - создание новых языков разметки, семантических сетей, фреймов, интерфейса с базами данных и т.п.
12.2. Бэкусовская нормальная форма (БНФ)
Эта форма записи грамматик была разработана Бэкусом [18] для описания языка АЛГОЛ в сообщении о языке АЛГОЛ 60 (см. Наур [20, 60]). Поскольку Наур был редактором сообщения, то эту форму записи также называют формой Бэкуса - Наура.
Отличительные особенности БНФ:
- К зарезервированным символам БНФ относят: '<', '>', '|', ':', '=', '\';
- Нетерминалы (аналог "нетерминальных символов") пишутся внутри знаков разметки '< … >' ;
- Терминальные символы пишутся "как есть";
- Альтернативы разделяются знаком '|';
- Левая и правая часть правил разделяются сочетанием "::=";
Например, грамматика из примера 01 "Описание формальных грамматик" будет выглядеть так:
[Пример 03]
<число> ::= <чс> <чс> ::= <чс><цифра>|<цифра> <цифра> ::= 0|1|2|3|4|5|6|7|8|9
Предложенная Бэкусом форма записи грамматики стала гораздо компактнее, чем используемые ранее формы для написания грамматик. Она предназначена в основном для записи КС-грамматик и А-грамматик (см. раздел 4.3 "Описание формальных грамматик" ).
12.3. Расширенная БНФ (РБНФ)
В литературе для описания синтаксиса различных языков используются и другие формы записи, примером которой может служить РБНФ. Она обладает такой же мощностью, что и БНФ, но она еще более компактна в записи. Перечислим основные нововведения в РБНФ:
Фигурные скобки
Выражение с их участием записывается как:
{<терминал или нетерминал>}<модификатор>
Фигурные скобки означают, что выражения в них может повторяться от 0 до бесконечности, или согласно модификатору:
- Необязательный модификатор " * " означает, что выражение в скобках может повторяться ноль или бесконечное число раз;
- Модификатор " + " означает, что выражение в скобках может повторяться от 1 до бесконечного числа раз;
- Модификатор (m,n) означает, что выражение в скобках может повторяться от m до n числа раз.
[Пример 04]
- <U> ::= a{ab} - цепочка, начинающаяся с a и содержащая ноль или более (до бесконечности) цепочек символов ab ;
- <U> ::= a{ab}+ - цепочка, начинающаяся с a и содержащая от одного до бесконечности повторений цепочки ab ;
- <U> ::= a{ab}(2,3) - содержит цепочки: aabab и aababab.
Квадратные скобки
В них заключено выражение, повторяющееся ноль или один раз.
Круглые скобки
В правых частях правил оператор конкатенации предшествует оператору выбора. Например, AB|C означает либо AB либо C. Если использовать круглые скобки как метасимвол, мы получим, что A(B|C) будет означать: либо AB, либо AC.
Диапазон
Чтобы указать, что символы, участвующие в разборе, расположены подряд один за другим, используется символ диапазона "-". Например, запись A-Z включает в себя все символы, расположенные между A и Z, включая эти символы.
Метасимволы и терминальные символы
Для того чтобы метасимволы: ':', '=', '|', '<', '>', '{', '}', '[', ']', '-', '+', '(', ')', '\' - могли использоваться как терминальные символы, перед ним вставляется знак '\'.
Таким образом, грамматика из (примера 01 "Описание формальных грамматик" ) в РБНФ будет выглядеть так:
[Пример 05]
<число> ::= {<цифра>}+ <цифра> ::= 0-9
Пример 06 "Описание формальных грамматик" в РБНФ может выглядеть так:
[Пример 06]
<врж> ::= [<врж>(\+|\-)]<терм> <терм> ::= [<терм>(*|/)]<множ> <множ> ::= [<множ>^]<степ> <степ> ::= \(<врж>\)|<идентификатор>|<число>
Однако чтобы приблизить пример 06 к регулярной грамматике, его следует записать следующим образом:
[Пример 07]
<врж> ::= <терм>[(\+|\-)<врж>] <терм> ::= <множ>[(*|/)<терм>] <множ> ::= [<множ>^]<степ> <степ> ::= \(<врж>\)|<идентификатор>|<число>
12.4. Резюме
В данной главе вы познакомились с одним из основных понятий искусственного интеллекта, информатики и алгебры - понятием "формальная грамматика". Вы поняли отличие "обычных" алгоритмов работы на ЭВМ с использованием символьных данных от собственно "символьных вычислений" на ЭВМ, научились разбору символьных выражений с использованием синтаксических деревьев и деревьев вывода. Самое главное - Вы поняли "логическую парадигму программирования" и ее использование в целях искусственного интеллекта.
Конечно же, в этом кратком введении в формальную грамматику "за бортом" осталось множество интересных алгоритмов. Это, прежде всего, алгоритмы "экспертных систем", "семантических сетей", "фреймов", алгоритмы построения "трансляторов" с языков программирования, разбора, проверки орфографии на "естественных языках" и т.п.. За этими алгоритмами автор отсылает к серьезной литературе по искусственному интеллекту, которую можно найти в библиотеке и во всемирной сети.
Теперь самое время отдохнуть, выпить чашку кофе, и … начать программировать!
Успехов Вам! Good Luck! Dankon!