Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Стили и методы программирования. Учебное пособие для СПО
.pdf
LATEX [15] или XML, то возникает задача описывать и
программировать преобразования подобных текстов. Решением этой
задачи могут быть специализированные языки преобразований текстов
либо соответствующие методики программирования, поддержанные
автоматизированным преобразованием спецификаций в программу.
Здесь мы рассмотрим методику, базирующуюся на автоматах.
Применим возможности системы XML/XSL к нашей задаче: описание
конечного автомата (за основу взята таблица переходов 9.1
).
<?xml version="1.0" encoding="windows-1251" ?>
<automat name="Test">
<action><![CDATA[char symbol; int cnt;]]>
</action>
<ref>St1</ref>
<state name="St1">
<if>
<condition><![CDATA[’a’<=symbol & symbol <= ’z’]]>
</condition>
<action><![CDATA[printf ("%c", symbol); cnt = 1;]]>
</action>
<ref>St2</ref>
</if>
<eif>
<condition> <![CDATA[ symbol != ’\n’]]>
</condition>
<action><![CDATA[/*Так как нужно печатать только слова,
действия не заполняются */ ]]>
</action>
<ref> St1 </ref>
</eif>
<eif>
<condition> <![CDATA[ symbol == ’\n’]]>
</condition>
<action><![CDATA[/*Так как нужно печатать только слова,
действия не заполняются */ ]]>
</action>
<ref> St3 </ref>
</eif>
Стили и методы программированияНепейвода Н.Н.
191

</state>
<state name="St2">
<if>
<condition><![CDATA[ ’a’<=symbol & symbol <= ’z’]]>
</condition>
<action><![CDATA[printf ("%c", symbol); cnt++;]]>
</action>
<ref>St2</ref>
</if>
<eif>
<condition><![CDATA[ symbol != ’\n’]]>
</condition>
<action><![CDATA[printf (" - %i\n", cnt);]]>
</action>
<ref>St1</ref>
</eif>
<eif>
<condition> <![CDATA[ symbol == ’\n’]]>
</condition>
<action><![CDATA[printf (" - %i\n", cnt);]]>
</action>
<ref>St3</ref>
</eif>
</state>
<state name="St3">
<if>
<condition><![CDATA[’a’<=symbol & symbol <= ’z’]]>
</condition>
<action><![CDATA[printf ("%c", symbol); cnt = 1;]]>
</action>
<ref>St2</ref>
</if>
<eif>
<condition> <![CDATA[ symbol != ’\n’]]> </condition>
<action><![CDATA[/* Так как нужно печатать только слова,
действия не заполняются */ ]]>
</action>
<ref> St1 </ref>
</eif>
Стили и методы программированияНепейвода Н.Н.
192

<eif>
<condition> <![CDATA[ symbol == ’\n’]]>
</condition>
<action><![CDATA[/* Переход не требует чтения,
symbol == ’\n’ не нужно читать */ ]]>
</action>
<ref>Exit</ref>
</eif>
</state>
</automat>
Листинг 11.2.1. Решение задачи автоматической трансформации
таблиц конечного автомата
В этом описании нашли отражение следующие свойства нашего
конечного автомата (за основу взята таблица переходов 9.1
):
Конечный автомат (тег <automat> ) включает в себя теги
<state> — перечень всех состояний в любом порядке, а также
теги <action> — действие и <ref> — ссылка на исходное
состояние
3)
.
Каждый <state> содержит атрибут name, чтобы на него можно
было ссылаться, и набор условий: один тег <if> и любое
количество тегов <eif> (означающих " else if "). Эти два тега
также можно было бы заменить одним универсальным, тем более
что структура их потомков не различается, но опять же этого не
сделано по соображениям облегчения форматирования.
Каждый <if> или <eif> включает в себя три тега:
<condition> — собственно условие и уже описанные теги
<action> и <ref> — действие при выполненном условии и
ссылка на следующее состояние.
Теги <action> и <condition> содержат специальный тег <!
[CDATA[...]]> для включения строк на языке C++.
В описание не включено состояние Exit. Эта часть одинакова у
различных автоматов, а потому нецелесообразно ее описывать явно.
Данное описание служит основой для построения различных
визуализаций автомата с помощью XSL. Например, достаточно просто
Стили и методы программированияНепейвода Н.Н.
193

