Научная статья на тему 'Синтаксические диаграммы Н. Вирта и граф-схемы в SYNTAX-технологии'

Синтаксические диаграммы Н. Вирта и граф-схемы в SYNTAX-технологии Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
797
66
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ГРАММАТИКИ / СИНТАКСИЧЕСКИЕ ДИАГРАММЫ Н. ВИРТА / WIRTH SYNTACTIC FLOWCHARTS / ГРАФ-СХЕМЫ / ТРАНСЛЯЦИИ / GRAMMARS / GRAPH-SCHEMES / REGULAR SPLINES / TRANSLATIONS

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Мартыненко Борис Константинович

Цель данной статьи методологическая. Описывается опыт применения модифицированных синтаксических диаграмм Н. Вирта в SYNTAX-технологии, разработанной в связи с реализацией языка программирования Алгол 68 в начале 1970-х.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

The purpose of the article is a methodological one. An application of modified the Wirth's syntactic charts is described in connection with the implementation of the programming language Algol 68 in the early 1970s.

Текст научной работы на тему «Синтаксические диаграммы Н. Вирта и граф-схемы в SYNTAX-технологии»

Мартыненко Борис Константинович УДК 519.682.1 +681.142.2

СИНТАКСИЧЕСКИЕ ДИАГРАММЫ Н. ВИРТА И ГРАФ-СХЕМЫ В SYNTAX-ТЕХНОЛОГИИ

Аннотация

Цель данной статьи - методологическая. Описывается опыт применения модифицированных синтаксических диаграмм Н. Вирта в SYNTAX-технологии, разработанной в связи с реализацией языка программирования Алгол 68 в начале 1970-х.

Ключевые слова: грамматики, синтаксические диаграммы Н. Вирта, граф-схемы, трансляции.

ВВЕДЕНИЕ

Среди календарных дат 2014 года есть одна, связанная с 80-летием Никлауса Вирта, автора языка программирования Паскаль [1], широко используемого в мире и в России для обучения программированию в старших классах школы и на первых курсах вузов. Вирт ввёл понятие синтаксических диаграмм, которое он использовал для наглядного представления структуры конструкций языка Паскаль. Впоследствии это понятие, родственное понятию графа, получило дальнейшие развитие и применение в качестве средства реализации систем обработки данных, управляемых синтаксисом языков.

Использование графов1 в математике началось ещё задолго до появления компьютеров. А когда они появились в 1950-х годах и программирование велось в кодах вычислительной машины в условных адресах, то программисты часто применяли блок-схемы для документирования управляющей структуры машинных программ. Вскоре это привело к появлению теории схем программ2 [2].

Плодотворно ставятся на графах и другие задачи программирования: оптимальное распределение памяти, исследование потока данных в программах, эквивалентные преобразования КС-грамматик, автоматическая генерация тестов, семантические сети Г.С. Цейтина [3] в задачах искусственного интеллекта и т. д.

В начале 1970-х группа сотрудников Вычислительного центра и лаборатории математической лингвистики Ленинградского государственного университета под научным руководством Г.С. Цейтина приступила к изучению языка программирования Алгол 68 [4], и вскоре

1 Отцом теории графов (так же как и топологии) является Эйлер (1707-1782), решивший в 1736 г. широко известную в то время задачу, называвшуюся проблемой кёнигсбергских мостов.

2 Схемы Янова — схемы программ, которые были введены в литературу А.А. Ляпуновым и Ю.И. Яновым в 1958 г. и направлены на разработку общей теории условий, управляющих последовательностью выполнений операторов в программе.

© Мартыненко Б.К., 2014

к его реализации на ЕС ЭВМ1 по заказу Научно-исследовательского центра электронной вычислительной техники (НИЦЭВТ) Министерства радиоэлектронной промышленности СССР (отчёт об этом проекте см. в [5]). Язык Алгол 68 в то время ещё не был «заморожен»: поправки поступали в каждом номере Алгол-Бюллетеня, некоторые выпуски которого содержали вложения - микрофиши с описанием синтаксиса этого языка в виде синтаксических диаграмм Н. Вирта. Это привело к идее использовать синтаксические диаграммы Вир-та как основы для внутреннего представления структуры предложений входного языка в системе его реализации.

Синтаксис Алгола 68 определяется двухуровневыми грамматиками А. ван Вейнгаарде-на, порождающими рекурсивно перечислимые множества, задача распознавания которых в общем случае алгоритмически не разрешима. Исходную грамматику можно было рассматривать лишь как первоначальную форму спецификации синтаксиса языка, то есть только как документ. Требовалось найти эффективный метод анализа языка Алгол 68 на основе других, более простых, классов грамматик и построить адекватный инструмент, его реализующий. Позднее он был воплощён в технологическом комплексе (ТК) SYNTAX [6].

1. ТРАНСЛЯЦИОННЫЕ RBNF-ГРАММАТИКИ

В SYNTAX-технологии трансляционные RBNF-грамматики являются двухуровневым формализмом для спецификации трансляций, который состоит из управляющей RBNF-грам-матики, представляющей синтаксический уровень спецификации языка, и описания операционной среды, представляющего его семантический уровень.

Трансляционная грамматика есть формальная система Gt = (Gc, e), где Gc - управляющая грамматика; e - описание операционной среды.

