あなたの説明から
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 を使用して文法を書き直すことをお勧めします。