1

私は現在、カンマ区切りのリストをいくつかのオプションの異なるルールと一致させることを目的とした bison の削減を行っています。

arg_list
    :
    | expr_list
    | assignment_list
    | expr_list ',' assignment_list
    | varargs
    | expr_list ',' varargs
    | assignment_list ',' varargs
    | expr_list ',' assignment_list ',' varargs
    | varkwdargs
    | expr_list ',' varkwdargs
    | assignment_list ',' varkwdargs
    | expr_list ',' assignment_list ',' varkwdargs
    | varargs ',' varkwdargs
    | expr_list ',' varargs ',' varkwdargs
    | assignment_list ',' varargs ',' varkwdargs
    | expr_list ',' assignment_list ',' varargs ',' varkwdargs
    ;

不明な場合は、これを (疑似コードで) 実装することを意図しています。

arg_list
    :
    | expr_list [',' assignment_list] [',' varargs] [',' varkwdargs]
    | assignment_list [',' varargs] [',' varkwdargs]
    | varargs [',' varkwdargs]
    | varkwdargs
    ;

これを行う方法は、たとえば次のように実装することです。

optional_assignment_list:
    :
    | ',' assignment_list
    ;

ただし、後者の定式化は LALR(1) ではありません。Bison がカンマを検出する各ステップで、たとえばシフトして *assignment_list* を探すか、空の *optional_assignment_list* を減らして先に進むかを決定する必要があるためです。 *optional_varargs* を探します。

これを表現するより良い方法があるかどうかを見つけようとしています。*optional_varkwdargs* を導入することで選択肢の数を減らすことができましたが、それでもなお 9 つの選択肢が残ります。これは 16 よりも優れていると思います。

optional_varkwdargs
    :
    | ',' varkwdargs
    ;

arg_list
    :
    | expr_list optional_varkwdargs
    | assignment_list optional_varkwdargs
    | expr_list ',' assignment_list optional_varkwdargs
    | varargs optional_varkwdargs
    | expr_list ',' varargs optional_varkwdargs
    | assignment_list ',' varargs optional_varkwdargs
    | expr_list ',' assignment_list ',' varargs optional_varkwdargs
    | varkwdargs
    ;

どんなアイデアでも大歓迎です。

4

1 に答える 1

3

1 つの可能性は、任意の順序でこれらのいずれかのリストを許可する、より一般的な arglist パーサーを使用することです。

arg_list: arg_item 
          { $$ = CreateSingletonArgList($1); }
        | arg_list ',' arg_item
          { if (CheckArgListOrdering($1, $3))
                $$ = AppendArgList($1, $3);
            else
                $$ = $1; }
        ;

arg_item: expr
        | assignment
        | vararg
        | varkwarg
        ;

次に、arg_list に対して解析後のチェックを行い、順序が間違っていないことを確認します。これには、一般的な「構文エラー」ではなく、これらのケース (「kwarg は vararg の後にある必要があります」など) に対してより適切なエラーメッセージを表示できるという利点があります。

編集

ルール内の上記のアクションにより、CheckArgListOrdering 関数は、arg_item が既存の arg_list 内のすべての後に移動できることを確認し、そうでない場合は適切なエラー メッセージを発行します。戻り値は、新しい arg_item を受け入れるか破棄するかをパーサーに伝えます。Create/Append 関数は、arg_lists を任意の種類の順序付けられたコレクション データ構造 (リンクされたリスト、配列、またはその他の適切なものである可能性があります) として管理するだけです。

于 2012-09-26T16:24:16.787 に答える