关于现有代码的快速说明:
在您的定义phrase1(Oclock)
中,Oclock
完全未确定,这意味着任何内容都将被视为短语 1。因此,您的 DCG 规则对于任何单个元素列表phrase1\\0
都是正确的:
?- phrase(phrase1, X).
X = [_G481].
?- phrase(phrase1, [a]).
true.
?- phrase(phrase1, [abababab]).
true.
?- phrase(phrase1, [[aba,dbdi,dbdi]]).
true.
?- phrase(phrase1, []).
false.
您的问题的可能解决方案:
这是一种可能的解决方案:
time --> hours, suffix.
suffix --> sep, minutes, meridiem.
suffix --> ['oclock'].
hours --> {between(1,12,H)}, [H].
sep --> ['.'].
minutes --> {between(1,60,M)}, [M].
meridiem --> [am].
meridiem --> [pm].
使用以下查询对其进行测试:
?- phrase(time, [1,'.',10,am]).
true.
phrase/2
或者phrase/3
是调用 DCG 规则的标准谓词。您还可以查询phrase(time, X)
并查看用所有可能的时间实例化的 X。
以防万一有任何混淆,这个解决方案和您自己的解决方案都只适用于atom 字符串,而不适用于字符串。因此,如果您尝试通过读入文件来解析自然语言,则必须做一些工作,要么将输入的字符转换为原子,要么让 dcg 处理字符。例如,
time --> hours, suffix.
suffix --> sep, minutes, meridiem.
suffix --> " oclock".
hours --> {hours(H)}, H.
sep --> ".".
minutes --> {minutes(M)}, M.
meridiem --> " am".
meridiem --> " pm".
hours(H) :-
between(1,12,N),
atom_codes(N,H).
minutes(M) :-
between(1,60,N),
atom_codes(N,M).
原子列表已替换为字符代码列表;因为?- A = "aaa". A = [97, 97, 97].
在 SWI-Prolog 中,原子和代码字符之间的转换可以通过这里列出的谓词来实现:file:///opt/local/lib/swipl-6.4.1/doc/Manual/manipatom.html#atom_chars/2
手册中还有更多与字符相关的谓词。