Операционная система UNIX. Руководство программиста


Действия - часть 2


A : B { $$ = 1; } C { x = $2; y = $3; } ;

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

$ACT : /* пусто */ { $$ = 1; } ;

A : B $ACT C { x = $2; y = $3; } ;

где $ACT - пустая цепочка.

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

node (L, n1, n2)

создает узел с меткой L и потомками n1 и n2 и возвращает указатель на него. Тогда дерево разбора можно построить при помощи действий вида

expr : expr '+' expr { $$ = node ('+', $1, $3); } ;

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

%{ int variable = 0; %}

переменная variable будет доступна всем действиям. Пользователям следует избегать имен, начинающихся с yy, поскольку yacc-процедура разбора использует только такие имена. В примерах, рассмотренных до сих пор, все значения были целочисленными. Работа со значениями других типов обсуждается в разделе БОЛЕЕ СЛОЖНЫЕ ВОПРОСЫ.




Начало  Назад  Вперед