如何在Prolog中创建此DCG?

如何在Prolog中创建此DCG?,prolog,regular-language,dcg,Prolog,Regular Language,Dcg,我想创建一个DCG,这样的语言可以被接受: c bbbcbbb bbacbba 阿巴卡巴 阿巴巴巴贝巴 正如你所看到的,这意味着有一个特定的顺序a和b,然后是一个c,然后是和c之前完全相同的顺序。如果不满足这些条件,则应失败 我目前在这里使用我的方法(有效,但也能识别错误的单词) 你们中有人能帮我解决我需要改变的问题吗?我不知道怎么继续下去。非常感谢 DCG实际上只是一个Prolog程序,经过预处理,添加了实现差异列表的隐藏参数。我们总是可以添加自己的参数,并使用模式匹配。然后 s --&g

我想创建一个DCG,这样的语言可以被接受:

  • c
  • bbbcbbb
  • bbacbba
  • 阿巴卡巴
  • 阿巴巴巴贝巴
正如你所看到的,这意味着有一个特定的顺序a和b,然后是一个c,然后是和c之前完全相同的顺序。如果不满足这些条件,则应失败

我目前在这里使用我的方法(有效,但也能识别错误的单词)


你们中有人能帮我解决我需要改变的问题吗?我不知道怎么继续下去。非常感谢

DCG实际上只是一个Prolog程序,经过预处理,添加了实现差异列表的隐藏参数。我们总是可以添加自己的参数,并使用模式匹配。然后

s --> ab(X), [c], ab(X). 
ab([a|T]) --> [a], ab(T).
ab([b|T]) --> [b], ab(T).
ab([]) --> [].

?- atom_chars(aababacaababa,Cs),phrase(s, Cs).
Cs = [a, a, b, a, b, a, c, a, a|...] 

您所描述的语言既不是常规语言,也不是上下文无关语言。因此,您需要求助于DCGs中提供的Prolog扩展。您可能会习惯一些习惯用语:

% any sequence

seq([]) -->
   [].
seq([E|Es]) -->
   [E],
   seq(Es).
使用此非终端,我们可以描述一个由一个字符重复和分隔的序列:

rep(Seq, Sep) --> 
   seq(Seq),
   [Sep],
   seq(Seq).
这显然太笼统了。您只需要
ab
c
。您现在可以添加其他要求:

rep(Seq, Sep) -->
   seq(Seq),
   {phrase(abs,Seq)},
   [Sep],
   seq(Seq).

 abs --> [] | ("a"|"b"), abs.
所以现在:

 s -->
     rep(_,c).
另一种选择是对语法进行“硬编码”,如@capelical所示。使用
seq//1
使方法更加灵活

在字符列表中使用双引号是非常方便的。
查看如何允许使用双引号来表示字符列表。

此设计还可以通过
短语(s,L)很好地生成解决方案。
@mbrach:这是运气而不是意图。查看所有解决方案的标准方法是
?-长度(L,N),短语(s,L)。
。现在,它们也按长度排序。看,左撇子戈麦斯说,“我宁愿幸运也不愿好。”;)但不管怎样,上面的代码按长度顺序生成“a,b”序列,并在继续下一个长度之前完成每个长度的排列集,这是一个很好的意外发现。我仍在学习DCG的许多细微差别,因此这篇文章和@capelical的文章对我都很有启发。@mbrach:这里有两个不同的概念:终止(意思是普遍终止)和公平枚举。如果发生冲突,请始终选择终止。终止于所有固定长度的DCG可以简单地用于枚举所有句子。但事实并非如此。
 s -->
     rep(_,c).