我想创建一个像这样的语言被接受的DCG:
正如您所看到的,这意味着a和b的特定顺序,然后是c,然后再次与c之前的顺序完全相同。如果不满足这些条件,它将失败。
我目前正在使用我的方法(有效但也能识别错误的单词)
s --> x, s, x.
s --> [c].
x --> [a].
x --> [b].
你们有人可以帮我解决我需要改变的事吗?我不知道该怎么做。非常感谢。
答案 0 :(得分:6)
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|...]
答案 1 :(得分:5)
您所描述的语言既不是常规语言也不是上下文。因此,您需要求助于DCG中提供的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).
另一种选择是“硬编码”语法,正如@CapelliC所示。使用seq//1
可以使方法更灵活。
使用双引号作为字符列表非常方便。 请参阅this answer如何允许使用双引号来表示字符列表。