1.1. Управляющая RBNF-грамматика определяет синтаксис входного языка, вернее, способ его обработки (трансляции) через синтаксическую структуру его предложений отличается от обычной BNF-грамматики2 тем, что в ней помимо алфавитов нетерминалов и терминалов имеются два дополнительных алфавита контекстных символов: семантических ирезольверных, а правые части правил представляют собой регулярные выражения над символами всех алфавитов грамматики. Эти выражения трактуются как формулы с регулярными операциями над множествами цепочек, составленных из терминальных и контекстных символов. При этом считается, что терминальный или контекстный символ, используемый в качестве операнда регулярного выражения, представляет множество из одной односимвольной цепочки, а нетерминальный символ - множество3 всех цепочек, представляющее его значение.

Таким образом, множество правил RBNF-грамматики рассматривается как своего рода «алгебраическая» система, неявно определяющая значения всех нетерминалов в качестве её неизвестных, в то время как все прочие символы, точнее одноэлементные множества, ими представляемые, играют роль её коэффициентов.

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

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

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

1 Советский аналог серии System/360 и System/370 фирмы IBM, выпускавшихся в США с 1964 г.

2 КС-грамматика, представленная в форме Бэкуса-Наура.

3 Возможно, бесконечное.

верным символом - некоторый предикат, заданный на множестве состоянии операционном среды.

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

