この節では、yacc 仕様としての yacc 入力構文について説明します。コンテキスト依存性などについては考慮していません。yacc では LALR(1) 文法を使用することもできますが、yacc 入力仕様言語は、LR(2) 文法として指定されています。この文法では、規則内のアクションの直後に識別子があると、問題が発生します。
この識別子の後にコロンが続いている場合には、次の規則の開始を表しています。コロンが続いていない場合は、現在の規則の続きであり、その規則のなかに偶然アクションが埋め込まれていただけに過ぎません。字句アナライザは、識別子を認識した後にその先を読み取り、次のトークン (空白文字、復帰改行、コメントなどは読み飛ばします) がコロンかどうかを判定します。コロンの場合には、トークン C_IDENTIFIER を返します。
コロンでない場合には、IDENTIFIER を返します。リテラル (引用符で囲んだ文字列) も C_IDENTIFIER としてではなく、必ず IDENTIFIER として返されます。
/* yacc に対する入力の文法 */
/* 基本エントリ */
%token IDENTIFIER /* 識別子とリテラルの取り込み */
%token C_IDENTIFIER /* 識別子 (リテラル以外) */
/* 後に a : が続く */
%token NUMBER /* [0-9]+ */
/* 予約語: %type=>TYPE %left=>LEFT、等 */
%token LEFT RIGHT NONASSOC TOKEN PREC TYPE START UNION
%token MARK /* %% 記号 */
%token LCURL /* %{ 記号 */
%token RCURL /* %) 記号 */
/* 自分自身を表す ASCII 文字リテラル*/
%token spec t
%%
spec : defs MARK rules tail
;
tail : MARK
{
In this action,read in the rest of the file
}
| /* 空: 2 番目の MARK は省略可 */
;
defs : /* 空 */
| defs def
;
def : START IDENTIFIER
| UNION
{
Copy union definition to output
}
| LCURL
{
Copy C code to output file
}
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 : '{'
{
Copy action translate $$ etc.
}
'}'
;
prec : /* 空 */
| PREC IDENTIFIER
| PREC IDENTIFIER act
| prec ';'
;