假设我想编写一个自定义运算符来组合DCG规则,否则将会重复.
例如,假设我有一个DCG,ws
这样:
ws --> [].
ws --> " ", ws.
匹配零个或多个空格.显然,如果我想在我的语法中的每个标记之间有可选的空格,那么必须放在, ws
任何地方都是令人讨厌的.
我可以定义一个新的运算符来替换,/2
.
:- op(1000, xfy, [ -- ]).
:- meta_predicate --(*,*,?,?).
--(L,R) --> ({callable(L)} -> call(L); L), ws, ({callable(R)} -> call(R); R).
这--/2
通过可选的空格规则加入左手和右手.这大多数工作正常,但有些事情绊倒了:
rule --> "foo" -- ("bar"; "quux").
如果我尝试执行此规则,则会收到错误消息,说明;/4
未定义.我对这个问题有一个模糊的概念,但基本上问题是:有没有办法为DCG定义具有相同通用性的新运算符,/2
?
1> mat..:
是的,这是可能的.
目前,主要问题是:
?- callable("foo").
true.
所以,我建议这个更简单的定义:
--(L, R) --> L, ws, R.
另外,我建议:
:- set_prolog_flag(double_quotes, chars).
示例查询:
?- phrase(rule, Ls).
Ls = [f, o, o, b, a, r] ;
Ls = [f, o, o, q, u, u, x] ;
Ls = [f, o, o, ' ', b, a, r] ;
Ls = [f, o, o, ' ', q, u, u, x] ;
Ls = [f, o, o, ' ', ' ', b, a, r] .
作为另一个例子,让我们使用这个规则:
rule --> "foo" -- ("bar" | "quux") -- "test".
现在我们举个例子:
?- length(Ls, _), phrase(rule, Ls).
Ls = [f, o, o, b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', t, e, s, t] ;
Ls = [f, o, o, q, u, u, x, t, e, s, t] ;
Ls = [f, o, o, ' ', b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', ' ', t, e, s, t] ;
Ls = [f, o, o, q, u, u, x, ' ', t, e, s, t] ;
Ls = [f, o, o, ' ', b, a, r, ' ', t, e, s, t] ;
Ls = [f, o, o, ' ', q, u, u, x, t, e, s, t] ;
Ls = [f, o, o, ' ', ' ', b, a, r, t, e, s, t] ;
Ls = [f, o, o, b, a, r, ' ', ' ', ' ', t, e, s, t] .
请注意迭代深化如何用于公平枚举.