Рефераты. Разработка конвертора из текстового формата nroff в гипертекстовый формат HTML

Можно пользоваться и внутренними функциями ввода-вывода. К ним относятся:

         1.  input() следующий символ из потока;

         2.  output(c) вывод символа в поток;

         3.  unput(c) возврат символа в поток.

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

Lex не использует без надобности просмотр вперед, но к нему приводят правила, содержащие /, или заканчивающиеся на один из следующих символов:

               + * ? $

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

Еще одна функция, которую иногда переопределяют, - yywrap. Она вызывается при достижении конца файла. Если она возвращает 1, выполняется нормальное завершение работы. Иногда бывает удобно организовать дополнительный ввод из другого источника. В этом случае пользователь пишет свою версию этой функции, которая выполняет новый ввод и возвращает 0. Это приводит к продолжению обработки. По умолчанию yywrap всегда возвращает 1.

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



Обработка неоднозначных правил.

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

          * Выбирается самая длинная последовательность.

          * Из всех подходящих правил выбирается первое.

Входной поток обычно разбивается на части так, что lex не ищет все возможные вхождения всех выражений. Каждый символ считается один и только один раз.

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



Чувствительность к левому контексту.

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

       Существует три способа обработки, используемые в различных условиях:

         1.  Применение флагов (при изменении условий правила меняются незначительно).

         2.  Использование начальных состояний.

         3.  Использование нескольких лексических анализаторов, работающих одновременно.


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


Задание определений.

       Рассмотрим общий формат входной спецификации:

               {определения}

               %%

               {правила}

               %%

               {программы пользователя}

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

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

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

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

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

         3.  Весь текст после третьего ограничителя %% копируется в генерируемую программу.

       Определения, предназначенные для lex, помещаются перед первым ограничителем %%. Любая строка этого раздела, не находящаяся внутри %{ %} и начинающаяся с позиции 1, считается строкой подстановки. Ее формат следующий:

               имя     подстановка

       Цепочкам из части подстановки присваивается имя. Имя и подстановка должны разделяться как минимум одним пробелом и имя должно начинаться с буквы. Подстановка вызывается в правиле с помощью конструкции {имя}.


Сгенерированные программы выполняют ввод-вывод символов только с помощью функций input(), output() и unput(). Используемое в этих функциях представление символов воспринимается lex и передается как возвращаемое значение в массиве yytext.  При внутреннем употреблении символ представлен небольшим целым числом, и при использовании стандартной библиотеки ввода-вывода его значение равно целому, соответствующему набору битов для этого символа в ЭВМ. Обычно символ a представлен так же, как и символьная константа:

               'a'

       Если это представление меняется с помощью функций ввода-вывода, выполняющих трансляцию, lex должен быть извещен об этом посредством таблицы трансляции.  Эта таблица должна находиться в разделе определений и ограничиваться строками, содержащими только %T.  Таблица содержит строки следующего формата:

               {целое} {символьная строка}

       Строки связывают с символом соответствующее значение.




Формат входного текста.

       Общий формат входного текста следующий:

               {определения}

               %%

               {правила}

               %%

               {подпрограммы пользователя}

       Раздел определений может содержать следующую информацию:

         1.  Определения в виде "имя пробел значение".

         2.  Включаемый фрагмент в виде "пробел фрагмент".

         3.  Включаемый фрагмент в виде

                     %{

                     фрагмент

                     %}

         4.  Начальные состояния в виде

                     %S имя1 имя2 имя3 ...

         5.  Таблицы наборов символов в виде

         %T

                    число пробел строка символов

                 %T

         6.  Модификация размеров внутренних таблиц в виде

                     %x nnn

             где nnn - десятичное число, соответствующее размеру массива, а x - параметр следующего вида:

             Символ  Параметр

             p       позиции

             n       состояния

             e       узлы дерева

             a       переходы

             k       упакованные символьные классы

             o       размер выходного массива

       Строки в разделе правил имеют следующий формат:

               выражение       действие

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

       В регулярных выражениях допустимы следующие операторы:

       x       Символ x.

       x       Всегда x, даже если это оператор.

       \x      Всегда x, даже если это оператор

       [xy]    Символы x или y.

       [x-z]   СИмволы x, y или z.

       [^x}    Любой символ кроме x.

       .       Любой символ кроме перевода строки.

       ^x      Символ x в начале строки.

       <y>x    Символ x, если lex находится в состоянии <y>.

       x$      Символ x в конце строки.

       x?      Необязательный x.

       x*      0, 1, 2 ... вхождений x.

       x+      1, 2, 3 ... вхождений x.

       x|y     x или y.

       (x)     x.

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.