Управляющая КБ^-грамматика есть формальная система Gc = N Т, ЭТ, Е, P, S), где N - словарь нетерминальных символов или нетерминалов; Т - словарь терминальных символов или терминалов; ЭТ - словарь резольверных символов или резольверов; Е - словарь семантических символов или семантик; Р = {А: жа\ А е N ЖА - регулярное выражение относительно символов из множества N и Т и ЭТ и Е - множество правил, £ - начальный нетерминал.

Управляющая грамматика специфицирует синтаксическое управление - множество цепочек с = Х(Ж3) над терминальными и контекстными символами (то есть символами из множества Т и ЭТ и Е, где А,(ж) определяется в зависимости от вида ж следующим образом:

^ {а}, если ж = а, а е (Т и ЭТ и 2) или а = в;

Л,(жа), если ж = А, А е N 3 р е Р,р = А: жа.;

и (ЦЗД*, если r = r1*;

X(r) = i

и (^(r1))k, если r = r1+;

ц r1) U (^(r2)^(r1))k, если r = r1 # r2;

k=1

A,(r1) A,(r2), если r = r1, r2;

A,(r1) u A,(r2), если r = r1; r2;

^(r1) u {в}, если r = [r1];

Здесь r1 и r2 - некоторые регулярные выражения. Определение вида регулярного выражения производится с учётом старшинства операций и расстановки скобок. Предполагается, что наивысшее старшинство имеют унарные операции *-Клини и + -Клини, затем бинарные операции - итерация с разделителем (#), далее конкатенация (,) и, наконец, объединение (;).

1.2. Описание операционной среды. Описанием операционной среды называется формальная система e = (E, H, i^, 1е, e0), где E - пространство состояний операционной среды - область определения предикатов, ассоциированных с резольверными символами: 1<r ={lp : E ^ {false, true} | р е и преобразований состояний операционной среды, ассоциированных с семантическими символами: = {ic : E ^ E | с е Е}; H - объектное подпространство, то есть та часть операционной среды, состояние которой представляет особый интерес2; e0 е E - начальное состояние операционной среды.

2. ТРАНСЛЯЦИЯ, ОПРЕДЕЛЯЕМАЯ ТРАНСЛЯЦИОННОЙ ГРАММАТИКОЙ

Пусть e е E - некоторое состояние операционной среды, р е - некоторая резоль-

Е*

- некоторая семантическая цепочка.

1 Порядок синхронизации преобразований с вычислением предикатов определяется в разд. 3.

2 Например, выходной файл.

со

k = 0

k=1

Положим по определению

l (e) ={ lpj(e) & \y(e), если р = рхр', рхе р'е^*, р I true, если р = в;

*a(e) ={'

^ (

ic'(ic1(e)), если с = схс', схе Е, с'е Е*, e, если с = в;

Здесь и iCi определяются описанием операционной среды, а 1р' и ic' - рекурсивные ссылки на соответствующие определения, приведённые выше.

Трансляционная грамматика определяет трансляцию: x(Gt) = {(х, [e]H) | 3 cx(cx е C(Gc), cx = к0а1к1а2...кш_^mKm - управляющая цепочка; к. е (^ и Е)* (/ = 0, 1, 2, ..., m) - цепочки контекстных символов, в которых р. е - резоль-верные подцепочки, с.е Е* - семантические подцепочки; а. е T(j = 1, 2, ..., m) - терминальные символы; х = a1a2...am - входная цепочка (предложение входного языка); e = ic (•••iC1(e0)) -финальное состояние операционной среды при условии, что 1р0(е0) & 1р1(е1) & ... & 1р (em) выполняется, где en+1= ic (en) (n = 0, 1, ..., m); очевидно, что e = em+1)}. Здесь [e]H обозначает проекцию точки e е E на объектное подпространство H - результат трансляции входной цепочки х.

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

Синхронизация означает, что сначала вычисляются предикаты, ассоциированные с ре-зольверными символами, предшествующими терминалу а1, в порядке их следования. Если все они выполняются, то исполняются преобразования состояния операционной среды, ассоциированные с семантическими символами, предшествующими терминалу a1 (также в текстуальном порядке). Затем аналогичным порядком выполняются резольверы и семантики, предшествующие терминалу a2, и т. д. Процесс заканчивается, когда успешно завершается вычисление конъюнкции предикатов, следующих за символом am, и исполнение соответствующих семантик.

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

Если некоторому входному предложению соответствует несколько управляющих цепочек с разными семантическими составляющими, то такое предложение называется семантически неоднозначным. В SYNTAX-технологии семантическая неоднозначность не допускается1. Однако использование резольверов во многих случаях помогает избегать этой опасности.

В ТК SYNTAX управляющие грамматики записываются на языке TSL2. Именно по ним генерируются граф-схемы. Операционная среда описывается на языке программирования Borland Pascal 7.0 и после компиляции представляется в виде DLL-библиотеки.

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

1 Фактически семантическая неоднозначность контролируется при построении управляющих таблиц процессоров (см. [6]).

2 Описание языка TSL дано в [6, гл. 8].

CALC — трансляционная грамматика калькулятора

MICROLEXICS

Lexical classes: d, '.', 'e', '+', '-', '*', '/', '(', ')', EOF, Escaped Symbols.

d: '0' ..'9'. Escaped Symbols: #32, #13, #10. EOF: ''.

SYNTAX

Nonterminals: PROGRAM (ПРОГРАММА), EXPRESSION (ВЫРАЖЕНИЕ).

Terminals: 'd', '.', 'e', '+', '-', '*', '/', '(' , ')', 'EOF'.

Auxiliary notions: NUMBER (ЧИСЛО), INTEGER NUMBER (ЦЕЛОЕ), FRACTIONAL PART (ДРОБНАЯ_ЧАСТЬ), EXPONENT PART (ПОРЯДОК), DIGIT (ЦИФРА), MONADIC OPERATION (УНАРНАЯ_ОПЕРАЦИЯ), DYADIC OPERATION (БИНАРНАЯ_ОПЕРАЦИЯ), OPERAND (ОПЕРАНД).

Forward pass semantics: Reset, Complete, Push Mon{adic} Op{eration}, Push Dyadic Op{eration}, Push Op{eran}d, Push Open Par{enthisis}, Unload And Discard Open Par{enthisis}, Init Int{eger Number}, App{end} Dig{it}, Set Int{eger} Part, App{end} Exp{onent} Part, Set Fr{actional} Part, App{end} Fr{actional} Part, Set Exp{onent}, Set Dig{it}, Set Sign.

PROGRAM: Reset, EXPRESSION, Complete, 'EOF'.

EXPRESSION: ((MONADIC OPERATION)*, OPERAND) # DYADIC OPERATION.

OPERAND: NUMBER, Push Op{eran}d;

Push Open Par{enthisis}, '(', EXPRESSION, Unload And Discard Open Par{enthisis}, ')'. NUMBER: INTEGER NUMBER, Set Int{eger} Part, [FRACTIONAL PART, App{end} Fractional} Part],

[EXPONENT PART, App{end} Exp{onent} Part]. INTEGER NUMBER: Init Int{eger Number}, (Set Dig{it}, DIGIT, App{end} Dig{it})+. FRACTIONAL PART: '.', INTEGER NUMBER, Set Fractional} Part. EXPONENT PART: 'e', Set Sign, (['+']; '-'), INTEGER NUMBER, Set Exp{onent}. DIGIT: 'd' .

MONADIC OPERATION: Push Mon{adic} Op{eration}, ('+'; '-'). DYADIC OPERATION: Push Dyadic Op{eration}, ('+' ; '-' ; '*' ; '/').

Поясним, что спецификация трансляционной грамматики состоит из трёх разделов. Раздел microlexics содержит информацию для построения транслитератора. Задача последнего - распределить символы входного алфавита по лексическим классам. Именно лексические классы, а не сами символы, управляют процессом обработки входного текста на стадии синтаксиса, описываемого в разделе SYNTAX.

Из словаря нетерминалов выделяются вспомогательные понятия (Auxiliary notions), если они определяются прямо или косвенно регулярными выражениями. Они вставляются в граф-схему механизмом макроподстановок.

Разделы environment и implementation, описывающие окружение и интерпретацию контекстных символов в этом окружении, здесь не показаны. Они, как сказано выше, преобразуются в DLL-библиотеку посредством транслятора на той платформе, на которой реализуется инструментальный комплекс SYNTAX-технологии.

3. СПЕЦИФИКАЦИЯ ТРАНСЛЯЦИЙ ПРИ ПОМОЩИ ТРАНСЛЯЦИОННЫХ ГРАФ-СХЕМ

В SYNTAX-технологии используется три различных формы спецификации трансляций, одна из которых (RBNF-грамматика) удобна для первоначального задания трансляций, другая (процессор) является формой реализации трансляций, а третья (трансляционная граф-

схема) есть промежуточная форма между двумя первыми. Эта форма, аналогичная синтаксическим диаграммам Вирта, может использоваться для описания синтаксиса языков и спецификации трансляций непосредственно, тем более что граф-схемы являются более гибким аппаратом для задания трансляций, чем грамматики1.

Трансляционная граф-схема G = (Gc, E), как и трансляционная грамматика, состоит из двух компонент: управляющей граф-схемы (Gc) и описания операционной среды (E), причём описание операционной среды (E) наследуется непосредственно от трансляционной грамматики (см. разд. 1).

Управляющая граф-схема является графовым аналогом управляющей грамматики. Каждое правило RBNF-грамматики представляется в виде отдельного связного ориентированного графа, вершины которого помечены терминалами или нетерминалами грамматики, а дуги - цепочками, составленными из резольверных и семантических символов, с возможными петлями, циклами и параллельными дугами (так что уместнее было бы говорить о псевдомультиграфе).

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

Пример граф-схемы, построенной по управляющей грамматике калькулятора до раскрытия вспомогательных понятий2, показан на рис. 1. Пунктирными рамками изображены вспомогательные понятия (Auxiliary notions), которые раскрываются с помощью макроподстановок, перед тем как по управляющей граф-схеме строится процессор. Дуги граф-схем помечены контекстными символами, в то время как дуги синтаксических диаграмм Вирта никак не помечаются. Только в этом их внешнее различие.

В общем случае управляющая граф-схема - это несвязный помеченный граф, в котором каждая компонента связности представляет одно правило управляющей грамматики. Очевидно, что управляющая граф-схема как формальная система вполне аналогична управляющей грамматике с той лишь разницей, что правила имеют графовую форму, то есть Gc=(N, T, Е, K, S), где N - нетерминалы, T - терминалы, ^ - резольверы, Е - семантики, K={KA | A е N, KA - компонента графа, определяющая нетерминал A}, S е N - начальный нетерминал.

Компоненту KS, определяющую начальный нетерминал S, назовем заглавной компонентой управляющей граф-схемы.

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

Назовем маршрут в некоторой компоненте управляющей граф-схемы полным, если он начинается в начальной и заканчивается в конечной вершине этой компоненты. Следом маршрута назовем последовательность меток вершин и дуг, составляющих этот маршрут.

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

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

2 На рис. 1 они показаны в пунктирных рамках.

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

Отметим, что компоненты используются лишь, после того, как в них раскрыты все вспомогательные понятия с помощью макроподстановок.

Фактически используется линейное представление «раскрытых» диаграмм в виде массива записей из двух полей: тип записи и информационное поле, соответствующее этому типу.

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

Рис. 1. Представление управляющей граф-схемы, построенной по грамматике САЬС, до раскрытия вспомогательных понятий

Машинное (линейное) представление графа есть последовательность занумерованных записей. Такая запись состоит из двух полей, одно из которых определяет её тип, а другое -информационное.

Записи типа «begin» и «end» представляют начальную и конечную вершину соответственно. Их информационные поля содержат определяемый данной компонентой нетерминальный символ.

Записи типа T и N представляют терминальные и нетерминальные вершины, а их информационные поля содержат символы соответствующих словарей.

Типы записей FR, BR, FS и BS — представляют соответственно резольверы и семантики прямого и обратного просмотров.

Записи типа «разветвление» (-<) и «переход» в которых информационные поля представлены номерами других записей, определяют возможный порядок обхода компонент управляющей граф-схемы.

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

Для рассматриваемого примера калькулятора линейное представление граф-схемы име-

ет вид:

0 begin PROGRAM 36 T ' d'

1 FS Reset 37 } DIGIT

2 N EXPRESSION 38 FS AppDig

3 FS Complete 39 -< 34

4 T 'EOF' 40 } INTEGER NUMBER

5 end PROGRAM 41 FS SetFrPart

6 begin EXPRESSION 42 } FRACTIONAL PART

7 -< 16 43 FS AppFrPart

8 { MONADIC OPERATION 44 -< 65

9 FS PushMonOp 45 { EXPONENT PART

10 -< 13 46 T ' E'

11 T ' + ' 47 FS SetSign

12 ^ 14 48 -< 52

13 T ' — ' 49 -< 51

14 } MONADIC OPERATION 50 T ' +'

15 ^ 7 51 ^ 53

16 { OPERAND 52 T ' — '

17 -< 68 53 { INTEGER NUMBER

18 { NUMBER 54 FS InitInt

19 { INTEGER NUMBER 55 FS SetDig

20 FS InitInt 56 { DIGIT

21 FS SetDig 57 T ' d'

22 { DIGIT 58 } DIGIT

23 T 'd' 59 FS AppDig

24 } DIGIT 60 -< 55

25 FS AppDig 61 } INTEGER NUMBER

26 -< 21 62 FS SetExp

27 } INTEGER NUMBER 63 } EXPONENT PART

28 FS SetIntPart 64 FS AppExpPart

29 -< 44 65 } NUMBER

30 { FRACTIONAL PART 66 FS PushOpd

31 T ! ! 67 ^ 73

32 { INTEGER NUMBER 68 FS PushOpenPar

33 FS InitInt 69 T ' ('

34 FS SetDig 70 N EXPRESSION

35 { DIGIT 71 FS UnloadDiscardOpenPar

72 T ') ' 81 T I _ I

73 } OPERAND 82 87

74 -< 89 83 -< 86

75 { DIADIC OPERATION 84 T ' *'

76 FS PushDyadicOp 85 ^ 87

77 -< 80 86 T '/'

78 T ' + ' 87 } DIADIC OPERATION

79 87 88 ^ 7

80 -< 83 89 end EXPRESSION

4. ЧЕЛНОЧНЫЙ сплаиновыи процессор

Челночным сплайновым процессором назовем формальную систему ps = (pcf, pcb, E), состоящую из управляющего сплайнового процессора прямого просмотра pcf, управляющего сплайнового процессора обратного просмотра pcb и операционной среды E, компилируемой по её описанию e.

4.1. Прямой просмотр. Управляющим сплайновым процессором прямого просмотра назовем формальную систему pcf = (Qf, Ef, Гf, Af, Й, 5f, qf0, Ff ), в которой Qf - множество состояний управления прямого просмотра; Ef - входной алфавит прямого просмотра; rf - алфавит магазинных символов прямого просмотра; Af - алфавит семантических символов прямого просмотра; Й - алфавит резольверных символов прямого просмотра; 5f = (8fj, 5f2, 5f3) - управляющая таблица прямого просмотра, состоящая из таблицы ре-зольверов прямого просмотра: 5f1: Qf х (Ef u {в}) ^ 2й , таблицы управляющих элементов прямого просмотра: 5f2: Qf х (Ef u {в}) х (Qf u {Sup}) х rf*x Af*, и таблицы возвратных состояний: 5f3: Qf x rf x *Kf* ^ Qf; qf0 - начальное состояние прямого просмотра; Ff с Qf - множество конечных состояний прямого просмотра.

4.2. Обратный просмотр. Управляющим сплайновым процессором обратного просмотра назовем формальную систему pcb = (Qb, Eb, Гь, Ab, йь, 5b, qb0, Fb ), в которой Q b - множество состояний управления обратного просмотра; Eb - входной алфавит обратного просмотра; Гь - алфавит магазинных символов обратного просмотра; Ab - алфавит семантических символов обратного просмотра; йь - алфавит резольверных символов обратного просмотра; 5b = (8bp 5b2) - управляющая таблица обратного просмотра, в которой 5b1:

b*

Qb x (Eb u {в}) ^ 2й - таблицарезольверов обратного просмотра, а 5b2: Qb х (Eb u {в}) х йь*^ (Qb u {Pop}) х (Гь u {в}) х Ab* - таблица управляющих элементов обратного просмотра; qb0 - начальное состояние обратного просмотра; Fb с Qb - множество конечных состояний обратного просмотра.

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

4.3. Операционная среда. Понятие операционной среды, включающей интерпретацию контекстных (то есть резольверных и семантических резольверных) символов, определённое для трансляционных грамматик, используется в сплайновых процессорах с учётом того, что й = Й u йь, йь йь = 0, A = Af u Ab, Af n Ab = 01, и что контекстные символы из Й и

1 В трансляционных грамматиках для обозначения семантических символов вместо символа А используется символ Е, причём предполагается, что Е = Е1, и Еь и Е1, п Еь = 0.

Д1 интерпретируются на прямом просмотре, а резольверы и семантики из и Еь - на обратном.

5. ФУНКЦИОНИРОВАНИЕ ЧЕЛНОЧНОГО СПЛАЙНОВОГО ПРОЦЕССОРА

Работу челночного сплайнового процессора опишем в терминах его конфигураций.

5.1. Прямой просмотр действует с начальной конфигурации x, в, е^), где gí0 е Qf -

начальное состояние его конечного управления; х е Ef* - входная цепочка; в означает, что

f

первоначально магазин пуст; е10 - начальное состояние операционной среды.

Пусть (д^, ах, а, е^) - текущая конфигурация прямого просмотра, в которой д^ е Qf -текущее состояние его управления; ах е Е1* - необработанная часть входной цепочки, где а е Е1 - текущий входной символ, х е Е1* - остаток входной цепочки; а е Г1* - текущая магазинная цепочка, причём считается, что на вершине магазина находится крайний левый символ цепочки а; е^ - текущее состояние операционной среды. Очередное движение определяется управляющей таблицей прямого 51.

Случай 1. а) Ф 0 - существуют контексты приёма входного символа а.

Случай 1.1. У(р е а)): (-^(е^)).

- Диагностируется контекстная ошибка по входному символу а.

Случай 1.2. 3(р, р' е 5*(д*, а)): ((р Ф р') & (р Ф в) & (р' Ф в) & гр(е*) & 1р'(е*)).

- Диагностируется контекстная неоднозначность по входному символу а. Случай 1.3. (5^(д^, а) ={р}) & (р е & ^(е^) - приём а.

Пусть а, р) = (д{2, у, с), где д^ е Qf - переходное состояние, у е Г1* - магазинная

цепочка, с е Д1* - семантическая цепочка. Тогда

(д^, ах, Ха, eíl) \—- х, уХа, е^).

9>*

После этого новая конфигурация анализируется сначала.

Случай 2. 511(д11, а) = 0 - не существуют контексты приёма а. Случай 2.1. 511(д11, в) Ф 0 - существуют контексты приёма в. Случай 2.2.1. У(р е 511(д11, в)) : (~1р(е11)).

- Диагностируется контекстная ошибка по в-движениям.

Случай 2.2.2. 3(р, р' е 5^, в)) : ((р Ф р') & (р Ф в) & (р' Ф в) & 1р(е*) & 1р'(е*)).

- Диагностируется контекстная неоднозначность выбора в-движения. Случай 2.2.3. (5*(д*, в)={р}) & (р е & гр(е*).

Движение процессора однозначно определяется управляющим элементом 512 (д11,в, р). Пусть 512(д11, в, р) = (Sup1, у, с), где у е Г1*, с е Д1*. Процессор выполняет переход вида

ах, Ха, eíl) У^ ах, уХа, е*2). Здесь е*2 =

Пусть уХа = Zр, где Z е Г1, р е Г1*.Тогда фактически (д11, ах, уХа, е^) = (д11, ах, Zр, е12). Если при этом 513(д11, Z, р) = gí2, то процессор совершает ещё один шаг перехода вида

(д\, ах, 2$, ег2) (д?2, ах, р, ег2).

Новое состояние д[2 называется возвратным, а исходное - подавляемым. Далее анализ новой конфигурации начинается сначала при том же текущем входном символе.

1 Для g-движения вместо переходного состояния всегда даётся специальное значение Sup (Suppress), означающее, что следующее (возвратное) состояние надо определять по таблице 5f3.

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

(</0, х, в, е\) {pf, е, s, ef), где pf е Ff.

Достигнутое состояние операционной среды ef является начальным для обратного просмотра. Подразумевается, что вся последовательность состояний управления прямого просмотра регистрируется на его выходе и передаётся на вход обратного просмотра.

5.2. Обратный просмотр, сканируя в обратном порядке последовательность состояний управления прямого просмотра, продолжает изменение состояний операционной среды, начиная со своей начальной конфигурации, которая имеет вид

(qb0, qf0, в, ef).

Пусть (qb1, qfk, qfk1 ... qf0, a, eb1) - текущая конфигурация обратного просмотра. Очередное движение обратного просмотра определяется его управляющей таблицей 5b в зависимости от ситуации.

Случай 1. 5b1(qb1, qfk) = 0 - существуют контексты приёма qfk.

Случай 1.1. v (р е 5f1(qb1, qfk)): (-^V) .

- Диагностируется контекстная ошибка по состоянию прямого просмотра qfk.

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

Случай 1.2. 3(р, р' е 5b1(qb1, qfk)): ((р Ф р') & (р Ф в) & (р' Ф в) & i^) & i/e^)).

- Диагностируется контекстная неоднозначность по состоянию прямого просмотра qfk.

Случай 1.3. (5b1(qb1, qfk) = {р}) & (р е йь*) & we^).

к

Пусть 5ь2(дь15 qfk, р) = ^ь2, у, ст), где qь2 е 0ь - переходное состояние, у е (Гь и {е}) -магазинная цепочка1, ст е Аь* — семантическая цепочка. В терминах конфигураций имеем

■ ■ ■ а, е\) Ь ( Чь2, ■ ■ ■ Щ, еь2).

