A quick note about your existing code:
In your definition phrase1(Oclock)
, Oclock
is left completely undetermined, which means that anything will count as phrase1. Thus, your DCG rule for phrase1\\0
will be true for any single element list:
?- phrase(phrase1, X).
X = [_G481].
?- phrase(phrase1, [a]).
true.
?- phrase(phrase1, [abababab]).
true.
?- phrase(phrase1, [[aba,dbdi,dbdi]]).
true.
?- phrase(phrase1, []).
false.
A possible solution to your question:
Here is one possible solution:
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].
Test it with the query:
?- phrase(time, [1,'.',10,am]).
true.
phrase/2
or phrase/3
are the standard predicates for calling DCG rules. You can also query phrase(time, X)
and see X instantiated with all possible times.
Just in case there is any confusion, both this solution and your own will only work for strings of atoms, but not strings of characters. So if you're trying to parse natural language by reading in a file, you'll have to do some work either converting the characters input into atoms or make the dcg deal with characters instead. E.g.,
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).
Lists of atoms have been exchanged for lists of character codes; since?- A = "aaa". A = [97, 97, 97].
In SWI-Prolog, conversion between atoms and code characters can be achieved through predicates listed here: file:///opt/local/lib/swipl-6.4.1/doc/Manual/manipatom.html#atom_chars/2
There are many more character related predicates to found in the manual.