次: Rules, 前: Grammar Outline, 上: Grammar File
Bison文法の記号(symbols)は、 言語の文法的分類を表現します。
終端記号(terminal symbol)
(トークン型(tokens types)ともいいます)は、
構文的に等価なトークンのクラスを表します。
そのクラスのトークンが許されることを表すために、
文法規則の中で記号を使えます。
その記号は、Bison構文解析器の中で番号で表現され、
yylex
関数は、どのような種類のトークンが読み込まれたかを示すために、
トークン番号を返します。
これを表す記号を知っていればよく、その番号を知っている必要はありません。
非終端記号(nonterminal symbol)は、 構文的に等価なグループを表現します。 記号名は文法規則の記述に使われます。 通常、非終端記号名を小文字で書きます。
記号名は、英字、先頭以外での数字、下線記号(`_')とピリオドからなります。 ピリオド記号(`.')は、非終端記号の名前には使えますが、 終端記号の名前には使えません。
文法中で終端記号を記述するには3種類の方法があります。
%token
のようなBison宣言とともに定義する必要があります。
See Token Type Names。
'+'
は文字トークン型です。
意味値データ型(see Data Types of Semantic Values)、
結合性、優先順位(see Operator Precedence)を
指定する必要がなければ、
文字トークン型を宣言する必要はありません。
通常、文字トークン型は、特別な文字1から
なるトークンを表すためだけに使います。
たとえば、トークン型'+'
を、
トークンとしての`+'文字を表すために使います。
このようにする義務はありませんが、そうしないと、
あなたが書いたプログラムを読む人が混乱するでしょう。
C言語の文字リテラルで使われる通常のエスケープシーケンス
2を、Bisonでも使えます。
しかし、'\0'
だけはASCII符号の0を表し、
yylex
がファイルの終わりを示す符号なので、
文字リテラルとしては使えません
(see Calling Convention for yylex
)。
"<="
がリテラル文字列トークンです。
意味値(see Value Type)、
結合性、優先順位(see Operator Precedence)を
指定する必要がなければ、
リテラル文字列トークンを宣言する必要はありません。
%token
宣言(see Token Declarations)を使って、
リテラル文字列トークンを、記号名の別名として関連づけられます。
そうしないと、字句解析器は、
yytname
表(see Calling Convention)を使って、
リテラル文字列トークンからトークン番号を検索する必要があります。
【警告】yacc
ではリテラル文字列トークンを使えません。
通常、特殊文字の列からなるトークンの表現にのみ、
リテラル文字列トークンを使います。
たとえば、トークンとしての`<='を表すために、
トークン型"<="
を使うべきです。
そうする義務はありませんが、そうしないと、
あなたが書いたプログラムを読む人が混乱するでしょう。
C言語で使えるエスケープシーケンスはすべてBisonでも使えます。 リテラル文字列トークンは、2文字以上からなります。 もし、トークンが1文字ならば、前述の1文字トークンを使ってください。
終端記号を書く方法は、終端記号の文法的意味に関係なく、 規則の中に現れる位置と、 構文解析器関数が記号を返す方法に関係します。
yylex
が返す値は、終端記号のどれかを表し、
入力の終わりでは0です。
文法規則の中でどの方法でトークン型を書いても、
yylex
を定義する書き方は同じです。
1文字トークン型に対する符号は、その文字のASCII符号なので、
yylex
は必要な符号を生成するために同一の文字定数を使えます。
名前を付けられたトークン型はそれぞれ、
構文解析器ファイルの中でCのマクロになるので、
yylex
は符号に対するマクロ名を使えます。
これが、終端記号の名前にピリオド記号を使えない理由です。
See Calling Convention for yylex
。
yylex
が構文解析器と別のソースファイルの中に書かれる場合には、
そこでトークン型マクロ定義を使えるように準備する必要があります。
`-d'オプションを付けてBisonを実行してください。
すると、マクロ定義がname.tab.hというファイルに書かれ、
必要に応じて別のソースファイルからインクルードできます。
See Invoking Bison。
記号error
は、エラー回復用に予約された終端記号(see Error Recovery)
で、他の目的に使うべきではありません。
実際に、yylex
がこの値を返すことは決してありません。