ВХОДНОЙ СИНТАКСИС YACC'А
В данном разделе в форме yacc-спецификации описывается входной синтаксис yacc'а. Не рассматриваются контекстные зависимости и аналогичные вопросы. Ирония заключается в том, что, хотя yacc
воспринимает LALR(1)-грамматики, сам входной язык спецификаций yacc'а наиболее естественным образом задается LR(2)-грамматикой: трудным оказывается случай, когда идентификатор идет сразу за действием. Если после идентификатора стоит двоеточие, то это начало следующего правила, в противном случае, это продолжение текущего правила, которое идет за внутренним действием. Реализация такова: лексический анализатор, обнаружив идентификатор, просматривает входной текст вперед и определяет, является ли следующая лексема двоеточием. Если является, лексический анали- затор возвращает C_IDENTIFIER. Если нет, возвращается IDENTIFIER. Литералы (в апострофах) также распознаются как IDENTIFIER, но не как C_IDENTIFIER.
/* грамматика yacc-спецификаций */
/* основные компоненты */ %token IDENTIFIER /* идентификаторы и литералы */ %token C_IDENTIFIER /* идентификатор (но не литерал), */ /* за которым следует двоеточие */ %token NUMBER /* [0-9]+ */
/* зарезервированные слова: %type=>TYPE %left=>LEFT и т.д.*/
%token LEFT RIGHT NONASSOC TOKEN PREC TYPE START UNION
%token MARK /* знак %% */ %token LCURL /* знак %{ */ %token RCURL /* знак %} */
/* ASCII-символы указываются непосредственно */
%%
spec : defs MARK rules tail ;
tail : MARK { В этом действии обрабатывается оставшаяся часть файла } | /* пусто: второй MARK необязателен */ ;
defs : /* пусто */ | defs def ; def : START IDENTIFIER | UNION { Копирование определения объединения в выходной файл } | LCURL { Копирование C-кода в выходной файл } RCURL | rword tag nlist ;
rword : TOKEN | LEFT | RIGHT | NONASSOC | TYPE ;
tag : /* пусто: тег необязателен */ | '<' IDENTIFIER '>' ;
nlist : nmno | nlist nmno | nlist ',' nmno ;
nmno : IDENTIFIER /* Замечание: литерал нельзя использовать с %type */ | IDENTIFIER NUMBER /* Замечание: нельзя использовать с %type */ ;
/* секция правил */
rules : C_IDENTIFIER rbody prec | rules rule ; rule : C_IDENTIFIER rbody prec | '|' rbody prec ;
rbody : /* пусто */ | rbody IDENTIFIER | rbody act ;
act : '{' { Копирование действия, обработка $$ и т.п. } '}' ;
prec : /* пусто */ | PREC IDENTIFIER | PREC IDENTIFIER act | prec ';' ;