一系列带有menhir的可选语法规则

时间:2013-07-06 12:19:04

标签: parsing ocaml menhir

我想使用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 DAA CB D等案例不匹配。如何改进语法/解析器实现以解决这个问题?

2 个答案:

答案 0 :(得分: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)] }

我删除了与空序列匹配的最后一个选项,因为它与您的要求相矛盾,即abcd中至少有一个存在。如果你准备接受空,你可以使用

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

虽然您可能希望在所有四个选项均为无的情况下调整操作以返回[]。

答案 1 :(得分:1)

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