/*  CHARS.PL  */

/*
:- module chars.


:- public is_newline_char/1,
          is_space_char/1,
          is_layout_char/1,
          is_printable_char/1,
          is_end_of_file_char/1,
          is_digit_char/1,
          is_digit_char/2,
          is_letter_char/1,
          is_letter_or_digit_char/1,
          is_uppercase_char/1,
          is_uppercase_char/2,
          is_lowercase_char/1,
          is_lowercase_char/2,
          is_underline_char/1,
          is_single_quote_char/1,
          is_double_quote_char/1,
          is_star_char/1,
          is_slash_char/1,
          is_backslash_char/1,
          is_left_round_bracket_char/1,
          is_right_round_bracket_char/1,
          is_dot_char/1,
          is_percent_char/1,
          is_query_char/1,
          is_shriek_char/1,
          is_comma_char/1,
          is_semicolon_char/1,
          is_left_square_bracket_char/1,
          is_right_square_bracket_char/1,
          is_left_curly_bracket_char/1,
          is_stick_char/1,
          is_right_curly_bracket_char/1,
          is_little_e_char/1,
          is_plus_char/1,
          is_minus_char/1,
          is_equals_char/1,
          is_ampersand_char/1,
          char_to_uppercase/2,
          chars_to_uppercase/2,
          char_to_lowercase/2,
          chars_to_lowercase/2.
*/


/*
SPECIFICATION
-------------

This module exports recognisers for certain character codes. Using
these, rather than explicit numbers, will make programs more portable.


PUBLIC is_newline_char( C? ):
C is the value returned by 'get0' on reading a newline.

PUBLIC is_end_of_file_char( C? ):
C is the value returned by 'get0' on reading end-of-file.

PUBLIC is_space_char( C? ):
C represents a space.

PUBLIC is_layout_char( C? ):
C is a layout character, including space, tab, linefeed, etc, but not
including end of file.

PUBLIC is_printable_char( C? ):
C is a printable character (and not a space, newline, tab, delete, null,
etc.).

PUBLIC is_digit_char( C+ ):
C represents '0', '1' ... '9'.

PUBLIC is_digit_char( C?, Value? ):
C represents '0', '1' ... '9'.
Value is the corresponding integer, 0..9.

PUBLIC is_letter_char( C+ ):
C represents any letter.

PUBLIC is_letter_or_digit_char( C+ ):
is_letter_char(C) or is_digit_char(C).

PUBLIC is_uppercase_char( C+ ):
C represents A..Z.

PUBLIC is_uppercase_char( C?, Ord? ):
C represents A..Z.
Ord is its position in the alphabet, with A=1.

PUBLIC is_lowercase_char( C+ ):
C represents a..z.

PUBLIC is_lowercase_char( C?, Ord? ):
C represents a..z.
Ord is its position in the alphabet, with a=1.

PUBLIC is_underline_char( C? ):
C represents _.

PUBLIC is_single_quote_char( C? ).
C represents '.

PUBLIC is_double_quote_char( C? ):
C represents ".

PUBLIC is_slash_char( C? ):
C represents /.

PUBLIC is_backslash_char( C? ):
C represents \.

PUBLIC is_star_char( C? ):
C represents *.

PUBLIC is_left_round_bracket_char( C? ):
C represents (.

PUBLIC is_right_round_bracket_char( C? ):
C represents ).

PUBLIC is_dot_char( C? ):
C represents ..

PUBLIC is_percent_char( C? ):
C represents %.

PUBLIC is_shriek_char( C? ):
C represents !.

PUBLIC is_query_char( C? ):
C represents ?.

PUBLIC is_comma_char( C? ):
C represents ,.

PUBLIC is_semicolon_char( C? ):
C represents ;.

PUBLIC is_left_square_bracket_char( C? ):
C represents [.

PUBLIC is_right_square_bracket_char( C? ):
C represents ].

PUBLIC is_left_curly_bracket_char( C? ):
C represents {.

PUBLIC is_stick_char( C? ):
C represents |.

PUBLIC is_right_curly_bracket_char( C? ):
C represents ].

PUBLIC is_little_e_char( C? ):
C represents e.

PUBLIC is_plus_char( C? ):
C represents +.

PUBLIC is_minus_char( C? ):
C represents -.

PUBLIC is_equals_char( C? ):
C represents =.

PUBLIC is_ampersand_char( C? ):
C represents &.

PUBLIC char_to_uppercase( C+, UC? ):
If C is in lowercase, converts to uppercase in UC, else leaves alone.

PUBLIC chars_to_uppercase( Chars+, UC? ):
Converts all lowercase characters in Chars to uppercase.

PUBLIC char_to_lowercase( C+, LC? ):
If C is in uppercase, converts to lowercase in LC, else leaves alone.

PUBLIC chars_to_lowercase( Chars+, LC? ):
Converts all lowercase characters in Chars to lowercase.
*/



