在prolog中从数据库调用事实

在prolog中从数据库调用事实,prolog,dcg,prolog-assert,Prolog,Dcg,Prolog Assert,我已经使用assert…将给定的上下文无关语法插入到数据库中。。。。 如果语法是 S-->a,S,b S-->c 此语法将插入到数据库中。 我必须写一个dcg来为数据库中的cfg生成句子。 例如,如果我以这种方式定义dcg,myDcg'S',str,'S'非终结符应该被aSb或c | d等调用或替换 问题是,每次遇到非终结符生成句子时,如何通过数据库中的事实调用/替换'S' 希望你理解我的问题,如果没有,我会尝试编辑这个问题 下面的示例代码正是我想要做的 这不是dcg myGram

我已经使用assert…将给定的上下文无关语法插入到数据库中。。。。 如果语法是

S-->a,S,b
S-->c
此语法将插入到数据库中。 我必须写一个dcg来为数据库中的cfg生成句子。 例如,如果我以这种方式定义dcg,myDcg'S',str,'S'非终结符应该被aSb或c | d等调用或替换

问题是,每次遇到非终结符生成句子时,如何通过数据库中的事实调用/替换'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). 

无论何时遇到终端,都应将其打印出来,当遇到非终端时,它将回溯。

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

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


有关语法的详细信息,请参阅。

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

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

有关语法的详细信息,请参阅。

在谓词mygrammar/2中,第一个参数中有一个非终结符和终结符列表,第二个参数中有一个终结符列表。如果第二个论点是第一个论点的形式,它可能会成功。这里基本上是一个DCG的元解释器。一些建议:

您的标记器当前生成[grammar'S',[a,'S',b],grammar'S',[…],…]。让它产生[grammar'S',[ta,nt'S',tb],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).
顺便说一句,DCGs比这个解释器更通用

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

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

lowercasecode(C) :-
   between(0'a,0'z,C).
如果您使用的是字符一个字符的原子,那么您将使用char_codeChar,代码在它们之间进行转换

对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).
在谓词mygrammar/2中,第一个参数中有一个非终结符和终结符列表,第二个参数中有一个终结符列表。如果第二个论点是第一个论点的形式,它可能会成功。这里基本上是一个DCG的元解释器。一些建议:

您的标记器当前生成[grammar'S',[a,'S',b],grammar'S',[…],…]。让它产生[grammar'S',[ta,nt'S',tb],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).
顺便说一句,DCGs比这个解释器更通用

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

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

lowercasecode(C) :-
   between(0'a,0'z,C).
如果您使用的是字符一个字符的原子,那么您将使用char_codeChar,代码在它们之间进行转换

对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).

我已经将语法写在一个文本文件中,并将其加载到prolog系统中。我还坚持所有规则。但我的问题是,当我开始为上下文无关语法编写dcg时,每当出现非终结符时,我希望回溯到插入数据库中的语法。因此,我的问题是如何回溯,而我尝试编写的dcg是针对任何在文本文件中编写的给定cfg。有些东西在您的描述中无法工作:如果您将语法加载到Prolog系统中,您根本不需要断言规则。所以在这个层面上存在一些误解。可能会显示文件,以及您调用Prolog的确切命令。初学者经常会犯这样的错误:认为事情必须先断言。但是你只需要用一些命令加载文件…对不起,我想我没有加载文件,但让我告诉你我做了什么。起初我在读课文

包含语法的文件。通过标记语法,我生成了一个类似于[grammar'S',[a,'S',b],grammar'S',[…],…]的列表。现在我尝试断言整个列表。最后,我必须为从文本文件读取的cfg语法编写一个dcg。因此,在编写dcg时,通常我们会在遇到非终端时回溯,当遇到终端时,会将其打印出来。因为我已经声明了这些规则,所以我必须在回溯时使用/调用它们。显然:你在实际任务中做得太多了!你不需要标记语法!只需将其从S->a、S、b更改即可。到s->[a],s[b]。然后读另一个线程,你可以如何生成所有的句子!我已经将语法写在一个文本文件中,并将其加载到prolog系统中。我还坚持所有规则。但我的问题是,当我开始为上下文无关语法编写dcg时,每当出现非终结符时,我希望回溯到插入数据库中的语法。因此,我的问题是如何回溯,而我尝试编写的dcg是针对任何在文本文件中编写的给定cfg。有些东西在您的描述中无法工作:如果您将语法加载到Prolog系统中,您根本不需要断言规则。所以在这个层面上存在一些误解。可能会显示文件,以及您调用Prolog的确切命令。初学者经常会犯这样的错误:认为事情必须先断言。但是你只需要用一些命令加载文件…对不起,我想我没有加载文件,但让我告诉你我做了什么。起初,我正在阅读包含语法的文本文件。通过标记语法,我生成了一个类似于[grammar'S',[a,'S',b],grammar'S',[…],…]的列表。现在我尝试断言整个列表。最后,我必须为从文本文件读取的cfg语法编写一个dcg。因此,在编写dcg时,通常我们会在遇到非终端时回溯,当遇到终端时,会将其打印出来。因为我已经声明了这些规则,所以我必须在回溯时使用/调用它们。显然:你在实际任务中做得太多了!你不需要标记语法!只需将其从S->a、S、b更改即可。到s->[a],s[b]。然后读另一个线程,你可以如何生成所有的句子!那么如何使用这个。在标记化时,我是否应该检查每个术语或字符是大写还是小写?是的。这是根据语法区分终端和非终端的唯一方法。在DCGs中,区别是不同的:像[a]和a这样的列表都是终端,包括空列表[],它是epsilon,其他的都是非终端。大写和小写都很好…但是如果语法像Sa->a,Sa,b怎么检查呢。大写和小写仅适用于右边的字符。通过尝试我展示的示例代码,我遇到了无限循环错误:超出本地堆栈。如何控制这一点。另外,我用我的代码生成了一个无限的列表,而不是列表,我想用这个格式显示所有的句子,句子=ab,句子=aabb`,…等等…那么如何控制循环?@venw.r.t.循环。请参考我的第一个答案。它包含一个指向语法的链接,该语法正是这个问题。那么如何使用它呢。在标记化时,我是否应该检查每个术语或字符是大写还是小写?是的。这是根据语法区分终端和非终端的唯一方法。在DCGs中,区别是不同的:像[a]和a这样的列表都是终端,包括空列表[],它是epsilon,其他的都是非终端。大写和小写都很好…但是如果语法像Sa->a,Sa,b怎么检查呢。大写和小写仅适用于右边的字符。通过尝试我展示的示例代码,我遇到了无限循环错误:超出本地堆栈。如何控制这一点。另外,我用我的代码生成了一个无限的列表,而不是列表,我想用这个格式显示所有的句子,句子=ab,句子=aabb`,…等等…那么如何控制循环?@venw.r.t.循环。请参考我的第一个答案。它包含一个指向与该问题完全相关的语法的链接。