0

私は現在 Decaf (プログラミング言語) 文法の一部を実装しています。関連するバイソンコードのスニペットは次のとおりです。

type:
  INT
  | ID
  | type LS RS
  ;

local_var_decl:
  type ID SEMICOLON
  ;

name:
  THIS
  | ID
  | name DOT ID
  | name LS expression RS
  ;

それにもかかわらず、名前生成ルールの作業を開始するとすぐに、私のパーサーはreduce-reduce警告を出します。

.outputファイル (bison によって生成)の内容は次のとおりです。

State 84

   23 type: ID .
   61 name: ID .

    ID        reduce using rule 23 (type)
    LS        reduce using rule 23 (type)
    LS        [reduce using rule 61 (name)]
    $default  reduce using rule 61 (name)

したがって、次の入力を与えると、{ abc[1] = abc; }と表示されsyntax error, unexpected NUMBER, expected RSます。NUMBERはルール (基本的には、どのように解析されたに違いないか)から来ていますが、 local_var_declルールを通じて解析しようとします。

この問題を解決するには、何を変更する必要があると思いますか? 約 2 時間費やし、さまざまなことを試しましたが、うまくいきませんでした。

ありがとうございました!!

PS。完全な.yソース コードへのリンクは次のとおりです。

4

1 に答える 1

1

これは、十分な情報が得られる前にパーサーが決定を下すことを余儀なくされている一般的な問題の特定の例です。このような場合、必要な情報はそれほど遠くないため、可能であれば先読みを増やすだけで十分です。(残念ながら、k > 1 の LR(k) パーサーを生成するパーサー ジェネレーターはほとんどなく、bison も例外ではありません。) 通常の解決策は、決定する必要なく単純に解析を続行できるようにすることです。もう 1 つの解決策は、 with bison(ただし C モードのみ) を要求することです%glr-parser。これは、追加の処理時間を犠牲にしてリダクションを解決する必要がある場合について、はるかに柔軟です。

この場合、コンテキストは atypeまたは a のいずれかを許可しname、どちらも で始まり、IDその後に[( LS) を続けることができます。の場合、 のname[に数字が続く必要があります。の場合、 のtype[に が続く必要があります]。したがって、 の後に 2 番目のトークンが表示されれば、IDすぐに判断できます。

しかし、先に見えるトークンは 1 つだけ]です。IDそして、文法は、ある場合にはを aに還元nameし、別の場合には a に還元しなければならないため、即座に決定を下すことができると主張していtypeます。したがって、リデュースとリデュースの競合が発生します。バイソンは、文法ファイルで最初に来るリダクションを常に使用して解決します。

1 つの解決策は、プロダクションを複製することを犠牲にして、この選択を強制しないようにすることです。例えば:

type_other:
  INT
  | ID LS RS
  | type_other LS RS
  ;
type: ID
  | type_other
  ;

name_other:
  THIS
  | ID LS expression RS
  | name_other DOT ID
  | name_other LS expression RS
  ;
name: ID
  | name_other
  ;
于 2017-11-04T04:17:09.100 に答える