这个回答:Very basic dcg prolog syntax帮助了我一点点,但[X]只获得了下一个角色,我想要整个辣酱玉米饼馅,请继续阅读!
我正在使用GNU Prolog编写一个命令选项解析器,我被困在DCG点上。我有这个语法规则,例如,查找“foo --as = json”,我只是无法弄清楚如何得到“任何”的结果,代码:
as_opt --> "--as=", anything, { c( as_opt )}, !.
anything --> [], {c(anything_match)}.
gprolog的扩展是:
as_opt([45, 45, 97, 115, 61|A], B) :-
anything(A, C),
c(as_opt), !,
C = B.
anything(A, B) :-
c(anything_match), !,
A = B.
“c()”谓词很简单,只是用于跟踪使用format()执行到stdout的规则,这样我就能看到它运行时发生了什么。如果我手工编写代码,我会这样做:
%% for completeness here!
c(Msg) :- format("Processed ~w~n", [Msg]).
as_opt([45, 45, 97, 115, 61|A], B) :-
anything(A, C),
c(as_opt), !,
C = B,
{ g_assign( gvValue, B )}. %% just for example
回到原来的DCG:
as_opt --> "--as=", anything, { c( as_opt ), gassign( gvValue, ??? )}, !.
那么“???”在哪里是。它有可能......一定是。我将重新阅读关于它如何再次扩展DCG规则的gprolog规则,以防我即将(facepalm)自己,但与此同时,任何协助都会受到欢迎。
谢谢, 肖恩。
答案 0 :(得分:3)
您要求的是最简单的DCG非终端之一,它描述了任何列表:
list --> [].
list --> [_], list.
要实际访问正在描述的列表,请引入一个参数:
list([]) --> [].
list([L|Ls) --> [L], list(Ls)
你可以像这样使用它:
as_opt(Option) --> "--as=", list(Option).
答案 1 :(得分:3)
有一个更好的解决方案,比mat描述的解决方案更快,避免虚假的选择点,但它需要支持call//1
内置的非终端,例如在SWI-Prolog,GNU Prolog和其他Prolog编译器。也在Logtalk上。考虑:
as_opt(Option) --> "--as=", list(Option).
list([L|Ls]) --> [L], list(Ls).
list([]) --> [].
as_opt2(Option) --> "--as=", call(rest(Option)).
rest(Rest, Rest, _).
使用SWI-Prolog更好地说明差异:
?- phrase(as_opt(Option), "--as=json").
Option = [106, 115, 111, 110] ;
false.
?- phrase(as_opt2(Option), "--as=json").
Option = [106, 115, 111, 110].
?- time(phrase(as_opt(Option), "--as=json")).
% 9 inferences, 0.000 CPU in 0.000 seconds (57% CPU, 562500 Lips)
Option = [106, 115, 111, 110] ;
% 2 inferences, 0.000 CPU in 0.000 seconds (63% CPU, 133333 Lips)
false.
?- time(phrase(as_opt2(Option), "--as=json")).
% 6 inferences, 0.000 CPU in 0.000 seconds (51% CPU, 285714 Lips)
Option = [106, 115, 111, 110].
虚假选择点来自list//1
非终端的定义。性能差异在于,虽然call//1
允许我们简单地访问隐式列表参数,但list//1
非终端正在按该隐式参数的元素执行列表复制元素。因此,list//1
版本性能在--as=
前缀后面的字符是线性的,而call//1
性能是常量,与前缀后面的字符数无关:
?- time(phrase(as_opt(Option), "--as=jsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjson")).
% 54 inferences, 0.000 CPU in 0.000 seconds (83% CPU, 2700000 Lips)
Option = [106, 115, 111, 110, 106, 115, 111, 110, 106|...] ;
% 4 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 137931 Lips)
false.
?- time(phrase(as_opt2(Option), "--as=jsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjsonjson")).
% 6 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 333333 Lips)
Option = [106, 115, 111, 110, 106, 115, 111, 110, 106|...].
答案 2 :(得分:1)
我认为你不应该使用全局变量。相反,将参数添加到DCG子句,以获取值:
anything([C|Cs]) --> [C], anything(Cs).
anything([]) --> [].
否则,余数可用作短语/ 3的最后一个参数,在规则成功后,“消耗”标题匹配。