【问题标题】:Calling facts from database in prolog在 prolog 中从数据库中调用事实
【发布时间】:2011-12-01 03:20:03
【问题描述】:

我已经使用 assert(....) 将给定的上下文无关语法插入到数据库中 如果语法类似于

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

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

【问题讨论】:

    标签: prolog dcg prolog-assert


    【解决方案1】:

    在您的谓词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/2code_type/2 用于此目的。

    uppercasecode(C) :-
       code_class(C, upper),
       code_class(C, prolog_var_start).
    

    【讨论】:

    • 那么如何使用它。在标记化时,我应该检查每个术语或字符是大写还是小写?
    • 确实如此。这是在给定语法的情况下区分终端和非终端的唯一方法。 ((在 DCG 中,区分方式不同:[a] 之类的列表以及“a”都是终端,包括空列表 [],它是 epsilon,其他所有内容都是非终端)。
    • 大写和小写都可以正常工作...但是如果语法类似于Sa-->a,Sa,b 如何检查。大写和小写仅适用于正确的字符。
    • 通过尝试我展示的示例代码,我正在运行无限循环(错误:超出本地堆栈)。这个怎么控制。另外,使用我的代码,我正在生成一个无限的列表,而不是列表,我想以这种格式显示所有句子Sentence=ab, Sentence=aabb`, ...等等...所以如何控制循环?
    • @ven w.r.t.循环。请参考我的第一个答案。它包含指向具有该问题的语法的链接。
    【解决方案2】:

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

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

    语法详情请参考this recent thread

    【讨论】:

    • 我已经在一个文本文件中编写了语法并将其加载到我的序言系统中。我还断言了所有规则。但是我的问题是,当我开始为上下文无关语法编写 dcg 时,我想在发生非终端时引用(回溯)插入数据库中的语法。所以我的问题是如何回溯,而我正在尝试编写的 dcg 是针对文本文件中写入的任何给定 cfg。
    • 有些东西在你的描述中无法工作:如果你将语法加载到你的 Prolog 系统中,你根本不需要断言规则。所以在那个层面上存在一些误解。也许显示文件,以及您如何调用 Prolog 的确切命令。 ((相信必须先声明事物是一个非常常见的初学者错误。但您只需使用一些命令加载文件......)
    • 对不起,我想我没有加载文件,但让我告诉你我做了什么。最初我正在阅读包含语法的文本文件。通过标记语法,我生成了一个类似[grammar('S',[a,'S',b]),grammar('S',[....]),..] 的列表。现在我尝试断言整个列表。最后,我必须为从文本文件中读取的 cfg 语法编写一个 dcg。
    • 所以在编写 dcg 时,通常我们会在遇到非终端时回溯,并且在遇到终端时将其打印出来。由于我已经断言了规则,我必须在回溯时使用/调用它们
    • 很明显:你在实际任务中做的太多了!您不需要标记语法!只需将其从 S-->a,S,b. 更改为 s --> [a],s,[b].,然后阅读其他线程如何生成所有句子!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    相关资源
    最近更新 更多