1

Menhir パーサーを使用して OCaml で次の文法を実装したいと思います。

4 つの異なるステートメントが次々に来るはずですが、そのうちの 3 つが欠落している可能性があります。したがって、どのプログラムにもこれらのステートメントが少なくとも 1 つ含まれていますが、特定の順序でさらに多くのステートメントを含めることができます。

文法は次のとおりです。

main =  A  (B) (C) (D)
     | (A)  B  (C) (D)
     | (A) (B)  C  (D)
     | (A) (B) (C)  D

より簡潔な表現で表現することはできますか?

parser.mlyこの文法の例を次に示します。

%token <char> ACHAR BCHAR CCHAR DCHAR
%token EOF

%start <char option list> main
%type <char> a b c d
%%

main:
    a option(b) option(c) option(d) { [Some($1); $2; $3; $4] }
|   option(a) b option(c) option(d) { [$1; Some($2); $3; $4] }
|   option(a) option(b) c option(d) { [$1; $2; Some($3); $4] }
|   option(a) option(b) option(c) d { [$1; $2; $3; Some($4)] }
| EOF { [] }

a:
    ACHAR { $1 } (* returns 'A' *)

b:
    BCHAR { $1 } (* returns 'B' *)

c:
    CCHAR { $1 } (* returns 'C' *)

d:
    DCHAR { $1 } (* returns 'D' *)

この場合、menhir は警告を生成します。

Warning: production option(a) -> a is never reduced.
Warning: production option(d) -> d is never reduced.

A B C DAA C、などのケースB Dは一致しません。これを修正するために文法/パーサーの実装を改善するにはどうすればよいですか?

4

2 に答える 2

3

これを試して:

main:
    a option(b) option(c) option(d) { [Some($1); $2; $3; $4] }
|   b option(c) option(d) { [None; Some($1); $2; $3] }
|   c option(d) { [None; None; Some($1); $2] }
|   d { [None; None; None; Some($1)] }

abcまたはの少なくとも 1 つdが存在するという要件と矛盾するため、空のシーケンスに一致する最後のオプションを削除しました。空を受け入れる準備ができている場合は、そのまま使用できます

main:
    option(a) option(b) option(c) option(d) { [$1; $2; $3; $4] }

ただし、4 つのオプションすべてが None の場合に [] を返すようにアクションを調整することもできます。

于 2013-07-06T13:48:07.507 に答える
1

a?の代わりに書くことができますoption(a)。また、4 つの要素を返したい場合は、リストの代わりにタプルを使用する必要があります。

于 2013-07-08T09:17:42.183 に答える