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

标签 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 专家

最佳答案

根据您的描述

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 或多个(由 分隔)值。

请注意,此类解释器在处理任何大量输入时都会非常慢。我建议您使用 DCG 重写语法。

关于prolog - 如何在SWI-Prolog中编写可选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13895668/

相关文章:

if-statement - Prolog如何以这种方式使用if/else?

prolog - 在 Prolog 中定义谓词的最佳方法

prolog - SML 有何用途?

list - 回文(作业)

nlp - 对于对自然语言处理感兴趣的人来说,什么是好的起点?

prolog - 处理 SWI-Prolog 中的未知程序错误

Prolog家谱,表亲问题

prolog - DCG 加倍计数

list - Prolog:搜索长度>=3的子列表

prolog - Prolog DCG语法规则中的堆栈溢出:如何有效或延迟地处理大型列表