自定义 DCG 运算符
Custom DCG Operators
假设我想编写一个自定义运算符来以重复的方式编写 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
相同的通用性?
是的,这是可以的
目前主要问题是:
?- 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] .
注意迭代深化如何用于公平枚举。
假设我想编写一个自定义运算符来以重复的方式编写 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
相同的通用性?
是的,这是可以的
目前主要问题是:
?- 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] .
注意迭代深化如何用于公平枚举。