строится табличная визуализация, практически не отличающаяся от
ранее составленной таблицы:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<DIV STYLE="font-family:Courier; font-size:12pt">
<xsl:for-each select="automat">
<TABLE border="1" width="75%">
<TR>
<TD colspan="3"><xsl:value-of select="action" /></TD>
<TD width="10%"><xsl:value-of select="ref" /></TD>
</TR>
<xsl:for-each select="state">
<TR>
<td rowspan="3" width="10%" valign="top">
<xsl:value-of select="@name" /></td>
<td><xsl:value-of select="if/condition" /></td>
<td><xsl:value-of select="if/action" /></td>
<td><xsl:value-of select="if/ref" /></td>
</TR>
<xsl:for-each select="eif">
<TR>
<TD><xsl:value-of select="condition" /></TD>
<TD><xsl:value-of select="action" /></TD>
<TD><xsl:value-of select="ref" /></TD>
</TR>
</xsl:for-each>
</xsl:for-each>
</TABLE>
</xsl:for-each>
</DIV>
</xsl:template>
</xsl:stylesheet>
Листинг 11.2.2. Решение задачи автоматической трансформации
таблиц конечного автомата
Следующая визуализация — это автоматическое преобразование XMLосновы в программу на языке С/С++. Стоит обратить внимание на то,
Стили и методы программированияНепейвода Н.Н.
194

что результирующий текст оказывается практически тем же, что и в
программе 10.2.5
. Причины тому глубже, чем простота преобразования.
Существование локального (без использования контекстно"=зависимой
информации) описания следует из структуры конечного автомата, не
требующей для определения перехода ничего вне состояния.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<blockquote>
<pre STYLE="font-family:Courier; font-size:12pt;" >
<xsl:for-each select = "automat">//C code for automat
"<xsl:value-of select="@name" />"
<![CDATA[
#include <stdio.h>
#define failure true
void main( void )
{]]>
<xsl:value-of select = "action"/>
goto <xsl:value-of select = "ref"/>;<br/>
<xsl:for-each select="state">
<xsl:value-of select="@name" />: symbol = getchar ();
<blockquote>if (<xsl:value-of select="if/condition" /> )
<blockquote>{ <xsl:value-of select="if/action" />
goto <xsl:value-of select="if/ref" />; }
</blockquote>
<xsl:for-each select="eif">
else if (<xsl:value-of select="condition" /> )
<blockquote>{ <xsl:value-of select="action" />
goto <xsl:value-of select="ref" />; }
</blockquote>
</xsl:for-each>
</blockquote>
</xsl:for-each>
Exit: return;<br/>}
</xsl:for-each>
</pre>
</blockquote>
</xsl:template>
Стили и методы программированияНепейвода Н.Н.
195

</xsl:stylesheet>
Листинг 11.2.3. Решение задачи автоматической трансформации
таблиц конечного автомата
Как легко видеть, разница этого и предыдущего стилевых файлов только
в том, что там, где для визуализации в таблицу вставляются
графические элементы, изображающие рамки, для трансляции
помещаются части синтаксиса языка С++/C# и отступы в целях лучшей
читаемости получаемой программы.
Итак, благодаря использованию формата представления данных XML,
мы получили возможность автоматически создавать программы для
данной задачи путем простой замены стилевых таблиц!
Отметим теперь еще несколько интересных возможностей, которые мы
бы могли использовать.
Хотя данная технология позволяет легко создавать С++/С# программы,
основой для них остается язык XML. Чтобы составить новый автомат,
программист должен как минимум знать синтаксис этого языка.
Следующим естественным шагом будет исключение этого звена:
требуется скрыть внутреннее представление данных от конечного
пользователя, оставив только интуитивно понятное представление в
виде таблицы. Но для этого в первую очередь необходимо выбрать:
преобразование таблица => XML представление и
средство для удобного редактирования таблиц.
Естественно редактировать таблицы там же, где мы их уже научились
генерировать — в окне браузера. Доступ к редактированиюэтих таблиц
может предоставить DOM (стандарт, реализованный в браузерах Internet
Explorer 5.0 и Netscape Navigator 6.0). Изменения, добавления и другие
редактирующие действия определяются довольно просто. Например, на
языке Java script добавление новой ячейки в таблицу можно описать
следующим образом:
var oRow;
var oCell;
Стили и методы программированияНепейвода Н.Н.
196

oRow = oTable.insertRow();
oCell = oRow.insertCell();
oCell.innerHTML = "This cell is <b>new</b>."
Точно так же можно создавать таблицы, строки и ячейки в них.
Реализация же самого интерфейса (кнопочек, средств выделения, полей
ввода) зависит только от вашей фантазии.
Тот же DOM, точно таким же образом, может работать с XML,
реплицируя все действия конечного пользователя с таблицей в XML
представление для записи последнего в виде готового файла со
структурой нового конечного автомата.
Еще одним шагом в развитии проекта, использующим язык XML, может
быть формализация представления: ведь как только определены все теги
представления, правила их вложения и способы задания, получается
новый язык (по аналогии с современными языками, построенными
таким же образом, мы можем назвать его automatML). Пока теги и
элементы XML используются исключительно ради удобства для вашего
собственного проекта (как если бы вы применяли CSS на своей
домашней страничке), то не имеет никакого значения, что вы даете этим
элементам и тегам имена, смысл которых отличается от стандартного и
известен только вам. Если же Вы хотите предоставлять данные
внешнему миру и получать информацию от других людей, то это
обстоятельство приобретает огромное значение. Элементы и атрибуты
должны употребляться вами точно так же, как и всеми остальными
людьми, или, по крайней мере, вы должны документировать то, что
делаете.
Для этого придется использовать определения типов документов
(Document Type Definition, DTD). Хранимые в начале файла XML или
внешним образом в виде файла *.DTD, эти определения описывают
информационную структуру документа. DTD перечисляют возможные
имена элементов, определяют имеющиеся атрибуты для каждого типа
элементов и сочетаемость одних элементов с другими.
Каждая строка в определении типа документа может содержать
декларацию типа элемента, именовать элемент и определять тип
данных, которые элемент может содержать. Она имеет следующий вид:
Стили и методы программированияНепейвода Н.Н.
197

