/*  OUTPUT_ENGLISH.PL  */
 
 
:- module output.
 
 
/*
SPECIFICATION
-------------
 
This module defines some specialised user-output clauses for pluralising
nouns, outputting is/are, and placing an indefinite article before a
noun.
 
The structure
    is_are_(N)
is output as 'is' if N=1, otherwise 'are'.
 
The structure
    number_(Ending,Noun,N)
is output as Noun if N=1, otherwise Noun<>Ending. Ending must be 's' or
'es'.
 
The structure
    a_(Noun)
is output as 'an'...Noun if Noun starts with a vowel, otherwise
'a'...Noun.
*/
 
 
/*
IMPLEMENTATION
--------------
 
The character codes in is_vowel below are non-portable.
 
 
Adapting to other languages.
----------------------------
 
A problem that English largely lacks is that of inflection. It is, for
example, possible to stick any adjective in front of any noun without
having to change its form. This makes it easy to build messages from
templates without knowing the words to be fitted in in advance.
 
I have checked through all the messages output by the Tutor, and as far
as I can tell, none of them would cause problems in another language.
They don't require a word in one part of the message to change form
according to a word somewhere else, whether with noun/adjective
agreement, noun/article agreement, verb/subject agreement, or whatever.
 
Regarding things specific to this module, the a_ structure defined above
is not used anywhere in the Tutor. The other two are only used in
AND_OR.PL. The is_are_ structure should be easily translatable. The
number_ structure may give difficulties in languages like German, where
you have internal inflection of some plurals. It may be better to
replace it by
    number_(N,NounS,NounP)
where NounS and NounP are the noun's singular and plural forms, with one
or the other being selected, depending on N.
 
You could extend this approach by building a dictionary which lists the
properties of all your nouns, with clauses such as
    noun( Tag, NounS, NounP, Gender )
 
Here, Tag is some atom which you use to refer to the noun. Then you
could add user-output clauses such as
    output_word( number_(1,Tag) ) :-
        %   Output the singular form of Tag
        !,
        noun( Tag, NounS, _, _ ),
        output( NounS ).
 
    output_word( number_(_,Tag) ) :-
        %   Output the plural form of Tag
        !,
        noun( Tag, _, NounP, _ ),
        output( NounP ).
 
    output_word( the_(Tag) ) :-
        %   Output the definite article appropriate for Tag's gender.
        !,
        noun( Tag, NounS, _, Gender ),
        ( Gender = n -> output(het) ; output(de) ),
        output( ' '<>NounS ).              
*/
 
 
:- needs add_user_output/1,output/1.
 
 
:- add_user_output( output_english ).
 
 
output_english( is_are_(1) ) :-
    !,
    output( is ).
 
output_english( is_are_(_) ) :-
    !,
    output( are ).
 
output_english( number_(_,Noun,1) ) :-
    !,
    output( Noun ).
 
output_english( number_(es,Noun,_) ) :-
    !,
    output( Noun<>es ).
 
output_english( number_(s,Noun,_) ) :-
    !,
    output( Noun<>s ).
 
output_english( a_(Noun) ) :-
    !,
    indefinite_article( Noun, A ),
    output( A...Noun ).
 
 
/*  indefinite_article( Noun+, A- ):
        If Noun starts with a vowel, A is 'an', otherwise 'a'.
*/
indefinite_article( Noun, an ) :-
    atom( Noun ),
    name( Noun, [C|_] ),
    is_vowel( C ),
    !.
 
indefinite_article( Noun, a ).
 
 
is_vowel( 97 /*a*/ ).
is_vowel( 101/*e*/ ).
is_vowel( 105/*i*/ ).
is_vowel( 111/*o*/ ).
is_vowel( 117/*u*/ ).
is_vowel( 65 /*A*/ ).
is_vowel( 69 /*E*/ ).
is_vowel( 73 /*I*/ ).
is_vowel( 79 /*O*/ ).
is_vowel( 85 /*U*/ ).
 
 
:- endmodule.
