next_inactive up previous


YaYacc: Руководство программиста
DocumentId:GradSof-yayacc-r-PG-22.03.2001-1

$Id: ProgrammingGuide_rus.tex,v 1.4 2001/05/05 19:35:27 rssh Exp $

Введение

YaYacc - сокращение для Yet Another Yacc.

Программа создана как синтаксический анализатор, совместимый по алгоритму разбора и воспринимаемому языку с оригинальным уасс [1] (хороший учебник - [2] ), но генерирующий код на C++ а не на C, как оригинальный yacc.

Общее описание работы с yayacc

  1. Подготовка описания грамматики.
  2. Генерация кода
  3. Использование кода: В генерируемом файле находится код метода класса Parser<MyGrammarTag> parse.

Таким образом, общая ситуация может быть выражена следующей схемой:

\begin{displaymath}
\begin{array}{c c c c c}\\
\fbox{ MyGrammarTag.h, MyGramma...
...\
\fbox{ MyGrammar.y }& & & & \fbox{y.tab.cpp}\\
\end{array}\end{displaymath}

Подробное рассмотрение

Теперь перейдем к более подробному рассмотрению процесса работы yayacc. Итак, вначале - параметры граммматик.

Параметры свойств грамматик: на что они влияют

subsectionYYType

Тип терминалов грамматики. Семантика у него такая-же, ка и YYTYPE в стандартном yacc: т. е. MyGrammarTag::YYType используется в том месте, где традиционно стоял YYTYPE; YYType должен обладать следующими свойствами:

Если в вашем понимании терминальный символ это более сложная структура, для которой использование глубокого копирования неэффективно (например, узел синтаксического дерева), то в качестве YYType лучше использовать указатели на эту структуру. В таком случае, не забудьте вставить цикл удаления элементов в ваш код восстановления от ошибок.

subsubsectionПредложение %union

Если вы используете %union клаузу в файле Grammar.y, то соответствующее определение типа генерируется автоматически, как конкатенация строк MyGrammarTag и YYType. Так, например, если вы запускаете yyac с опцией -n Calculator, и в вашем Calculator.y файле есть определиние union

%union {
  int i;
  char ch;
};
то в результате работы в y.tab.h и в y.h.cpp появятся следующие строки:
typedef union {
    int i;
    char ch;  
}  CalculatorYYTag;

В Calculator.h вы можете либо продублировать это определение, либо включить y.tab.h и нписать что-то вроде:

struct Calculator
{
 typedef CalculatorYYType YYType;
 ...
};

subsectionYYInfoType

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

Более подробно: Классу Parser во время создания передается ссылка на объект типа YYInfoType. Вы можете пользоваться ей, для передачи дополнительной информации из/в синтаксичесуого анализатора

subsectionmaxStackSize

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

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

subsectioninitStackSize

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

subsectionПример: описание тега грамматики

struct MyGrammarTag
{
 typedef int YYType;
 typedef bool YYInfoType;
 static  const int maxTableSize;
 static  const int initTableSize;
}

Интерфейс с лексическим анализатором

Лексический анализатор передается1 объекту YYParser при его создании. Шаблон для лексического анализатора описан в интерфейсном файле GradSoft/YaYacc.h и имеет вид:

template<class YYTag>
class YYLexer
{
public:
  int      readToken();
  typename YYTag::YYType  getLastValue();

  YYLexer() {};
  virtual ~YYLexer() {};

private:

  YYLexer(const YYLexer&);
  YYLexer& operator=(const YYLexer&);

};

Вы должны специализировать этот шаблон и /или/ наследовать свой лексический анализатор от него.

Важными там являются две функции:

Пример лексического анализатора находится в файлах CalculatorLexer.h (соответственно CalculatorLexer.cpp) в поддиректории demo/calculator дистрибутива YaYacc

Интерфейс с основной программой

Пример: простой калькулятор

Находится в директории demo/calculator/ в дистрибутиве yayacc.

Опции командной строки

Распространение YaYacc runtime в ваших пакетах

Просто перенесите содержимое подкаталога interfaces в какой-то подкаталог вашего проекта и укажите его как еще один источник включаемых файлов в опциях C++ компилятора.

Если ваш проект инсталлирует включаемые файлы, которые каким-то образом используют yayacc интерфейсы, то при инсталляции создайте в <prefix>/include 2 поддиректорию GradSoft и инсталлируйте туда файл YaYacc.h

Перечень изменений

  1. 07.05.2001 - добавлено описание метода getErrorMessage.
  2. 26.04.2001 - опубликована первая редакция.
  3. 22.03.2001 - создан.

Bibliography

1
Stephen C. Johnson.
yacc - Yet Another Compiler Compiler.
bell-labs, 1978.
aviable online at http://cm.bell-labs.com/7thEdMan/vol2/yacc.bun.

2
John R. Levine Tony Mason and Doug Brown.
Lex & Yacc.
O'Reilly and Associates, 1992.
ISBN 1-56592-000-7.



Footnotes

... передается1
по ссылке
... <prefix>/include2
здесь prefix - место инсталляции Вашего пакета

next_inactive up previous
GradSoft