1

我想使用 Menhir 解析器在 OCaml 中实现以下语法。

应该有四个不同的语句一个接一个地出现,但是,其中任何三个都可能丢失。因此,任何程序都至少包含这些语句中的一个,但可以包含更多以特定顺序出现的语句。

这是语法:

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 D, A, A C,B D等情况不匹配。如何改进语法/解析器实现以解决此问题?

4

2 回答 2

3

Try this:

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)] }

I removed the last option, which matches the empty sequence, because it contradicts your requirement that at least one of a, b, c or d be present. If you are prepared to accept empty, you could just use

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

although you might want to adjust the action to return [] in the case where all four options are None.

于 2013-07-06T13:48:07.507 回答
1

你可以写a?而不是option(a). 此外,如果要返回四个元素,则应使用元组而不是列表。

于 2013-07-08T09:17:42.183 回答