关于您现有代码的快速说明:
在您的定义中,phrase1(Oclock)
中的Oclock
没有被确定,这意味着任何内容都可以作为phrase1。因此,对于phrase1\\0
的DCG规则将对任何单个元素列表成立:
?- 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实例化为所有可能的时间。
以防有任何混淆,无论是这个解决方案还是您自己的解决方案,都只适用于原子字符串,而不是字符字符串。因此,如果您正在尝试通过读取文件来解析自然语言,则必须进行一些工作,将输入的字符转换为原子,或使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
手册中还有许多与字符相关的述语。
?- set_prolog_flag(double_quotes, chars).
后,你会得到原子而不是字符编码,例如:?- Xs = "abc".
会产生Xs = [a,b,c]
。这使得处理字符串更加方便。 - matdouble_quotes
标志的建议,并享受了其带来的好处。 - Shon