如何在SWI-Prolog中编写可选项

时间:2012-12-15 19:58:19

标签: prolog dcg

我需要通过Prolog实现一些规则

例如:

S ---> A,[b],{c}.

其中:

[b]可能会发生一次或没有像0或1次

{c}可能发生0,1,2,......次

我怎么写呢?

修改

我用过这个:

:- op(700,xfx,--->).
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];[]).

它给了我一个错误“在句子体中完全停止?无法重新定义,/ 2”

在这一行的逗号“vp ---> [feal_amr],...”

修改

我用“--->”因为我有这个

parse_topdown(Category,String,Reststring,[Category|Subtrees]) :-
        Category ---> RHS,
        matches(RHS,String,Reststring,Subtrees).

和“ - >”操作员“: - ”给出错误?!!

这是我的代码 Arabic Parser Code

我很抱歉给您带来不便,但我不是Prolog的专家

2 个答案:

答案 0 :(得分:1)

首先,你可能想要小写的S和A; Prolog使用变量名的初始上限。

允许'b'发生一次或根本不发生的一种方法是写下这样的东西:

s --> a, b_optional, {c}.

b_optional --> [b].
b_optional --> [].

如果您愿意,还有将b_optional的两个规则写为单一规则的语法;请参阅您最喜欢的Prolog文本中有关明确条款语法的章节。

我不知道你所说的0,1,2,......次是什么意思,所以我认为我不能帮助你。

答案 1 :(得分:1)

来自您的描述

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重写你的语法。