简体   繁体   English

DCG:为DCG {}代码中的变量分配余数

[英]DCG: Assigning remainder to a variable within DCG {} code

This answer: Very basic dcg prolog syntax helped me a little but [X] only gets the next character, I want the whole enchilada, read on! 这个答案: 非常基本的dcg prolog语法对我有所帮助,但[X]只获得下一个字符,我想要整个辣酱玉米饼馅,请继续阅读!

I am using GNU Prolog to write a command option parser and I am stuck on a DCG point. 我正在使用GNU Prolog编写一个命令选项解析器,我被困在DCG点上。 I have this grammar rule which looks for "foo --as=json" for example, and I just cannot work out how to get my hands on the result of "anything", the code: 我有这个语法规则,例如,查找“foo --as = json”,我只是无法弄清楚如何得到“任何东西”的结果,代码:

as_opt --> "--as=", anything, { c( as_opt )}, !.
anything --> [], {c(anything_match)}.

And the gprolog expansion of that is: 而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.

The "c()" predicate is simple and is just used to track that the rule executed with a format() to stdout so I could see what's going on as it runs. “c()”谓词很简单,只是用于跟踪使用format()到s​​tdout执行的规则,这样我就能看到它运行时发生了什么。 If I had written the code by hand I would do: 如果我手工编写代码,我会这样做:

%% 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

Going back to the original DCG: 回到原来的DCG:

as_opt --> "--as=", anything, { c( as_opt ), gassign( gvValue, ??? )}, !.

So what goes where the "???" 那么什么是“???” is. 是。 Is it possible...it must be. 它有可能......一定是。 I am going to re-read the gprolog rules on how it expands DCG rules again in case I am about to (facepalm) myself but in the meantime any assistance would be most welcome. 我将重新阅读关于它如何再次扩展DCG规则的gprolog规则,以防我自己(facepalm)自己,但与此同时,任何帮助都会受到欢迎。

Thanks, Sean. 谢谢,肖恩。

You are asking for one of the simplest DCG non-terminals, which describes any list: 您要求的是最简单的DCG非终端之一,它描述了任何列表:

list --> [].
list --> [_], list.

To actually access the list that is being described, you introduce an argument: 要实际访问正在描述的列表,请引入一个参数:

list([])    --> [].
list([L|Ls) --> [L], list(Ls)

You can use it like this: 你可以像这样使用它:

as_opt(Option) --> "--as=", list(Option).

There's a better solution than the one described by mat that is faster and avoids spurious choice points but it requires support for the call//1 built-in non-terminal as found on eg SWI-Prolog, GNU Prolog, and other Prolog compilers. 有一个更好的解决方案,比mat描述的更快,避免虚假的选择点,但它需要支持call//1内置的非终端,如在SWI-Prolog,GNU Prolog和其他Prolog编译器上找到的。 Also on Logtalk. 也在Logtalk上。 Consider: 考虑:

as_opt(Option) --> "--as=", list(Option).

list([L|Ls]) --> [L], list(Ls).
list([]) --> [].

as_opt2(Option) --> "--as=", call(rest(Option)).

rest(Rest, Rest, _).

Using SWI-Prolog to better illustrate the differences: 使用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].

The spurious choice-point comes from the definition of the list//1 non-terminal. 虚假选择点来自list//1非终端的定义。 The performance difference is that, while call//1 allows us to simply access the implicit list argument, the list//1 non-terminal is doing a list copy element by element of that implicit argument. 性能差异在于,虽然call//1允许我们简单地访问隐式列表参数,但是list//1非终端正在按该隐式参数的元素执行列表复制元素。 As a consequence, the list//1 version performance is linear on the characters following the --as= prefix while the call//1 performance is constant, independent of the number of characters after the prefix: 因此, 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|...].

I think you should not use global variables. 我认为你不应该使用全局变量。 Instead, add argument(s) to DCG clauses, to get back the values: 相反,将参数添加到DCG子句,以获取值:

anything([C|Cs]) --> [C], anything(Cs).
anything([]) --> [].

otherwise, the remainder is available as last argument of phrase/3, after rules succeded, 'consuming' the heading match. 否则,余数可用作短语/ 3的最后一个参数,在规则成功后,“消耗”标题匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM