1

如果语法类似于

S-->a,S,b
S-->c

这个语法被插入到数据库中。我必须编写一个 dcg 来为数据库中的 cfg 生成句子。例如,如果我以这种方式定义 dcg myDcg('S',str),则'S'(非终端)应该被调用或替换aSbc|d左右。

问题是每次遇到非终端('S')以生成句子时,我如何用数据库中的事实调用/替换'S' 。

希望您理解我的问题,如果没有,我将尝试编辑问题。


下面(示例代码)是我想要做的这不是 dcg。

myGrammar([], []):-!.

myGrammar([T|Rest], [T|Sentence]):-
          myGrammar(Rest, Sentence).

myGrammar([NT|Rest], Sentence):-
          grammar(NT, Rest1),
          append(Rest1,Rest, NewRest),
          myGrammar(NewRest, Sentence). 

每当遇到终端时,它应该被打印出来,当遇到非终端时,它将回溯。

4

2 回答 2

2

我假设您最近开始使用 Prolog。是的,您可以在数据库中断言,但这并不是您最开始做的常见事情。当您对基本语言感到安全时,您将希望稍后使用该功能。

您通常所做的是将语法写入文件myfirstgrammar.pl,然后将该文件加载到您的 Prolog 系统中。

有关语法的详细信息,请参阅此最近的线程。

于 2011-12-01T11:46:38.733 回答
2

在您的谓词mygrammar/2中,第一个参数中有一个非终端和终端列表,第二个参数中有一个终端列表。如果第二个参数是第一个参数的形式,它可能应该成功。因此,您在这里拥有的本质上是 DCG 的元解释器。几点建议:

您的分词器当前生产[grammar('S',[a,'S',b]),grammar('S',[....]),..].让它[grammar('S',[t(a),nt('S'),t(b)]),grammar('S',[....]),..]代替生产。通过这种方式,很明显什么是终端,什么是非终端。而且,哦,删除它!

myGrammar([], []).
myGrammar([t(T)|Rest], [T|Sentence]):-
   myGrammar(Rest, Sentence).
myGrammar([nt(NT)|Rest], Sentence):-
   grammar(NT, Rest1),
   append(Rest1,Rest, NewRest),
   myGrammar(NewRest, Sentence).

DCG,顺便说一句,比这个解释器更通用一点。

非终端和终端之间的实际分类必须由分词器完成。

uppercasecode(C) :-
   between(0'A,0'Z,C).

lowercasecode(C) :-
   between(0'a,0'z,C).

如果您使用的是字符(单字符原子),您将使用char_code(Char, Code)它们在它们之间进行转换。

完整的 Unicode 支持仍处于起步阶段。它非常棘手,因为像Ⓐ这样的字符的所有特殊情况是大写但仍然不能成为标识符的一部分。但这是目前在 SWI 中的操作方法。

uppercasecode(C) :-
   '$code_class'(C,upper),
   '$code_class'(C,id_start).

lowercasecode(C) :-
   '$code_class'(C,id_start),
   '$code_class'(C,id_continue),
   \+ '$code_class'(C,upper).

更新:与此同时,char_type/2为此code_type/2目的。

uppercasecode(C) :-
   code_class(C, upper),
   code_class(C, prolog_var_start).
于 2011-12-01T21:56:02.403 回答