Опубликован: 11.02.2005 | Уровень: специалист | Доступ: платный
Лекция 11:

Автоматное преобразование структурированных текстов

< Лекция 10 || Лекция 11: 12 || Лекция 12 >

Применим возможности системы 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>
  </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>
    <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Можно было бы оформить эти теги с помощьюо особого состояния Init, но при этом мы бы потеряли универсальность тега <state>, т. к. состояние Init, например, не нуждается в чтении символа, не содержит условий и должно быть всегда первым. Как будет понятно впоследствии, универсальность составных частей модели упрощает работу с ней..
  • Каждый <state> содержит атрибут name, чтобы на него можно было ссылаться, и набор условий: один тег <if> и любое количество тегов <eif> (означающих " else if "). Эти два тега также можно было бы заменить одним универсальным, тем более что структура их потомков не различается, но опять же этого не сделано по соображениям облегчения форматирования.
  • Каждый <if> или <eif> включает в себя три тега: <condition> — собственно условие и уже описанные теги <action> и <ref> — действие при выполненном условии и ссылка на следующее состояние.
  • Теги <action> и <condition> содержат специальный тег <![CDATA[...]]> для включения строк на языке C++.

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

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

<?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-основы в программу на языке С/С++. Стоит обратить внимание на то, что результирующий текст оказывается практически тем же, что и в программе 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>
</xsl:stylesheet>
Листинг 11.2.3. Решение задачи автоматической трансформации таблиц конечного автомата

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

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

Отметим теперь еще несколько интересных возможностей, которые мы бы могли использовать.

Хотя данная технология позволяет легко создавать С++/С# программы, основой для них остается язык XML. Чтобы составить новый автомат, программист должен как минимум знать синтаксис этого языка. Следующим естественным шагом будет исключение этого звена: требуется скрыть внутреннее представление данных от конечного пользователя, оставив только интуитивно понятное представление в виде таблицы. Но для этого в первую очередь необходимо выбрать:

  • преобразование таблица => XML представление и
  • средство для удобного редактирования таблиц.

Естественно редактировать таблицы там же, где мы их уже научились генерировать — в окне браузера. Доступ к редактированиюэтих таблиц может предоставить DOM (стандарт, реализованный в браузерах Internet Explorer 5.0 и Netscape Navigator 6.0). Изменения, добавления и другие редактирующие действия определяются довольно просто. Например, на языке Java script добавление новой ячейки в таблицу можно описать следующим образом:

var oRow;
var oCell;

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 перечисляют возможные имена элементов, определяют имеющиеся атрибуты для каждого типа элементов и сочетаемость одних элементов с другими.

Каждая строка в определении типа документа может содержать декларацию типа элемента, именовать элемент и определять тип данных, которые элемент может содержать. Она имеет следующий вид:

<!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 будут, видимо, заменены более мощными и простыми в использовании схемами, работа над которыми ведется в настоящее время.

< Лекция 10 || Лекция 11: 12 || Лекция 12 >
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

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

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?

Денис Сафронов
Денис Сафронов
Россия
жылдыз насырбекова
жылдыз насырбекова
Киргизия, бишкек