- Documentation
- Reference manual
- Built-in Predicates
- Notation of Predicate Descriptions
- Character representation
- Loading Prolog source files
- Editor Interface
- Verify Type of a Term
- Comparison and Unification of Terms
- Control Predicates
- Meta-Call Predicates
- Delimited continuations
- Exception handling
- Printing messages
- Handling signals
- DCG Grammar rules
- Database
- Declaring predicate properties
- Examining the program
- Input and output
- Status of streams
- Primitive character I/O
- Term reading and writing
- Analysing and Constructing Terms
- Analysing and Constructing Atoms
- Localization (locale) support
- Character properties
- Operators
- Character Conversion
- Arithmetic
- Misc arithmetic support predicates
- Built-in list operations
- Finding all Solutions to a Goal
- Forall
- Formatted Write
- Global variables
- Terminal Control
- Operating System Interaction
- File System Interaction
- User Top-level Manipulation
- Creating a Protocol of the User Interaction
- Debugging and Tracing Programs
- Debugging and declaring determinism
- Obtaining Runtime Statistics
- Execution profiling
- Memory Management
- Windows DDE interface
- Miscellaneous
- Built-in Predicates
- Packages
- Reference manual
4.24 Character properties
SWI-Prolog offers two comprehensive predicates for classifying characters and character codes. These predicates are defined as built-in predicates to exploit the C-character classification's handling of locale (handling of local character sets). These predicates are fast, logical and deterministic if applicable.
In addition, there is the library library(ctypes)
providing compatibility with some other Prolog systems. The predicates
of this library are defined in terms of code_type/2.
- code_type(?Code, ?Type)
- char_type(?Char, ?Type)
- Tests or generates alternative Types or Char/Codes.
The character types are inspired by the standard C
<ctype.h>primitives. Neither the classes nor the case conversions are sensitive to the active locale: they are derived from the Unicode Character Database at build time (unicode_syntax_version) rather than from the C library's<wctype.h>, so a program classifies text the same way regardless ofLC_CTYPEand of the platform's C library. This also means the classes agree with the classification used by read/1 and friends, which is where the typesprolog_var_start,prolog_atom_start,prolog_identifier_continueandprolog_symbolcome from. The case (to_lower,to_upper,lower(Upper)andupper(Lower)) still use the C library and are thus still locale conversions (to_lower,to_upper,lower(Upper)andupper(Lower)) use the Unicode simple case mapping, which is one code point to one code point and thus length preserving;upcase_atom('straße', X)yields'STRAßE'rather than'STRASSE'. Because the mapping is Unicode's rather than the C library's, it does not follow the Turkish and Azeri dotted/dotlessirules even under atr_TRlocale. Foreign code can reach the same classifier and the same case mapping through PL_ctype_flags(), PL_toupper(), PL_tolower() and PL_totitle().Every type is derived from the Unicode Character Database, from the files
UnicodeData.txt(general categories and the simple case mappings),DerivedCoreProperties.txt(Alphabetic, Uppercase, Lowercase, XID_Start, XID_Continue),PropList.txt(White_Space, Sentence_Terminal, Pattern_Syntax) andEastAsianWidth.txt(display width), for the Unicode version named by the unicode_syntax_version flag. The derivations are:Type Derived from alnumalpha, or category Nd, Nl or Noalphaproperty Alphabetic asciicode point < 128; not a Unicode notion cntrlcategory Cc or Cf csymASCII letter, digit or _; see belowcsymfASCII letter or _; see belowdecimalcategory Nd digitU+0030..U+0039; POSIX fixes this to ASCII end_of_filethe code -1 end_of_linethe Unicode line terminators graphalnumorpunctlowerproperty Lowercase newlineU+000A parencategories Ps and Pe, paired pattern_syntaxproperty Pattern_Syntax (UAX #31) periodproperty Sentence_Terminal printgraph, or white space that is not Ccprolog_end_of_linethe Unicode line terminators prolog_layoutproperty Pattern_White_Space (UAX #31) punctcategory P* or S*, not Alphabetic quote',",`and categories Pi, Pfspaceproperty White_Space to_lower,to_upperthe simple case mappings upperproperty Uppercase whiteWhite_Space minus end_of_linewidthproperty East_Asian_Width (UAX #11) xdigit0..9,a..f,A..FThe types
prolog_var_start,prolog_atom_start,prolog_identifier_continue,prolog_symbolandprolog_soloare the reader's own classification; see section 2.15.1.9.Note that the mode (-,+) is only efficient if the Type has a parameter, e.g.,
char_type(C, digit(8)). If Type is a atomic, the whole unicode range (0..0x1ffff) is generated and tested against the character classification function.- alnum
- Char is
alphaor a numeric character (Unicode general category Nd, Nl or No). Note that this is wider thandigit: e.g.0’(ARABIC-INDIC DIGIT ZERO) and
u06600’(VULGAR FRACTION ONE HALF) are
u00BDalnumbut notdigit. - alpha
- Char has the Unicode Alphabetic property. This covers the letters of all scripts, not just those that have case, as well as letter-like numbers such as the Roman numerals.
- csym
- Char is a character of a C identifier: an ASCII letter, an
ASCII digit or the underscore (
_). - csymf
- Char is a valid first character of a C identifier:
an ASCII letter or the underscore (
_).These two are ASCII because C identifiers are: C89 admits nothing else, and the extended identifiers of C99 and later are written as universal character names (
) rather than as source characters. Prolog identifiers do range over all of Unicode; use\u00E9prolog_atom_start,prolog_var_startandprolog_identifier_continuefor those, oralnumandalphafor a script-independent notion of a word character. - ascii
- Char is a 7-bit ASCII character (0..127). This is the one type that is defined by the code point range rather than by a Unicode property.
- white
- Char is white space that stays within a line: the
spacecharacters minus the seven line terminators (U+000A.. U+000D, U+0085, U+2028 and U+2029). That leaves U+0009 TAB, U+0020 SPACE, U+00A0 NO-BREAK SPACE, U+1680, U+2000..U+200A, U+202F, U+205F and U+3000 IDEOGRAPHIC SPACE. This is what POSIX callsblank. - cntrl
- Char is a control character (Unicode general category
Cc, i.e. 0..31, 127 and 128..159) or a format character (category Cf,
e.g. U+00AD SOFT HYPHEN, U+200B ZERO WIDTH SPACE and U+FEFF).
U+0009..U+000D and U+0085 are both
cntrlandspace. Note that U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR arespace, notcntrl. - digit
- Char is in 0 ... 9. POSIX requires the
digitclass to hold exactly the ten ASCII digits, so the decimal digits of other scripts arealnumanddecimal, but notdigit. See alsodecimal. - digit(Weight)
- Char is a digit with value Weight. I.e.
char_type(X, digit(6))yields X =’6’. Useful for parsing numbers. - xdigit(Weight)
- Char is a hexadecimal digit with value Weight.
I.e.
char_type(a, xdigit(X))yields X =’10’. Useful for parsing numbers. As withdigit(Weight)this is ASCII only; there is no Unicode-wide counterpart because hexadecimal notation is a source syntax rather than a script property. - decimal
- Char is a decimal digit in any script. This implies it has the Unicode general category Nd).
- decimal(Weight)
- Char is a decimal digit in any script with Weight 0 ... 9.
- Char is a printable character:
graph, or white space that is not a control character (U+0020, U+00A0, U+2028, U+3000, ... but not tab or newline). - graph
- Char produces a visible mark on a page when printed, i.e.
alnumorpunct. Note that the space is not included! POSIX requiresgraphandspaceto be disjoint, which is why U+00A0 NO-BREAK SPACE isprintbut notgraph. - lower
- Char is a lowercase letter.
- lower(Upper)
- Char is a lowercase version of Upper. Only true if Char is lowercase and Upper uppercase.
- to_lower(Upper)
- Char is a lowercase version of Upper. For non-letters, or letter without case, Char and Lower are the same. See also upcase_atom/2 and downcase_atom/2.
- upper
- Char is an uppercase letter.
- upper(Lower)
- Char is an uppercase version of Lower. Only true if Char is uppercase and Lower lowercase.
- to_upper(Lower)
- Char is an uppercase version of Lower. For non-letters, or letter without case, Char and Lower are the same. See also upcase_atom/2 and downcase_atom/2.
- punct
- Char is a punctuation character. This is a
graphcharacter that is not a letter or digit. - space
- Char has the Unicode White_Space property: the ASCII
layout characters (tab, newline, vertical tab, form feed, carriage
return and space), U+0085 NEL, U+00A0 NO-BREAK SPACE, U+1680, the
U+2000..U+200A spaces, U+2028, U+2029, U+202F, U+205F and U+3000. Note
that
<wctype.h>implementations disagree here: glibc denies that U+00A0 is white space and Darwin denies that U+0085 is. Note also that U+00A0 is deliberately not layout for the reader; seeprolog_layout. - end_of_file
- Char is -1.
- end_of_line
- Char terminates a line: the seven code points Unicode defines
as line terminator, being U+000A LF, U+000B VT, U+000C FF,
U+000D CR, U+0085 NEL, U+2028 LINE SEPARATOR and U+2029 PARAGRAPH
SEPARATOR. Equivalently,
spacethat is notwhite: white space either stays within a line or ends it.prolog_end_of_lineis the set the reader acts on, which happens to be the same today but is defined by the Prolog syntax rather than by Unicode. - newline
- Char is a newline character (10).
- period
- Char counts as the end of a sentence. This is the Unicode
Sentence_Terminal property: besides
,.and!it holds the Armenian, Arabic, N'Ko, Devanagari, ideographic and fullwidth sentence enders, 170 code points in Unicode 17.? - quote
- Char is a quote character:
",',`or one of the Unicode initial/final quotation marks (categories Pi and Pf). Note that this holds for both sides of a pair, wherequote(Close)below holds only for the opening one. - paren(Close)
- Char is an opening bracket and Close is its
matching close. Covers the three ASCII bracket pairs
(),[]and{}, plus every UnicodePs/Pepair (about 60 pairs in Unicode 17, including angle, corner, ceiling, floor, mathematical, ornamental, fullwidth and CJK brackets). The mapping is reversible: with Close bound, Char unifies with the matching open. - quote(Close)
- Char is an opening quotation mark and Close is its
matching close. The ASCII quotes
’,", and‘have Close = Char; UnicodePi/Pfquote pairs (the guillemets, the standard left/right curly single and double quotes, and the single/double angle and reversed quotation marks) have Close different from Char. The mapping is reversible. - width(Width)
- Width is the number of columns for fixed-width usage used by Char.
True for all printable characters. Most characters require 1 column. Unicode
combining characters require no space (they follow the base
character). Many Asian characters and the Emojis require 2 columns.
These values are used by stream_property/2
for the
position(-Pos)property. - prolog_layout
- Char is a Prolog layout character: a member of the
Unicode
Pattern_White_Spaceset used by read_term/2 to separate tokens. The eleven code points are U+0009..U+000D, U+0020, U+0085, U+200E, U+200F, U+2028 and U+2029. Locale- independent; pinned to unicode_syntax_version.prolog_end_of_lineis the seven-element line-terminator subset. - prolog_end_of_line
- Char ends a line of Prolog source text. Covers the seven
line-terminator-like
Pattern_White_Spacecode points: U+000A (LF), U+000B (VT), U+000C (FF), U+000D (CR), U+0085 (NEL), U+2028 (LINE SEPARATOR), and U+2029 (PARAGRAPH SEPARATOR). The same set terminatescomments and increments the source line counter. It is the reader's own definition and is kept separate from%end_of_line, which is Unicode's, although the two currently agree. See section 2.15.1.9. - prolog_var_start
- Char can start a Prolog variable name.
- prolog_atom_start
- Char can start a unquoted Prolog atom that is not a symbol.
- prolog_identifier_continue
- Char can continue a Prolog variable name or atom.
- prolog_symbol
- Char is a Prolog symbol character. Sequences of Prolog symbol
characters glue together to form an unquoted atom. Examples are
,=.., etc.\= - prolog_solo
- Char is a Prolog solo character: a punctuation code
point that forms an atom on its own and never combines with neighbouring
symbol characters. In ASCII the solo set is
,!and;%; the same flag carries over to non-ASCII code points via the Unicode syntax map (see section 2.15.1.9). Solo characters are written unquoted by writeq/1 and are accepted as single-character atoms by the reader. - pattern_syntax
- Char has the Unicode
Pattern_Syntaxproperty (UAX #31 R3). This is the immutable set of punctuation and symbol code points whose classification is guaranteed not to change across Unicode versions. Used by write_canonical/1 and thepattern_syntax_solooption of write_term/2 to decide which single-character atoms can be printed bare with round-trip safety across Unicode upgrades.
4.24.1 Case conversion
There is nothing in the Prolog standard for converting case in textual data. The SWI-Prolog predicates code_type/2 and char_type/2 can be used to test and convert individual characters. We have started some additional support:
- downcase_atom(+AnyCase, -LowerCase)
- Converts the characters of AnyCase into lowercase as char_type/2 does (i.e. based on the defined locale if Prolog provides locale support on the hosting platform) and unifies the lowercase atom with LowerCase.
- upcase_atom(+AnyCase, -UpperCase)
- Converts, similar to downcase_atom/2, an atom to uppercase.
4.24.2 White space normalization
- normalize_space(-Out, +In)
- Normalize white space in In. All leading and trailing white
space is removed. All non-empty sequences of white space characters are
replaced by a single space (
\u0020) character. Out uses the same conventions as with_output_to/2 and format/3.A character counts as white space if it satisfies
code_type(Code, space), i.e., the C library function iswspace(). This depends on the locale. Using a Unicode locale this includes the Unicode separator characters such as\u00a0(no-break space) and\u3000(ideographic space), while in theClocale only the ASCII white space characters are recognised. Note that the bidi format characters\u200eand\u200fare not white space and are thus preserved.
4.24.3 Language-specific comparison
This section deals with predicates for language-specific string comparison operations.
- collation_key(+Atom, -Key)
- Create a Key from Atom for locale-specific
comparison. The key is defined such that if the key of atom A
precedes the key of atom B in the standard order of terms, A
is alphabetically smaller than B using the sort order of the
current locale.
The predicate collation_key/2 is used by locale_sort/2 from library(sort). Please examine the implementation of locale_sort/2 as an example of using this call.
The Key is an implementation-defined and generally unreadable string. On systems that do not support locale handling, Key is simply unified with Atom.
- locale_sort(+List, -Sorted)
- Sort a list of atoms using the current locale. List is a list of atoms or string objects (see section 5.2). Sorted is unified with a list containing all atoms of List, sorted to the rules of the current locale. See also collation_key/2 and setlocale/3.