これはあなたが望んでいる答えではありません。必要な例が見当たらない理由は、文法ファイル(.y)に入力規則を適用するのは非現実的だからだと思います。むしろ、開発者は手続き型の.cまたは.cppコードでこれを実現します。一般に、とにかく解析された入力の分析を行う必要があるため、そうするときにセマンティックルールを適用することは副産物です。
余談ですが、質問で再現する文法の断片を考えると、式をどのように解析しているのかよくわかりません。
これが私がそれが非現実的であると主張する理由です。(1)タイプ情報は、文法の非終端記号全体に浸透する必要があります。(2)さらに悪いことに、それは変数名に反映されなければなりません。
識別子、数値定数、および4つの卓上電卓演算子を使用できる単純な代入ステートメントを解析するこのおもちゃの例を考えてみてください。NUMBERトークンは、42のような整数または3.14のような浮動小数点数にすることができます。そして、識別子が1文字のAZであるとしましょう。
%token IDENTIFIER NUMBER
%%
stmt : IDENTIFIER '=' expr
;
expr : expr '+' term
| expr '-' term
| term
;
term : term '*' factor
| term '/' factor
| factor
;
factor : '(' expr ')'
| '-' factor
| NUMBER
| IDENTIFIER
;
それでは、タイピングルールを紹介してみましょう。NUMBERトークンをFLT_NUMBERとINT_NUMBERに分けます。、、および非終端記号も2つexpr
に分割されます。term
factor
%token IDENTIFIER FLT_NUMBER INT_NUMBER
stmt : IDENTIFIER '=' int_expr
| IDENTIFIER '=' flt_expr
;
int_expr : int_expr '+' int_term
| int_expr '-' int_term
| int_term
;
flt_expr : flt_expr '+' flt_term
| flt_expr '-' flt_term
| flt_term
;
int_term : int_term '*' int_factor
| int_term '/' int_factor
| int_factor
;
flt_term : flt_term '*' flt_factor
| flt_term '/' flt_factor
| flt_factor
;
int_factor : '(' int_expr ')'
| '-' int_factor
| INT_NUMBER
| int_identifier
;
flt_factor : '(' flt_expr ')'
| '-' flt_factor
| FLT_NUMBER
| flt_identifier
;
int_identifier : IDENTIFIER ;
flt_identifier : IDENTIFIER ;
私たちの文法はこの時点で立っているので、矛盾があります。パーサーはIDENTIFIERをaint_identifier
または。として認識するかどうかを判断できませんflt_identifier
。A = B
したがって、 asIDENTIFIER = int_expr
またはを減らすかどうかはわかりませんIDENTIFIER = flt_expr
。
(ここで、Rubyについての私の理解は少しソフトです:) Ruby(ほとんどの言語のように)は、識別子の数値タイプを決定するための語彙レベルの方法を提供しません。これを古い学校のBASICと比較してください。ここで、Aは数値を示し、A$は文字列を示します。言い換えれば、たとえば、A#が整数を表し、A @が浮動小数点数を表す言語を発明した場合、これを機能させることができます。
のような限定された混合型の式を許可したい場合int_term '*' flt_factor
、文法はさらに複雑になります。
これらの問題を回避する方法があるかもしれません。yacc/bison以外のテクノロジーで構築されたパーサーを使用すると簡単になる場合があります。少なくとも、私のスケッチはあなたにさらに追求するためのいくつかのアイデアを与えるでしょう。