/*
IMPLEMENTATION
--------------

This version assumes ASCII. On some ASCII systems, the newline character
may be 13 and not 10.

If your system uses EBCDIC, remember that the character codes for
letters (and digits?) are not contiguous.
*/


:- needs assertion.


is_newline_char( 10 ).


is_end_of_file_char( 26 ).


is_space_char( 32 ).


is_layout_char( C ) :-
    C =< 32, C \= 26.


is_printable_char( C ) :-
    C > 32, C < 127.


is_underline_char( 95 ).


is_single_quote_char( 39 ).


is_double_quote_char( 34 ).


is_dot_char( 46 ).


is_left_round_bracket_char( 40 ).


is_right_round_bracket_char( 41 ).


is_star_char( 42 ).


is_slash_char( 47 ).


is_backslash_char( 92 ).


is_percent_char( 37 ).


is_shriek_char( 33 ).


is_query_char( 63 ).


is_comma_char( 44 ).


is_semicolon_char( 59 ).


is_left_square_bracket_char( 91 ).


is_right_square_bracket_char( 93 ).


is_left_curly_bracket_char( 123 ).


is_stick_char( 124 ).


is_right_curly_bracket_char( 125 ).


is_digit_char( C ) :-
    C >= 48,
    C =< 57.


is_digit_char( C, Value ) :-
    nonvar(C),
    !,
    C >= 48,
    C =< 57,
    Value is C-48.

is_digit_char( C, Value ) :-
    nonvar(Value),
    !,
    assertion( (Value>=0,Value=<9), 'is_digit_char: Value out of range', [Value] ),
    C is Value + 48.

is_uppercase_char( C ) :-
    C >= 65 /*A*/,
    C =< 90 /*Z*/.


is_uppercase_char( C, Ord ) :-
    nonvar(C),
    !,
    ( C >= 65 /*A*/, C =< 90 /*Z*/ ),
    Ord is C - 64.

is_uppercase_char( C, Ord ) :-
    nonvar(Ord),
    !,
    assertion( (Ord>=1,Ord=<26), 'is_uppercase_char: Ord out of range', [Ord] ),
    C is Ord + 64.


is_lowercase_char( C ) :-
    C >= 97  /*a*/,
    C =< 122 /*z*/.


is_lowercase_char( C, Ord ) :-
    nonvar(C),
    !,
    ( C >= 97 /*a*/, C =< 122 /*z*/ ),
    Ord is C - 96.

is_lowercase_char( C, Ord ) :-
    nonvar(Ord),
    !,
    assertion( (Ord>=1,Ord=<26), 'is_lowercase_char: Ord out of range', [Ord] ),
    C is Ord + 96.


is_letter_char( C ) :-
    (
        C >= 65, C =< 90
    ;
        C >= 97, C =< 122
    ),
    !.


is_letter_or_digit_char( C ) :-
    (
        is_letter_char( C )
    ;
        is_digit_char( C )
    ),
    !.


is_little_e_char( 101 ).


is_plus_char( 43 ).


is_minus_char( 45 ).


is_equals_char( 61 ).


is_ampersand_char( 38 ).


char_to_uppercase( C, UC ) :-
    is_lowercase_char( C, Ord ),
    !,
    is_uppercase_char( UC, Ord ).

char_to_uppercase( C, C ).


chars_to_uppercase( [], [] ) :- !.

chars_to_uppercase( [H|T], [UH|UT] ) :-
    char_to_uppercase( H, UH ),
    chars_to_uppercase( T, UT ).


char_to_lowercase( C, LC ) :-
    is_uppercase_char( C, Ord ),
    !,
    is_lowercase_char( LC, Ord ).

char_to_lowercase( C, C ).


chars_to_lowercase( [], [] ) :- !.

chars_to_lowercase( [H|T], [LH|LT] ) :-
    char_to_lowercase( H, LH ),
    chars_to_lowercase( T, LT ).

/*
:- endmodule.
*/
