Алгоритмы построения состояний анализатора для КСР-языка

УДК 681.51

doi: 10.18101/2304-5728-2016-4-23-33

О Я. Н. Федорченко Алгоритмы построения состояний анализатора для КСР-языка

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

Ключевые слова: КСР-грамматики, обобщённое регулярное выражение.

О L. N. Fedorchenko Algorithms for constructing parser states for CFR language

We consider algorithms for constructing parser's states determined with the special translational context-free grammar in regular form.

Keywords: CFR-grammars, generalized regular expression.

Введение

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

Опыт использования различных инструментальных систем [1-4] автоматизирующих построение трансляторов показывает, что его удобно задавать в виде КС-грамматики в регулярной форме (КСР-грамматики) [35], которая отличается от обычной КС-грамматики тем, что в ней помимо алфавитов нетерминалов и терминалов имеются дополнительные алфавиты контекстных символов (семантик) и предикатов, а правые части правил представляют собой обобщённые регулярные выражения над символами объединённого алфавита грамматики.

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

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

В работе даётся определение состояния магазинного автомата и рассматривается алгоритм построения множества состояний анализатора для КСР-языка и его реализация.

Напомним основные определения.

1. Основные определения

Пусть дан алфавит символов V = {а1,а2,...ап} . V* - множество всех слов в алфавите V .

Определение 1. Регулярным множеством слов (регулярным языком) над алфавитом V называют следующие множества:

1. е = {е} - (пустое слово);

2. 0 - (пустое множество слов);

3. {аг } - элементарные множества слов над алфавитом V для любого

