我想使用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
等案例不匹配。如何改进语法/解析器实现以解决这个问题?
答案 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)] }
我删除了与空序列匹配的最后一个选项,因为它与您的要求相矛盾,即a
,b
,c
或d
中至少有一个存在。如果你准备接受空,你可以使用
main:
option(a) option(b) option(c) option(d) { [$1; $2; $3; $4] }
虽然您可能希望在所有四个选项均为无的情况下调整操作以返回[]。
答案 1 :(得分:1)
您可以写a?
而不是option(a)
。
此外,如果要返回四个元素,则应使用元组而不是列表。