3><

После этого новая конфигурация анализируется сначала.

Случай 2. 5b1(qb1, qfk) = 0 - не существуют контексты приёма qfk. Случай 2.1. 5b1(qb1, в) Ф 0 - существуют контексты приёма в. Случай 2.2.1. v (р е 5b1(qb1, в)): (-г^)).

- Диагностируется контекстная ошибка по в.

Случай 2.2.2. 3(р, р')е 5b1(qb1, в): ((р Ф р') & (р Ф в) & (р' Ф в) & гр^) & i/e^)).

- Диагностируется контекстная неоднозначность выбора в-движения. Случай 2.2.3. (5b1(qb1, в) = {р}) & (р е йь*) & г^).

Пусть 5b2(qb1, в, р) = (Pop2, у, с), где у е (Гь u {в}), с е Ab*. В этом случае выполняется переход вида

(4bi, 1 • • • а, е\) ь (qhv cfkcfk_J ... ya, еь2), где eb2 = i^).

3>*

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

^ qfkqfk-l - qfo, Уa, еЬ2> = (qьl, qfkqfk-l - qfo, Ж ^

Далее процессор совершает ещё один шаг перехода, а именно:

1 Односимвольная или пустая.

2 Для в-движения вместо переходного состояния всегда даётся специальное значение Pop. Следующее (возвратное) состояние следует брать с вершины магазина.

(<Л> - е\) Ь (ЧЪ2> - <?0> Р' ^ Где ЯЪ2 =Х-

Это последнее движение затрачивает верхний символ магазина, но текущий входной

2

символ всё ещё остаётся не принятым. Новое состояние дь2 называется возвратным, а ис-

ходное дь1 - подавляемым.

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

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

(дь0,/... в, е1) (р\ в, в, еъ).

Здесь ръ е Fъ - конечное состояние обратного просмотра, прочитана вся последовательность состояний прямого просмотра и магазин пуст.

Итак, трансляцией, реализуемой челночным сплайновым процессором, которую мы также будем называть челночной трансляцией, называется множество пар: т(^)={(х, Ин) | е5 (р^ е5 ^

(рь, в, е,еь),рь е

ЗАКЛЮЧЕНИЕ

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

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

Известно [7], что структура любого предложения КС-языка может быть представлена в виде дерева вывода, отображающего его на правила грамматики. В описываемом методе используется другая постановка задачи синтаксического анализа: по данному предложению КС-языка выделить из леса деревьев, порождающих язык, то дерево, результат которого равен этому предложению.

Внутренней задачей транслятора является реконструкция управляющей цепочки по предложению входного языка и её интерпретация. Эта реконструкция равносильна нахождению в управляющей граф-схеме маршрутов, порождающих данное предложение входного языка. Эти маршруты начинаются в начальной вершине заглавной компоненты, заканчиваются в конечной её вершине и проходят через некоторые другие компоненты управляющей граф-схемы. Заход в другие компоненты (или повторное прохождение той же самой компоненты) связано с прохождением нетерминальных вершин. Дуги, составляющие порождающий маршрут, несут на себе контекстные условия, при выполнении которых только и возможен проход по ним, а также задают преобразования текущего состояния операционной среды, выполняемые при их проходе.

Эта задача нахождения порождающего маршрута решается в два просмотра, один из которых - прямой - сканирует входную цепочку в прямом направлении, а другой - обратный - сканирует последовательность состояний конечного управления прямого просмотра

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

Построение и оптимизация челночного сплайнового процессора, описанного в разд. 4, производится по управляющей грамматике, представленной в виде граф-схемы с ограничениями, гарантирующими его детерминизм. Эти ограничения формулируются в терминах граф-схемы и учитываются во время его построения [6].

Класс языков, определяемых RBNF-граф-схемами через порождающие маршруты, есть LL(1) и, следовательно, имеет линейную оценку сложности по времени относительно длины входного предложения [7].

Технология реализована в виде пакета инструментальных программ, названного технологическим комплексом (ТК) SYNTAX [6]. Он достаточно полно инструментирует все основные этапы разработки средств синтаксически управляемой обработки данных (СУОД), таких как анализаторы языков программирования, интерпретаторы и компиляторы, конверторы, синтаксические редакторы и т. д.

SYNTAX-технология была успешно использована при реализации ряда языков программирования, таких как Алгол 68, Ада, Паскаль, при написании конвертора Reduce 2 ^ Mathematica, а также при реализации самого языка спецификации трансляций TSL - входного языка TK SYNTAX.

В течение ряда лет TK SYNTAX использовался в спецсеминаре по технологии трансляции на математико-механическом факультете СПбГУ.

Литература

1. Wirth N. The Programming Language Pascal. Acta Informática, 1971. Vol. 1. Р. 35-63.

2. ЯновЮ.И. О логических схемах алгоритмов // Проблемы кибернетики, 1958. Вып. 1. С. 75-127.

3. Цейтин Г.С. Программирование посредством ассоциативных сетей. В: ЭВМ в проектировании и производстве. Вып. 2 / Под ред. Г.В. Орловский. Л.: «Машиностроение», 1985, С. 16-48.

4. Пересмотренное сообщение об Алголе 68 / Под ред. А. Ван Вейнгаарден, Б. Майу, Дж. Пек, К. Костер, М. Синцов, Ч. Линдси, Л. Меертенс, Р. Фискер. М.: «Мир», 1979.

5. Алгол 68. Методы реализации / Под ред. Г.С. Цейтина. Л.: Изд-во Ленингр. ун-та, 1976.

6. МартыненкоБ.К. Синтаксически управляемая обработка данных. СПб.: Изд-во СПбГУ, 2004.

7. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции. Т. 1. Синтаксический анализ; Т. 2. Компиляция. М.: Мир, 1978.

Приложение

УПРАВЛЯЮЩАЯ ТАБЛИЦА КАЛЬКУЛЯТОРА Табл. 1. 5f2

Вход Семантика Магазин Состояние

1 2 3 4

State 1 = {0}

d Reset; InitInt; SetDig 1 2

+ Reset;PushMonOp 1 3

- Reset;PushMonOp 1 4

( Reset;PushOpenPar 1 5

1 Если граф-схема не однокомпонентная.

Вход Семантика Магазин Состояние

1 2 3 4

State 2= {23}

е AppDig; SetlntPart; PushOpd Sup

d AppDig;SetDig 2

AppDig;SetIntPart 6

E AppDig;SetIntPart 7

+ AppDig; SetIntPart; PushOpd; PushDyadicOp 8

- AppDig; SetIntPart; PushOpd; PushDyadicOp 9

* AppDig; SetIntPart; PushOpd; PushDyadicOp 10

/ AppDig; SetIntPart; PushOpd; PushDyadicOp 11

State 3 = {11}; 4={13}; 8 = {78}; 9 = {81}; 10 = {84}; 11 = {86}

d InitInt;SetDig 2

+ PushMonOp 3

- PushMonOp 4

( PushOpenPar 5

State 5 = {69}

d InitInt;SetDig 2 2

+ PushMonOp 2 3

- PushMonOp 2 4

( PushOpenPar 2 5

State 6= {31}

d InitInt;SetDig 12

State 7 = {46}

d SetSign;InitInt;SetDig 13

+ SetSign 14

- SetSign 15

State 12 = {36}

е AppDig;SetFrPart;AppFrPart;PushOpd Sup

d AppDig;SetDig 12

E AppDig;SetFrPart;AppFrPart 7

+ AppDig;SetFrPart;AppFrPart;PushOpd;PushDyadicOp 8

- AppDig;SetFrPart;AppFrPart;PushOpd;PushDyadicOp 9

* AppDig;SetFrPart;AppFrPart;PushOpd;PushDyadicOp 10

/ AppDig;SetFrPart;AppFrPart;PushOpd;PushDyadicOp 11

State 13 = {57}

е AppDig;SetExp;AppExpPart;PushOpd Sup

d AppDig;SetDig 13

+ AppDig;SetExp;AppExpPart;PushOpd;PushDyadicOp 8

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

- AppDig;SetExp;AppExpPart;PushOpd;PushDyadicOp 9

* AppDig;SetExp;AppExpPart;PushOpd;PushDyadicOp 10

/ AppDig;SetExp;AppExpPart;PushOpd;PushDyadicOp 11

State 14 = {50}; 15= {52}

d InitInt;SetDig 13

1 2 3 4

State 16 = {2}

EOF Complete 18

State 17 = {70}

) UnloadAndDiscardOpenPar 19

Вход Семантика Магазин Состояние

1 2 3 4

State 18 = {4} (final)

e Stop

State 19 = {72}

e Sup

+ PushDyadicOp 8

- PushDyadycOp 9

* PushDyadycOp 10

/ PushDyadycOp 11

Табл. 2. 5f3. Подавляемые состояния: 2, 12, 13, 19

Магазинный Возвратное

символ состояние

1 16

2 17

Некоторые пояснения

1. Подтаблица 5^ оказывается не у дел, так как резольверные символы не используются в трансляционной грамматике калькулятора.

2. Подобные строки таблицы 5^, соответствующей состояниям 3, 4, 8, 9, 10, 11, представляются одной копией, также так же как и состояниям 14 и 15.

3. Комментарии, подобные (2), касаются также таблицы 5^ по подавленным состояниям 2, 12, 13, 19.

4. Процессор обратного прохода не используется.

Рассмотрим пример вычисления арифметического выражения 2 * (3 * (1 + 4)) + 5 (см. табл. 3). Процессор-калькулятор воспроизводит модифицированный алгоритм Дейкстры, совмещающий преобразования выражений в обратную польскую форму с одновременным их вычислением. Арифметические операции над значениями, находящимися на вершине магазина операндов, выполняются процессором в момент, когда оригинальный алгоритм пересылает их из магазина операций на выход. Результат образуется в магазине операндов (на шаге 17). После его печати магазин операндов опустошается. Вычисление заканчивается в состоянии 18, которое является конечным. При благополучном завершении вычислений магазин процессора также оказывается пустым.

Протокол работы процессора-калькулятора (см. табл. 3) состоит из двух частей, одна из которых, озаглавленная «Управляющий процессор», показывает его работу, а другая, под заголовком «Операционная среда» описывает её состояние в соответствующие моменты времени. Эти моменты (шаги) пронумерованы в первой графе протокола. Графа «Сост.» показывает текущее состояние управления процессора. В графе «Вход» представлены текущие входные символы, составляющие интерпретируемое арифметическое выражение. Пустая клетка в этой графе означает, что в соответствующий момент повторно анализируется входной символ, который не был принят на предыдущем шаге процессирования1 (см., например, шаги 11, 13 и 17). В графе «Магазин» показано текущее состояние магазина управляющего процессора. Его вершина на каждом шаге процессирования определяется положением последней записи (для удобства читателя графа «Магазин» оцифрована). В графе «Семантики» указывается, какие семантики исполняются в соответствующий момент обработки.

1 Это соответствует в-движениям, использующим символы с вершины магазина.

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

Табл. 3

УПРАВЛЯЮЩИЙ ПРОЦЕССОР ОПЕРАЦИОННАЯ СРЕДА

н о ч о Магазин Семантики Операнд Операция w ад 1 % 'ад Number

У О га 1 2 3 1 2 3 4 1 2 3 4 5 15 ад Q Q

1 1 2 1 Reset;InitInt; SetDig 0 0 2

2 2 * 1 AppDig;SetIntPart; PushOpd; PushDyadicOp 2 * 2 1 2 2

3 1 0 ( 1 PushOpenPar 2 * ( 2 1 2 2

4 5 3 1 2 InitInt;SetDig 2 * ( 0 0 3

5 2 * 1 2 AppDig;SetIntPart; PushOpd; PushDyadicOp 2 3 * ( * 3 1 3 3

6 10 ( 1 2 PushOpenPar 2 3 * ( * ( 3 1 3 3

7 5 1 1 2 2 InitInt;SetDig 2 3 * ( * ( 0 0 1

8 2 + 1 2 2 AppDig;SetIntPart; PushOpd; PushDyadicOp 2 3 1 * ( * ( + 1 1 1 1

9 8 4 1 2 2 InitInt;SetDig 2 3 1 * ( * ( + 0 0 4

10 2 ) 1 2 2 AppDig;SetIntPart; PushOpd 2 3 1 4 * ( * ( + 4 1 4 4

11 17 1 2 UnloadAndDiscard 2 3 5 * ( * 4 1 4 4

12 19 ) 1 2 2 3 5 * ( * 4 1 4 4

13 17 1 UnloadAndDiscard 2 15 * 4 1 4 4

14 19 + 1 PushDyadicOp 30 + 4 1 4 4

15 8 5 1 InitInt;SetDig 30 + 0 0 5

16 2 EOF AppDig;SetIntPart; PushOpd 30 5 + 5 1 5 5

17 16 Complete 35

18 18 Stop

WIRTH SYNTACTIC CHARTS AND GRAPH-SCHEMES IN THE SYNTAX-TECHNOLOGY

Abstract

The purpose of the article is a methodological one. An application of modified the Wirth's syntactic charts is described in connection with the implementation of the programming language Algol 68 in the early 1970s.

Keywords: grammars, Wirth syntactic flowcharts, graph-schemes, regular splines, translations.

Мартыненко Борис Константинович, доктор физико-математических наук, профессор кафедры информатики математико-механического факультета СПбГУ,

mbk@ctinet.ru

© Наши авторы, 2014. Our authors, 2014.

i Надоели баннеры? Вы всегда можете отключить рекламу.