2

我需要通过 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).

并且 "-->" 给出了操作符 ":-" 的错误?!!

这是我的 阿拉伯语解析器代码

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

4

2 回答 2

1

首先,您可能希望将 S 和 A 小写;Prolog 对变量名使用首字母大写。

允许 'b' 出现一次或根本不出现的一种方法是编写如下内容:

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

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

如果您愿意,也可以将 b_optional 的两个规则编写为单个规则的语法;请参阅您最喜欢的 Prolog 文本中有关定子句语法的章节。

我不知道你所说的 c 发生 0、1、2、... 次是什么意思,所以我认为我无法帮助你。

于 2012-12-15T20:58:10.913 回答
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 重写您的语法。

于 2012-12-15T22:05:18.513 回答