DCG - 如何将原子拆分为列表以进行进一步的dcg规则处理

时间:2013-12-27 16:55:24

标签: prolog dcg

我有一个简单的语法,它需要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规则来分割它,但我不确定这是否可行,因为我们正在解析列表,而不是原子。

2 个答案:

答案 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失败......