从你的描述
s --> [a], ([b] ; []), c_1.
c_1 --> [c], c_1 ; [].
一些测试模式:
?- phrase(s, [a,b,c,c,c]).
true
?- phrase(s, [a]).
true
编辑
关于您的代码:您应该使用-->
. 为什么要声明--->
(而不是定义)?这样你就应该编写自己的分析器,而不是使用 DCG。
请注意, [vp,conj,vp] 它是一个终端列表,
不确定 feal_amr、mfoal_beh 等,但 vp 它肯定是一个非终端(它被重写)。
那我觉得你应该写
s --> vp.
s --> vp,conj,vp.
s --> vp,conj,np.
vp -->
[feal_amr],
([mfoal_beh];[]),
([mfoal_beh];[]),
([bdl];[]),
[sefa_optional],
([hal];[]),
([shbh_gomla];[]),
([mfoal_motlk];[]).
% I hypotesize it's a comma.
conj --> [','].
如评论中所述进行编辑,您使用的不是DCG,而是您自己的解释器。我用一个最小的例子测试了它
:- op(700,xfx,--->).
s ---> [name,verb,names].
names ---> [name, conj, names].
names ---> [name].
names ---> [].
lex(anne, name).
lex(bob, name).
lex(charlie, name).
lex(call, verb).
lex(and, conj).
parse_topdown(Category,[Word|Reststring],Reststring,[Category,Word]) :-
lex(Word,Category).
parse_topdown(Category,String,Reststring,[Category|Subtrees]) :-
Category ---> RHS,
matches(RHS,String,Reststring,Subtrees).
matches([],String,String,[]).
matches([Category|Categories],String,RestString,[Subtree|Subtrees]) :-
parse_topdown(Category,String,String1,Subtree),
matches(Categories,String1,RestString,Subtrees).
该程序接受 0,1 或更多名称:
?- parse_topdown(s,[anne,call,bob,and,charlie],R,P).
R = [],
P = [s, [name, anne], [verb, call], [names, [name, bob], [conj, and], [names|...]]] ;
R = [charlie],
P = [s, [name, anne], [verb, call], [names, [name, bob], [conj, and], [names]]] ;
R = [and, charlie],
P = [s, [name, anne], [verb, call], [names, [name, bob]]] ;
R = [bob, and, charlie],
P = [s, [name, anne], [verb, call], [names]] ;
false.
注意我让 R 自由,以检查部分匹配。回到最初的问题,您可以看到非终结符如何names
接受 0,1 或许多(由 分隔and
)值。
请注意,这样的解释器在任何实质性输入上都会非常慢。我建议您使用 DCG 重写您的语法。