残念ながら、bison は (単一の) 解析を生成することを強く主張しているため、あいまいな解析をマージする方法を指定する必要があります。そうしないと、可能な解析が複数ある場合、bison の GLR パーサーは解析が曖昧であると文句を言うでしょう。
複数の解析のうちどれが受け入れられるかをあまり気にしないのであれば、bison を自分の意志に曲げるのはさほど難しくありません。%dprec
最も簡単な方法は、あいまいな可能性のあるすべてのプロダクションに異なる を割り当てることです。その後、Bison は、たまたま優先順位が最も高い適用可能なプロダクションを選択します。
%merge
単純な関数を使用して、bison に複数の解析について教えてもらうこともできます。バイソンのマニュアルに例があります。(この機能のドキュメントは良くありませんが、ニーズには十分かもしれません。そうでない場合は、お気軽に、より具体的な質問をしてください。)
私は DParser の経験があまりありませんが、マニュアルには、複数の可能な解析に直面したときの動作が似ていることが示されています: デフォルトは文句を言うことですが、独自の簡単なマージ機能を提供できます: 12、あいまいさ)
あいまいさは、優先順位と関連性に基づいて自動的に解決されます。さらに、他の解決手法が失敗した場合、ユーザー定義のあいまいさの解決が可能です。デフォルトのあいまい性ハンドラーは、未解決のあいまいさに対して致命的なエラーを生成します。この動作は、署名が で提供されているユーザー定義のリゾルバーに置き換えることができますdparse.h
。
2 番目の例のバイソン GLR 文法の例を次に示します。私はレクサーを省略しましたが、これは実際には関係ありません (急いでいたので少し恥ずかしいです)。
%{
int yylex();
void yyerror(const char* msg);
%}
%error-verbose
%glr-parser
%token WORD_A "a"
%token WORD_BOY "boy"
%token WORD_GIRL "girl"
%token WORD_IN "in"
%token WORD_LIKED "liked"
%token WORD_PARK "park"
%token WORD_SAW "saw"
%token WORD_TELESCOPE "telescope"
%token WORD_THE "the"
%token WORD_WITH "with"
%%
S : NP VP {puts("S: NP VP");} %dprec 1
| NPA VP {puts("S: NPA VP");} %dprec 2
;
NPA: D N {puts("NPA: D N");} %dprec 3
| NP PP {puts("NPA: NP PP");} %dprec 4
;
NP : D N {puts("NP: D N");} %dprec 6
| NP PP {puts("NP: NP PP");} %dprec 7
| NPA {puts("NP: NPA");} %dprec 10
;
VP : V NP {puts("VP: V NP ");} %dprec 11
| VP PP {puts("VP: VP PP");} %dprec 12
;
PP : P NP {puts("PP: P NP");} %dprec 14
;
D : "the" {puts("D: the");} %dprec 15
| "a" {puts("D: a");} %dprec 16
;
P : "in" {puts("P: in");} %dprec 17
| "with" {puts("P: with");} %dprec 18
;
V : "liked" {puts("V: liked");} %dprec 19
| "saw" {puts("V: saw");} %dprec 20
;
N : "girl" {puts("N: girl");} %dprec 21
| "boy" {puts("N: boy");} %dprec 22
| "park" {puts("N: park");} %dprec 23
| "saw" {puts("N: saw");} %dprec 24
| "telescope"{puts("N: telescope");} %dprec 25
;
%%
int main(int argc, char** argv) {
printf("yyparse returned %d\n", yyparse());
return 0;
}
コンパイル:
$ make ambig2
bison30 -v -d -o ambig2.c ambig2.y
ambig2.y: warning: 6 shift/reduce conflicts [-Wconflicts-sr]
ambig2.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]
gcc-4.8 -ggdb -Wall -D_POSIX_C_SOURCE=200809L -std=c99 -c -o ambig2.o ambig2.c
gcc-4.8 ambig2.o -o ambig2
rm ambig2.o ambig2.c
サンプル解析:
$ ./ambig2 <<<"a boy saw a girl"
D: a
N: boy
NPA: D N
V: saw
D: a
N: girl
NPA: D N
NP: NPA
VP: V NP
S: NPA VP
yyparse returned 0
$ ./ambig2 <<<"a saw saw the saw in a saw"
D: a
N: saw
NPA: D N
V: saw
D: the
N: saw
NPA: D N
NP: NPA
VP: V NP
P: in
D: a
N: saw
NPA: D N
NP: NPA
PP: P NP
VP: VP PP
S: NPA VP
yyparse returned 0