<!ELEMENT имя_элемента (тип_данных)>
Например, декларация
<!ELEMENT action (#PCDATA)>
определяет элемент с именем action, содержащий символьные
данные (т. е. текст). Декларация
<!ELEMENT automat (state_1, state_2, state_3)>
определяет элемент с именем automat, содержащий подэлементы
state_1, state _2 и state_3 в указанном порядке, например:
<automat>
<state_1>XML : время пришло</state_1>
<state_2>XML превосходит самое себя</state_2>
<state_3>Управление сетями и системами
с помощью XML</state_3>
</automat>
После определения элементов DTD могут также определять атрибуты с
помощью команды !ATTLIST. Она указывает элемент, именует
связанный с ним атрибут и затем описывает его допустимые значения.
Команда !ATTLIST позволяет управлять атрибутами и многими
другими способами: задавать значения по умолчанию, подавлять
пробелы и т. д. DTD могут содержать декларации !ENTITY, где
приводятся ссылки на объекты, и декларации !NOTATION,
указывающие, что делать с двоичными файлами, представленными не в
формате XML.
Серьезное и несколько удивительное ограничение DTD состоит в том,
что они не допускают типизации данных, т. е. ограничивают данные
конкретным форматом (таким, как дата, целое число или число с
плавающей точкой). Как вы, вероятно, уже заметили, DTD используют
иной синтаксис, нежели XML, и не очень-то интуитивно понятный. По
названным причинам DTD будут, видимо, заменены более мощными и
простыми в использовании схемами, работа над которыми ведется в
настоящее время.
Стили и методы программированияНепейвода Н.Н.
198

1)
В связи с этим данная лекция может быть опущена при изучении
курса.
2)
Тенденция отделения распознавания от обработки характерна и для
других стилей программирования. Но для сентенциального стиля она
оказывается решающей.
3)
Можно было бы оформить эти теги с помощьюо особого состояния
Init, но при этом мы бы потеряли универсальность тега <state>, т. к.
состояние Init, например, не нуждается в чтении символа, не
содержит условий и должно быть всегда первым. Как будет понятно
впоследствии, универсальность составных частей модели упрощает
работу с ней.
Стили и методы программированияНепейвода Н.Н.
199

Переход от данных к конечному автомату
Построение автомата по данным. Анализ автоматного
программирования.
Таблицы переходов и состояний представляют собой метод
программирования не только для задач, которые сводятся к конечным
автоматам. При обсуждении XML/XSL-подхода к задаче
стандартизованного представления таблиц переходов были указаны
возможности применения методики оперирования со структурными
представлениями данных и программ для более широкого класса
алгоритмов.
Однако мы пока не решали задачи, когда представление алгоритма
зависит от входных данных. Она классифицирована для автоматов как
задача динамического порождения автомата (см. 9.3, пункт 3).
Конечно же, под таким углом зрения можно рассматривать трансляцию:
текстовый файл на входном языке есть часть данных, генерирующая
план обработки другой части данных, которая предъявляется при
решении конкретной задачи. Вторая задача подобного типа, для которой
разработаны методы, — это задача специализации универсальной
программы. Она также может рассматриваться как уточнение общего
плана, исходя из частичного знания обрабатываемых данных.
Упомянутые случаи характеризуются тем, что представление алгоритма,
зависящее от части входных данных, строится из заранее определенных
заготовок. Например, для трансляции такими заготовками являются
алгоритмы выполнения абстрактно-синтаксического представления
программы.
В данном разделе показан иной метод построения алгоритма,
зависящего от входных данных. Его идея в том, чтобы составить такое
представление алгоритма, которое допускает непосредственную
интерпретацию. Естественный путь демонстрации метода — взять за
основу известный класс алгоритмов, конкретный представитель
которого выбирается, исходя из знания о входных данных.
Обратимся к задаче, которая для каждого конкретного случая решается с
помощью конечного автомата специального вида (как и всегда, выбор
конкретного представления существенно влияет на сложность и другие
Стили и методы программированияНепейвода Н.Н.
200
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
