在序言中从数据库调用事实 [英] Calling facts from database in prolog
问题描述
我已经使用 assert(....) 将给定的上下文无关语法插入到数据库中如果语法类似于
I've inserted the given context free grammar into the database using assert(....) If the grammar is something like
S-->a,S,b
S-->c
这个语法被插入到数据库中.我必须写一个dcg来为数据库中的cfg生成句子.例如,如果我以这种方式定义 dcgmyDcg('S',str),'S'(非终结符)应该被调用或替换 由 aSb 或 c|d 左右.
This grammar is inserted into the database. I have to write a dcg to generate sentences for the cfg in the database. For example if i define the dcg in this way myDcg('S',str), the 'S'(non terminal) should be called or substituted by aSb or c|d or so.
问题是每次遇到非终结符('S')来生成句子时,我如何通过数据库中的事实调用/替换'S'.
The problem is how can i call/substitute 'S' by facts from the database each time a non terminal('S') is encountered to generate sentences.
希望你理解我的问题,如果没有我会尝试编辑问题.
Hope you understood my question, if not i will try to edit the question.
下面(示例代码)正是我想要做的这不是dcg.
Below(Sample code) is what i wanted to do exactly This is not dcg.
myGrammar([], []):-!.
myGrammar([T|Rest], [T|Sentence]):-
myGrammar(Rest, Sentence).
myGrammar([NT|Rest], Sentence):-
grammar(NT, Rest1),
append(Rest1,Rest, NewRest),
myGrammar(NewRest, Sentence).
遇到终端就打印出来,遇到非终端就回溯.
Whenever a terminal is encountered it should be printed out and when a non terminal is encountered it will backtrack.
推荐答案
在你的谓词 mygrammar/2
中,第一个参数中有一个非终结符和终结符列表,以及第二.如果第二个参数是第一个参数的形式,它可能应该成功.因此,您在这里拥有的本质上是 DCG 的元解释器.一些建议:
In your predicate mygrammar/2
there is a list of non-terminals and terminals in the first argument and a list of terminals in the second. It should probably succeed if the second argument is of the form of the first. So what you have here essentially is a meta interpreter for DCGs. A few suggestions:
您的分词器当前生成 [grammar('S',[a,'S',b]),grammar('S',[....]),..].
让它产生 [grammar('S',[t(a),nt('S'),t(b)]),grammar('S',[....]),..]
代替.通过这种方式,很明显什么是终端,什么是非终端.而且,哦,删除那个!
Your tokenizer produces currently [grammar('S',[a,'S',b]),grammar('S',[....]),..].
Let it produce [grammar('S',[t(a),nt('S'),t(b)]),grammar('S',[....]),..]
instead. In this manner it's evident what is a terminal and what is a non-terminal. And, oh, remove that !.
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,顺便说一句,比这个解释器更通用.
DCGs, btw are a bit more general than this interpreter.
非终结符和终结符之间的实际分类必须由分词器完成.
The actual classification between non-terminals and terminals has to be done by the tokenizer.
uppercasecode(C) :-
between(0'A,0'Z,C).
lowercasecode(C) :-
between(0'a,0'z,C).
如果您使用字符(一个字符的原子),您将使用 char_code(Char, Code)
在它们之间进行转换.
If you are using chars (one-character atoms), you will use char_code(Char, Code)
to convert between them.
完整的 Unicode 支持仍处于起步阶段.它非常棘手,因为所有像 Ⓐ 这样的字符的特殊情况都是大写,但仍然不能成为标识符的一部分.但是,您目前可以在 SWI 中执行此操作.
Full Unicode support is still in its infancy. Its very tricky because of all those special cases for characters like Ⓐ which is upper case but still cannot be part of an identifier. But here is how you can do it in SWI currently.
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
用于此目的.
Update: In the meantime, there is char_type/2
and code_type/2
for this purpose.
uppercasecode(C) :-
code_class(C, upper),
code_class(C, prolog_var_start).
这篇关于在序言中从数据库调用事实的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!