我有一个简单的语法,它需要 3 个列表项,并对每个列表项运行不同的 dcg 规则。
[debug] ?- phrase(sentence(X), [sky, a, 1], []).
X = [bright, amber, on] .
法典:
sentence([A,C,R]) -->
analyse(A),
colour(C),
rating(R).
analyse(bright) --> [sky].
analyse(dark) --> [cave].
colour(red) --> [r].
colour(amber) --> [a].
colour(green) --> [g].
rating(on) --> [1].
rating(off) --> [0].
这工作正常。
我的问题是我的输入列表需要有 2 个项目,而不是 3 个,第二个原子是颜色和评级的串联原子:
[sky, a1]
所以不知何故,我必须(?)将这个原子分成[a,1],然后颜色和评级规则将与简单的dcg规则一起使用。
我不知道该怎么做。.显然,对于普通的prolog,我只会使用atom_chars,但我无法弄清楚如何将其与语法交错。
在一个完美的世界里,感觉我不应该求助于使用atom_chars,我应该能够想出一个简单的 dcg 规则来拆分它,但我不确定这是否可能,因为我们解析的是列表,而不是原子。
正如你自己所说,你只需要使用像 atom_chars/2
这样的谓词。您可以将普通代码交错到 DCG 规则中,方法是将其包含在 {
和 }
中。
但是你的问题定义有些可疑。正如你自己也说过的,你正在解析一个列表,而不是一个原子。您正在解析的列表应该已经正确标记化,否则您不能期望定义可以解析它的 DCG。还是我看错了?
换句话说:你接受你的输入,分成单个字符,使用 DCG 对其进行标记。根据您的输入,您可以在同一步骤中执行解析。
很明显,一个精致的DCG规则可以工作,但是,唉,我花了太多时间为您的问题制定解决方案。
在这里:
sentence([A,C,R]) -->
analyse(A),
colour(C),
rating(R).
analyse(bright) --> [sky].
analyse(dark) --> [cave].
colour(red) --> [r].
colour(amber) --> [a].
colour(green) --> [g].
colour(X), As --> [A], {
atom_codes(A, Cs),
maplist(char2atomic, Cs, L),
phrase(colour(X), L, As)}.
rating(on) --> [1].
rating(off) --> [0].
char2atomic(C, A) :- code_type(C, digit) -> number_codes(A, [C]) ; atom_codes(A, [C]).
收益 率
?- phrase(sentence(X), [sky, a1], []).
X = [bright, amber, on]
关键是使用"推回"(即 colour(X), As -->...
)。在这里,我们拆分无法解析的输入,使用一个令牌,然后推回其余的......
像往常一样,大部分时间都需要时间来了解我第一次尝试失败的地方:我正在编写char2atomic(C, A) :- atom_codes(A, [C]).
,但后来 rating//1 失败了......