Prolog 序言:结合DCG语法和其他限制

Prolog 序言:结合DCG语法和其他限制,prolog,grammar,dcg,Prolog,Grammar,Dcg,Prolog的DCG以及我能以多快的速度生成符合特定语法的所有可能结构给我留下了深刻的印象 但我想将此搜索与其他约束结合起来。例如,定义一个复杂的语法,让Prolog生成不超过10个单词的所有句子。或者所有不重复同一单词两次的句子 是否可以向DCG语法添加这样的额外约束?或者我基本上必须将DCG翻译回普通的序言子句并开始修改它们吗?如果您只想看到生成的所有句子,使用以下语句非常方便: ?- length(Xs, N), phrase(mynonterminal, Xs). 当然,这会产生所有的

Prolog的DCG以及我能以多快的速度生成符合特定语法的所有可能结构给我留下了深刻的印象

但我想将此搜索与其他约束结合起来。例如,定义一个复杂的语法,让Prolog生成不超过10个单词的所有句子。或者所有不重复同一单词两次的句子


是否可以向DCG语法添加这样的额外约束?或者我基本上必须将DCG翻译回普通的序言子句并开始修改它们吗?

如果您只想看到生成的所有句子,使用以下语句非常方便:

?- length(Xs, N), phrase(mynonterminal, Xs).
当然,这会产生所有的句子。但是它非常有用,它可以节省您思考具体限制的时间。如果要进一步限制,请在前面添加介于(0,10,N)之间的目标

如果你想在语法中说某个非终结符应该有一定的长度,最好明确地说:

seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).

a --> {length(Es,10)}, seq(Es), {phrase(mynonterminal,Es)}.
如果你仍然不开心,那么你要表达两个非终点的交点。这相当于询问两种上下文无关语言的交叉点,这在一般情况下是不可判定的。但更早的时候,你会遇到终止合同的问题。因此,请注意以下几点:

:- op( 950, xfx, &).

(NT1 & NT2) -->
     call(Xs0^Xs^(phrase(NT1,Xs0,Xs),phrase(NT2,Xs0,Xs))).
仅当您不使用时,才需要以下内容:


所以现在可以表示两个非终点的交点。但请注意,这里的终止非常脆弱。特别是,第一个非终结符的终止并不一定限制第二个非终结符。

好的,您可以始终使用{}并在两者之间编写任何类型的prolog谓词,例如:

foo(X)-->
    { valid(X) },
    [a].
foo(X)-->
    [b].

所以你可以添加一些单词计数器。当然,如果每个标记都是一个单词,那么您可以简单地在编译器中编写类似于:length(L,N)、Nsemantic checker的内容。

我认为前面的部分,处理“seq”,就是我需要的(即一个非终结符是一个有限列表)。但我并没有完全让它发挥作用,也许是因为我不明白。第一个例子中的“短语”是什么?在理解
(&)//2
的定义之前,试着理解在Prolog中如何编码DCG。这方面的一本好书是Pereira和Shieber的Prolog和自然语言分析。(免费)嗨,false,谢谢你的参考书。这将是有用的。关于我的特殊问题,我认为您的解决方案“a-->{length(Es,10)},seq(Es),{phrase(mynonterminal,Es)}.”看起来几乎正是我想要的。我只是不明白,在我的程序中,我应该在你写“短语”的地方写什么。我可以看出这一部分的目的是说序列是由Mynonterminal组成的。但是那个“短语”谓词本身是什么呢?啊。不好。很抱歉我知道这是一个内置关键字。
phrase/2
是谓词调用非终端的干净接口。您也可以直接调用它们,但如果调用谓词或非终结符,则不明显。所以严格地说,这是没有必要的,但更清楚地阅读。
foo(X)-->
    { valid(X) },
    [a].
foo(X)-->
    [b].