yacc 文法ファイルの宣言

yacc 文法ファイルの宣言セクションには、次のものが入っています。

  • 文法ファイルの他の部分で使用される任意の変数または定数の宣言
  • このファイルの一部として他のファイルを使用するための #include ステートメント (ライブラリー・ヘッダー・ファイルに使用される)
  • 生成されたパーサーの処理条件を定義するステートメント

共用体のメンバーが文法ファイル内の各種の名前と関連している場合、 ユーザー定義 C 言語の共用体 内の構文解析スタックに現在あるトークンと関連する、意味構造情報を保持することができます。

変数または定数の宣言は、C プログラミング言語の次の構文を使用します。
TypeSpecifier Declarator ;

TypeSpecifier はデータ型キーワードで、 Declarator は変数または定数の名前です。 名前は任意の長さで、英字、ドット、下線、および数字で構成することができます。 名前は数字から始めることはできません。 英大文字と小文字は別です。

終端 (またはトークン) 名は、%token 宣言を使用して宣言でき、非終端名は、%type 宣言を使用して宣言できます。 % type 宣言は非終端名に必須ではありません。 非終端名は、 少なくとも 1 つの規則の左側に現れた場合に、自動的に定義されます。 宣言セクションに名前が宣言されていない場合、 その名前は非終端記号としてのみ使用することができます。 # include ステートメントは、C 言語と構文が同じで、 同じ機能を実行します。

yacc プログラムには、生成されたパーサーの処理条件を定義する、 一組のキーワードがあります。 それぞれのキーワード は、% (パーセント記号) で始まり、 その後にトークンまたは非終端名が続きます。 次のキーワードがあります。

キーワード 説明
%left 他のトークンと左方関連のトークンを示します。

%nonassoc 他のトークンと関連していないトークンを示します。

%right 他のトークンと右方関連のトークンを示します。

%start 開始記号の非終端名を示します。

%token yacc コマンドが受け入れるトークン名を示します。 宣言セクション内のすべてのトークン名を宣言します。

%type 非終端のタイプを示します。 タイプ検査は、この構成が存在するときに行われます。

%union yacc 値スタックを、希望するさまざまな値の型の共用体として識別します。 デフォルトでは、戻される値は整数です。 この構成によって、YYSTYPE の宣言が入力から直接提供されます。

%{
Code
%}
指定した Code をコード・ファイルにコピーします。 この構成を使用すると、C 言語の宣言と定義を定義セクションに追加することができます。
注: %{ (パーセント記号、 左大括弧) と %} (パーセント記号、右大括弧) の記号は、1 行に単独で入力しておかなければなりません。
%token%left%right、 および %nonassoc キーワードは、オプショナルで、<Tag> (リテラルの不等号括弧で囲まれた共用体メンバー名) という C 共用体メンバー名 (%union によって定義される) をサポートします。 %type キーワードには <Tag> が必要です。 <Tag> の使用は、行に指定されているトークンが、<Tag> によって参照される共用体メンバーと同じ C タイプになることを示します。 例えば、次の宣言は、Name パラメーターがトークンであることを宣言します。
%token [<Tag>] Name [Number] [Name [Number]]...

<Tag> が存在する場合、この行のすべてのトークンの C タイプが、<Tag> によって参照されるタイプであることを宣言されます。 正の整数 (Number) が Name パラメーターに続く場合、その値はトークンに割り当てられます。

同一行上のトークンは、すべて同じ優先順位と結合順序を持ちます。 行は、ファイル内で優先順位またはバインディング強度に関して昇順に並んでいます。 例えば、次は、4 つの算術演算子の優先順位と結合順序を説明しています。

%left '+' '-'
%left '*' '/'

+ (正符号) と - (負符号) は結合順序が左方結合ですが、 同様に左方結合である * (アスタリスク) および / (スラッシュ) より優先順位が低くなります。

グローバル変数の定義

字句解析プログラムで使用するのと同様に、 一部またはすべてのアクションでも使用する変数を定義するには、 それらの変数の宣言を %{ (パーセント記号、 左大括弧) 記号と %} (パーセント記号、 右大括弧) 記号の間に囲む必要があります。 これらの記号で囲まれた宣言は、グローバル変数 と呼ばれます。 例えば、var 変数を完全なプログラムのすべての部分で使用できるようにするには、 文法ファイルの宣言セクションに次の項目を使用します。

%{
int var = 0;
%}

開始条件

パーサーは 開始 記号と呼ばれる特殊な記号を認識します。 開始記号は、文法ファイルの規則セクションの中の、 構文解析する言語の最も一般的な構造を記述する規則の名前です。 この構造は最も一般的なものであるため、 パーサーは入力ストリームのトップダウン分析をここから始めます。 %start キーワードを使用して、 宣言セクションに開始記号を宣言します。 開始記号の名前を宣言しないと、 パーサーは文法ファイル内の最初の文法規則の名前を使用します。

例えば、C 言語の関数を構文解析する場合、 パーサーが認識する最も一般的な構造体は、次のとおりです。

main()
{
        code_segment
}

開始記号は、この構造体を記述する規則を指します。 ファイル内の他のすべての規則は、関数内の下位構造体を識別する方法を記述しています。

トークン番号

トークン番号は、トークンの名前を表す負でない整数です。 字句解析プログラムが実際のトークン名でなくトークン番号をパーサーに渡す場合、 両方のプログラムがトークンに割り当てられた番号に同意している必要があります。

yacc 文法ファイルで使用されているトークンに番号を割り当てることができます。 トークンに番号を割り当てない場合、 yacc 文法ファイルは以下の規則を使用して番号を割り当てます。
  • リテラル文字は、ASCII ASCII 文字セット内の文字の数値である。
  • その他の名前には、257 から始まるトークン番号を割り当てる。
    注: トークン番号で 0 を割り当てないでください。 この番号は、終了マーカー・トークンに割り当てられます。 これを再定義することはできません。

文法ファイルの宣言セクションでトークン (リテラルを含む) に番号を割り当てるには、%token 行のトークン名の直後に正の整数 (0 以外) を置きます。 この整数が、その名前またはリテラルのトークン番号です。 各トークン番号は、固有でなければなりません。 yacc コマンドで使用されるすべての字句解析プログラムは、 入力の終わりに達したら、0 または負の値をトークンに戻す必要があります。