4. Множества Р ^ (2,Р(),Р* , где Р и () - регулярные множества в ал-

фавите V.

Добавим к традиционному набору операций операцию бинарной обобщённой итерации (#) над множествами слов в алфавите V . Она может быть определена через традиционную (унарную) операцию Клини как

Р#Я = Р^Р)*

Определение 2. Обобщённым регулярным выражением множества А называется слово г(А) над расширенным алфавитом Ж, где Ж = V и {#,*,+,;, С), е, 0 }, причем:

1. Если ,4 = 0, то г(А}=0;

2. Если А = е , то г(А) = е ;

3. Если А = {а} , где А е V, то г(А) = а ;

4. Если г(Р) = р и ¡"{О) - регулярные выражения для множеств Р и (2 тогда:

г (А) = (р; с/) для множества (РиО); г{А) (р.с/) для множества {РО); г{А)={р*^ для множества Р* ; /'(/!) = ([) ) для множества

РЛ

для множества (Р# О) . Ничто другое не является обобщённым регулярным выражением.

Для представления этого множества цепочек используется понятие синтаксической граф-схемы (СГС), являющейся графовым аналогом правил КСР-грамматики [3], а вывод в грамматике заменяется более простой структурой - маршрутом (или путём) в СГС.

Определение 3. Под синтаксической граф-схемой понимают набор конечных ориентированных графов с помеченными вершинами и дугами. Каждый граф соответствует одному правилу КСР-грамматики и называется графом для нетерминала, определяющего КСР-правило.

Две вершины графа Г^ для нетерминала А являются входными и выходными с метками ЕЛ и /<',.. Внутренние вершины помечены терминальными и нетерминальными символами - операндами регулярного выражения правой части правила, определяющего нетерминал А, а дуги помечены контекстными символами (семантиками) - именами семантических процедур, которые должны исполняться по ходу синтаксического анали-

Покажем графические представления основных операций над элементарными регулярными выражениями

Рис. 1 Графическое представление основных операций над регулярными выражениями

Так задаются базисные элементы, к которым рекурсивно сводятся более сложные случаи.

Рис.2. Граф для нетерминала statement 25

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

Пример 1. Пусть КСР-грамматика 0\ = {{Н,А,В,0\, {а,Ь},Р, 5): Р - конечное множество правил вида ЯД

В: А, д.

А: а.

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

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

0. <5

1. А

2.

3. ¿7

4. В

5. Ь

6. конец Б

7. начало В

8. А 9- Я

10.конец В

11. начало А

12. а

13. конец А

14. начало 0

15. а

16. <19

17. 0

18. конец 0

По линейной записи граф-схемы строятся состояния автомата - анализатора языка.

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

следовательно, какие цепочки (подслова) допустимы к моменту перехода в это состояние. Отсюда, состояние позволяет установить принадлежность слова языку, порождаемому данной компонентой граф-схемы. Определение 4. Состоянием в СГС Гс называется:

1. Либо выходная вершина /', графа /', для некоторого нетерминала

1 1

Д из алфавита N;

2. Либо терминальная вершина в Г0 ;

3. Либо пара множеств (.V,, Л\ ). где .V, и Л\ - состояния в Г а ;

4. Либо объединение состояний в Г0 . Пример 2. Рассмотрим грамматику (¡2:

где Р= {

На рисунке 3 представлена СГС для грамматики О 2.

Пронумеруем терминальные и нетерминальные вершины в возрастающем порядке. Нумерация происходит не по всем натуральным числам. Почему так, будет объяснено позже (см. описание алгоритма).

Множество состоятш в граф-схеме грамматики (¡2, построенное по

определению 4 следующее:

=0

-Ч)

З'у = {а - 3 ,а -15} ^ = {{а - 6, а -11},({а - 20},£ -17)}

= Ша - 3,а -15}^ - 8), а -\2\{Ехв -21,В-17)} БТ = {{({а - 6,а -11} ({а - 20}, В -17). .V - 8), Ех5 -19} {<7 -18}}

Т4

Состояние SП дает нам представление возможных передвижений на 7-ом шаге. В фигурных скобках находятся элементарные состояния перехода, а в круглых скобках находятся переходное состояние и состояние возврата. Если мы будем знать п состояний, то проверка принадлежности цепочки данной КСР-грамматики будет осуществляться за линейное время О(п).

2. Постановка задачи

Целью данной работы является построение множества состояний КСР-грамматики для последующей проверки входных цепочек символов на принадлежность их языку. Предложенная КСР-грамматика не должна иметь левой рекурсии, так как в этом случае алгоритм не закончит работу (зациклится). Леворекурсивная грамматика может быть приведена в КСР-грамматику без левой рекурсии посредством эквивалентного преобразования [3].

3. Описание алгоритма

Алгоритм построения КСР-анализатора состоит из трех основных этапов:

Этап 1. Преобразование граф-схемы в представление, приближенное к машинному (в виде одномерного массива). Этап 2. Построение стека состояний.

Этап 3. Построение последовательности состояний анализатора.

Преобразование граф-схемы в представление, приближенное к машинному

Низкоуровневое представление граф-схемы строится по предложенной КСР-грамматике. В определении б были описаны условные обозначения для построения данного массива.

Машинное представление строится следующим образом: каждое из КСР-правил анализируется путем последовательного прохождения терминальных и нетерминальных вершин. Вход по нетерминалу, а также разветвления путей заносятся в очередь. Когда анализ КСР-правила дошел до конца правила, из очереди достается первая запись. Аналогичным образом анализируется она, и все последующие записи в очереди.

Для примера из рисунка 3 граф-схема в линейной записи будет вида:

Таблица 1.

_Граф-схема в линейной записи_

Адрес 0 1 2 3 4 5 6 7 8 9

0 < 15 'а' < 11 'а' А 1

1 12 'а' 'а' 1 19 'а' А 20 'а' Ех8

2 'а' Ехв

Построение стека состояний

Когда граф-схема представлена в удобном для анализа виде, по ней формируется стек состояний. На рисунке 3 показан стек состояний, построенный по граф-схеме из таблицы 1.

Стек состояний формируется снизу-вверх. В примере начальный элемент по адресу 200 (дно стека). Каждая секция имеет следующую структуру: длина секции (количество ячеек), хеш-функция (например, произведение значений всех элементов секции). Далее сами элементы (термина-

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

Первый блок стартовый, состояние . Следующее состоя ни с 8гр

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

Адрес 3Hdie Hiie

133 3

134 -168

13 S 158

13 в 2

137 hash

138 13

139 5

140 hash

141 -165

142 189

143 -149

144 178

145 3

146 hash

147 149

148 178

149 4

150 hash

151 22

152 195

153 158

154 3

155 hash

156 195

157 158

158 2

159 hash

160 19

ГГгП 3

162 hash

163 195

164 165

165 2

166 hash

167 12

Адрес Значение

168 3

169 hash

170 -172

171 189

172 2

173 hash

174 21

ГВД 5

176 hash

177 -192

178 189

179 11

ISO 6

181 3

192 hash

183 11

184 6

185 3

186 hash

187 -192

188 189

189 2

190 hash

191 18

192 2

193 hash

194 20

[fcE 3

196 hash

197 15

198 3

m 1

200 1

Рис.3. Стек состояний, построенный по граф-схеме из таблицы 1

Следующие два блока иллюстрируют вхождение по нетерминалу на символ в ячейке 20, а также ячейку возврата 18. Следующий блок объединяет их, говоря о том, по какому адресу находится возвратное состояние, а по какому переходное. По адресу 175 находится состояние .

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

Чтобы составить 7-ое состояние алгоритм использует предыдущее состояние и рекурентно сканирует каждый блок, наращивая 7-ое состояние.

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

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

4. Алгоритм построения анализатора

НАЧАЛО: top:=0;

State: = initialstate; NEXT symbol: symbol: =insymbol; SAME symbol: finals: =0;

if state ф final state then level: =state; PROCESS stack: nonterminals: =nonterminal(level);

ifnononterminals=level

then stack [top+: =1]: =nonterminals;

level: = first (level); goto PROCESS stack else fin: = end (level); if fin ф 0 then finals: =fin;

flop: =top

end if end else;

partial state: = terminal(level)/symbol; if partial state Ф 0 then outset (partial state)', state: =successors(partial state);

goto NEXT symbol

end if;

nonterminals: =nonterminal (level);

if nonterminals Ф 0

then stack[top+:=l]:=nonterminals;

level: =first(nonterminals); goto PROCESS stack

end if;

if finals Ф 0 then outset (finals);

state: =stack[top: =ftop]/mask(finals);

outset (state);

top:=top-l;

state: =successors(state);

goto SAME symbol else ERROR end if;

end if;

outset (state);

5. Описание модулей и классов

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

лизации алгоритмов является студент 3-го курса СПбГУ Слёзкин Никита Евгеньевич.

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

enuiri type { CHAR, ADDRESS, EXIT, OPERATIONS };

struct ControlTableType {

typ'e el em typ'e; char symbC'1; int int value;

}

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

class E'.uildCC'ntrolTable {

private :

int quantity C'f rules; string ksr gr[];

ControlTableType Controllable[]; public:

E'.uildCoritrC'lTable ( string [ ] reg, int quant rules);

ControlTableType GetValue(int inde:: of table);

CcritrolTableTyp'e StartRule ( int number 'C'f rule);

C'C'ntrC'lTab'leTyp'e FinishRule ( int number C'f rule);

Typ'e GetTyp'e (int inde:: of table);

}

Класс BuildStateStack отвечает за построение стека состояний распознавателя. В конечном итоге после работы конструктора данного класса на выход получается массив stack[], алгоритмически построенный по вы-шенаписанным правилам (см. Описание алгоритма). С помощью специальных методов класса, можно провести двустороннюю связь между состоянием граф-схемы и индексом элемента в стеке. В дальнейшем, используя имеющиеся данные, мы должны научиться проверять принадлежность цепочек символов.

class E'UildStateStaclr {

P'rivate :

int StatesAddress[]; int stack[];

BuildControlTable b_c_t a ble;

P'Ub'lic :

BuildStsteStack(BuildControlTable BCTable); int GetStateE'ylnde:: ( int inde::);

int GetInde::E''yState ( int state); j_

Классы StringPath и CheckingStrings работают в паре. StringPath

хранит полученный путь в ходе передвижения по состояниям. Так как таких путей может быть больше чем один, paths является массивом. С помощью конструктора CheckingString добавляется полученный ранее стек состояний, а с помошью метода Checking добавляется цепочка символов, которую как раз и надо проверить на принадлежность грамматике. Эти две функции разделены на две части специально для того, чтобы при желании проверить несколько строк не нужно было пересобирать стек состояний каждый раз. Стек состояний привязывается один раз вначале создания объекта.

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

class StringPath {

private:

int path[];

P'Ublic :

StringPath() ;

void WritePathWithDeep(); _}_

class CheckingStrings {

private:

E'.uildStsteStack b s stack; int number of p'aths; int state now; StringPath paths[]; public:

CheckingStrings (BuildStsteStack BSStack) ; int Ne::tState ( ) ;

int Checking(string string value);

1_I_

Заключение

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

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

1. Проверка входных грамматик на синтаксическую правильность;

2. Возможность задавать рекурсивные грамматики и выполнять преобразования;

3. Возможность использовать семантики и предикаты. Представленная разработка намного эффективнее в плане времени в

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

Литература

1. G. Rozenberg A. Salomaa (Eds.) Handbook of Formal Languages. Vol. 2. Berlin, Heidelberg, New York. Springer-Verlag, 1997. 527 p.

2. Bison - GNU parser generator. — URL: http://www.gnu.org/ software/bison/.

3. Федорченко Л. H. Регуляризация контекстно-свободных грамматик / LAP LAMBERT Academic Publishing GmbH & Co. KG Dudweiler Landstr. 99, 66123 Saarbrucken, Germany. 2011. С. 180.

4. Федорченко Л. Н. Синтаксически управляемая обработка данных для практических задач // Вестник БГУ. — 2013. — № 9. — С. 87 - 99.

5. Ludmila Fedorchenko and Sergey Baranov Equivalent Transformations and Regularization in Context-Free Grammars // Bulgarian Academy of Sciences / Cybernetics and Information Technologies (CIT). Vol. 14. No 4. Pp.11 -28. Sofia 2015.

References

1. G. Rozenberg A. Salomaa (Eds.) Handbook of Formal Languages. Vol. 2. Berlin, Heidelberg, New York. Springer-Verlag, 1997. 527 p.

2. Bison - GNU parser generator. — URL: http://www.gnu.org/ software/bison/.

3. Fedorchenko L. N. Reguljarizacija kontekstno-svobodnyh grammatik / LAP LAMBERT Academic Publishing GmbH & Co. KG Dudweiler Landstr. 99, 66123 Saarbrucken, Germany. 2011. C. 180.

4. Fedorchenko L. N. Cintaksicheski upravljaemaja obrabotka dannyh dlja prakticheskih zadach // Vestnik BGU. — 2013. — № 9. — S. 87 - 99.

5. Ludmila Fedorchenko and Sergey Baranov Equivalent Transformations and Regularization in Context-Free Grammars // Bulgarian Academy of Sciences / Cybernetics and Information Technologies (CIT). Vol. 14. No 4. Pp.11 -28. Sofia 2015.

Федорченко Людмила Николаевна, кандидат технических наук, старший научный сотрудник лаборатории прикладной информатики Федерального государственного бюджетного учреждения науки Санкт-Петербургский институт информатики и автоматизации Российской академии наук (СПИИРАН), e-mail: LNF@iias.spb.su

Fedorchenko Ludmila Nikolaevna, Senior Researcher, PhD, St.Petersburg Institute for Informatics and Automation of the Russian Academy of Sciences (SPIIRAS).