我有一个简单的语法,它需要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规则来分割它,但我不确定这是否可行,因为我们正在解析列表,而不是原子。
答案 0 :(得分:4)
正如你自己所说,你只需要使用像atom_chars/2
这样的谓词。您可以将普通代码插入到{
和}
中,将其交错为DCG规则。
但是你的问题定义有些可疑。正如你自己也说过的那样,你正在解析一个列表,而不是一个原子。您正在解析的列表应该已经正确标记,否则您不能期望定义可以解析它的DCG。或者我看到了这个错误?
换句话说:你接受输入,分成单个字符,用DCG标记。根据您的输入,您可以在同一步骤中进行解析。
答案 1 :(得分:4)
很明显,精确的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]
关键是使用'pushback'(即colour(X), As -->...
)。
在这里我们拆分不可解析的输入,使用一个令牌,然后推回其余的......
像往常一样,大部分时间都需要了解我的第一次尝试失败的地方:我正在编码char2atomic(C, A) :- atom_codes(A, [C]).
,但后来评分// 1失败......