Quintus Prolog Manual
This chapter describes the syntax of Quintus Prolog.
The data objects of the language are called terms. A term is either a constant, a variable, or a compound term.
A constant is either a number (integer or floating-point) or an atom. Constants are definite elementary objects, and correspond to proper nouns in natural language.
Variables and compound terms are described in section G-1-1-4, and section G-1-2, respectively.
Foreign data types are discussed in Chapter K-10, on the Structs library package.
The printed form of an integer consists of a sequence of digits optionally preceded by a minus sign (-). These are normally interpreted as base 10 integers. It is also possible to enter integers in other bases (1 through 36); this is done by preceding the digit string by the base (in decimal) followed by an apostrophe. If a base greater than 10 is used, the characters A-Z or a-z are used to stand for digits greater than 9.
Examples of valid integer representations are:
1 -2345 85923 8'777 16'3F4A -12'2A9
Note that
+525
is not a valid integer.
A base of zero will return the ASCII code of the (single) character after the quote; for example,
0'a = 97
G-1-1-2: Floating-point Numbers
A floating-point number (float) consists of a sequence of digits with an embedded decimal point, optionally preceded by a minus sign (-), and optionally followed by an exponent consisting of upper- or lowercase 'E' and a signed base 10 integer. Examples of floats are:
1.0 -23.45 187.6E12 -0.0234e15 12.0E-2
Note that there must be at least one digit before, and one digit after, the decimal point.
An atom is identified by its name, which is a sequence of up to 65532 characters (other than the null character). An atom can be written in any of the following forms:
+ - * / \ ^ < > = ` ~ : . ? @ # $ &
'yes' '%'
If the single quote character is included in the sequence it must be written twice, for example:
'can''t' ''''
For further details see section G-1-7-5.
! ; [] {}
Note that the bracket pairs are special: '[]' and '{}' are atoms but '[', ']', '{', and '}' are not. The form [X] is a special notation for lists (see section G-1-2-1), and the form {X} is
allowed as an alternative to '{}'(X).
Examples of atoms are:
a void = := 'Anything in quotes' []
WARNING: It is recommended that you do not invent atoms beginning with the character '$', since it is possible that such names may conflict with the names of atoms having special significance for certain built-in predicates.
Variables may be written as any sequence of alphanumeric characters (including '_') beginning with either a capital letter or '_'. For example:
X Value A A1 _3 _RESULT
If a variable is referred to only once in a clause, it does not need to be named and may be written as an anonymous variable, represented by the underline character '_' by itself. Any number of anonymous variables may appear in a clause; they are read as distinct variables. Anonymous variables are not special at runtime.
Pointers to C data structures can be handled using the Structs package, described in Chapter K-10.
The structured data objects of Prolog are compound terms. A compound term comprises a name (called the principal functor of the term) and a sequence of one or more terms called arguments . A functor is characterized by its name, which is an atom, and its arity or number of arguments. For example, the compound term whose principal functor is 'point' of arity 3, and which has arguments X, Y, and Z, is written
point(X, Y, Z)
When we need to refer explicitly to a functor we will normally denote it by the form Name/Arity. Thus, the functor 'point' of arity 3 is denoted
point/3
Note that a functor of arity 0 is represented as an atom.
Functors are generally analogous to common nouns in natural language. One may think of a functor as a record type and the arguments of a compound term as the fields of a record. Compound terms are usefully pictured as trees. For example, the (compound) term
s(np(john), vp(v(likes), np(mary)))
would be pictured as the following tree:
s
/ \
np vp
| / \
john v np
| |
likes mary
The principal functor of this term is s/2. Its arguments are also compound terms. In illustration, the principal functor of the first argument is np/1.
Sometimes it is convenient to write certain functors as operators; binary functors (that is, functors of two arguments) may be declared as infix operators, and unary functors (that is, functors of one argument) may be declared as either prefix or postfix operators. Thus it is possible to write
X+Y P;Q X<Y +X P;
as optional alternatives to
+(X,Y) ;(P,Q) <(X,Y) +(X) ;(P)
The use of operators is described fully in section G-1-4.
Lists form an important class of data structures in Prolog. They are essentially the same as the lists of Lisp: a list is either the atom '[]', representing the empty list, or else a compound term with functor '.' and two arguments which are the head and tail of the list respectively, where the tail of a list is another list. Thus a list of the first three natural numbers is the structure
.
/ \
1 .
/ \
2 .
/ \
3 []
which could be written using the standard syntax, as (A) but which is normally written in a special list notation, as (B). Two examples of this list notation, as used when the tail of a list is a
variable, are (C) which represent the structure in (D).
.(1,.(2,.(3,[]))) (A)
[1,2,3] (B)
[X|L] [a,b|L] (C)
. .
/ \ / \
X L a .
/ \
b L (D)
Note that the notation [X|L] does not add any new power to the language; it simply improves readability. These examples could be written equally well as (E).
.(X,L) .(a,.(b,L)) (E)
For convenience, a further notational variant is allowed for lists of integers that correspond to ASCII character codes. Lists written in this notation are called strings . For example,
"Humpty-Dumpty"
represents exactly the same list as[72,117,109,112,116,121,45,68,117,109,112,116,121]
The character escaping facility allows escape sequences to occur within strings and quoted atoms, so that programmers can put non-printable characters in atoms and strings and still be able to see what they are doing. This facility can be switched on and off by the commands:
| ?- prolog_flag(character_escapes, _,
on).
| ?- prolog_flag(character_escapes, _, off).
See section G-10, for a description of prolog_flag/3. Character escaping is off by default.
Strings or quoted atoms containing the following escape sequences can occur in terms obtained by read/[1,2], compile/1, and so on.
The 0' notation for the integer code of a character is also affected by character escaping.
With character escaping turned on, the only things that can occur in a string or quoted atom are the characters with ASCII codes 9 (horizontal tab), 32 (space), 33 through 126 (non-layout characters), or one of the following escape sequences:
It is an error if an escape sequence or ASCII character which is not defined above occurs in a string or quoted atom. For instance, an ordinary newline in an atom or string is regarded as an error when character escapes are on. This allows the syntax error of a missing closing quote to be caught much earlier, but it has the problem that some old programs will break (which is why character_escapses are off by default).
With character escaping turned on, the escape sequence (\') represents the same character as the sequence ('') within a quoted atom, namely one single quote. Similarly, with character escaping turned on, the escape sequence (\") represents the same character as the sequence ("") within a string, namely one double quote.
The escape sequence '\c' (c for continue) is useful when formatting a string for readability. For example, the atom (A), is equivalent to (B):
'!Ruth \c (A)
Gehrig \c
Cobb \c
Williams!'
'!Ruth Gehrig Cobb Williams!' (B)
The following sequence denotes the integer 9:
(0'\t)
G-1-4: Operators and their Built-in Predicates
Operators in Prolog are simply a notational convenience. For example, '+' is an infix operator, so
2 + 1
is an alternative way of writing the term +(2, 1). That is, 2 + 1 represents the data structure
+
/ \
2 1
and not the number 3. (The addition would only be performed if the structure were passed as an argument to an appropriate procedure, such as is/2; see section G-8-1.)
Prolog syntax allows operators of three kinds: infix, prefix, and postfix. An infix operator appears between its two arguments, while a prefix operator precedes its single argument and a postfix operator follows its single argument.
Each operator has a precedence, which is a number from 1 to 1200. The precedence is used to disambiguate expressions in which the structure of the term denoted is not made explicit through the use of parentheses. The general rule is that the operator with the highest precedence is the principal functor. Thus if '+' has a higher precedence than '/', then
a+b/c a+(b/c)
are equivalent, and denote the term "+(a,/(b,c))". Note that the infix form of the term "/(+(a,b),c)" must be written with explicit parentheses:
(a+b)/c
If there are two operators in the expression having the same highest precedence, the ambiguity must be resolved from the types of the operators. The possible types for an infix operator are
xfx xfy yfx
Operators of type 'xfx' are not associative: it is required that both of the arguments of the operator must be subexpressions of lower precedence than the operator itself; that is, the principal
functor of each subexpression must be of lower precedence, unless the subexpression is written in parentheses (which gives it zero precedence).
Operators of type 'xfy' are right-associative: only the first (left-hand) subexpression must be of lower precedence; the right-hand subexpression can be of the same precedence as the main operator. Left-associative operators (type 'yfx') are the other way around.
An atom named Name is declared as an operator of type Type and precedence Precedence by the command
:-op(Precedence, Type, Name).
An operator declaration can be cancelled by redeclaring the Name with the same Type, but Precedence 0.
The argument Name can also be a list of names of operators of the same type and precedence.
It is possible to have more than one operator of the same name, so long as they are of different kinds: infix, prefix, or postfix. An operator of any kind may be redefined by a new declaration of the same kind. Declarations for all these built-in operators can be found in section G-1-4-4. For example, the built-in operators '+' and '-' are as if they had been declared by (A) so that (B) is valid syntax, and means (C) or pictorially (D).
:-op(500, yfx, [+,-]). (A)
a-b+c (B)
(a-b)+c (C)
+
/ \
- c
/ \
a b (D)
The list functor '.'/2 is not a standard operator, but we could declare it to be (E) then (F) would represent the structure (G).
:-op(600, xfy, .). (E)
a.b.c (F)
.
/ \
a .
/ \
b c (G)
Contrasting this with the diagram above for a-b+c shows the difference between 'yfx' operators where the tree grows to the left, and 'xfy' operators where it grows to the right. The tree cannot grow at all for 'xfx' operators; it is simply illegal to combine 'xfx' operators having equal precedences in this way.
The possible types for a prefix operator are:
fx fy
and for a postfix operator they are:
xf yf
If these precedence and associativity rules seem rather complex, remember that you can always use parentheses when in any doubt.
G-1-4-2: Manipulating and Inspecting Operators
To add or remove an operator, use op(+Precedence, +Type, +Name). op/3 declares the atom Name to be an operator of the stated Type and Precedence. If Precedence is 0, then the operator properties of Name (if any) are cancelled.
To examine the set of operators currently in force, use current_op(*Precedence, *Type, *Name).
Note carefully the following syntax restrictions, which serve to remove potential ambiguities associated with prefix operators.
assert((P:-Q))
because the precedence of the infix operator ':-', and hence of the expression "P:-Q", is 1200. Enclosing the expression in parentheses reduces its precedence to 0.
[(P->Q)]
because the precedence of the infix operator '->', and hence of the expression "P->Q", is 1050. Enclosing the expression in parentheses reduces its precedence to 0.
point (X,Y,Z)
is invalid syntax.
:-(p;q),r.
(where ':-' is the prefix operator) is invalid syntax. The system would try to interpret it as the structure:
,
/ \
:- r
|
;
/ \
p q
That is, it would take ':-' to be a functor of arity 1. However, since the arguments of a functor are required to be expressions of precedence less than 1000, this interpretation would fail as
soon as the ';' (precedence 1100) were encountered.
In contrast, the term:
:- (p;q),r.
is valid syntax and represents the following structure:
:-
|
,
/ \
; r
/ \
p q
X = (?-)
since the precedence of '?-' is 1200.
:-op( 1200, xfx, [ :-, --> ])
:-op( 1200, fx, [ :-, ?- ])
:-op( 1150, fx, [ dynamic, multifile,
meta_predicate, initialization, volatile ])
:-op( 1100, xfy, [ ; ])
:-op( 1050, xfy, [ -> ])
:-op( 1000, xfy, [ ',' ])
:-op( 900, fy, [ \+, spy, nospy ])
:-op( 700, xfx, [ =, is, =.., ==, \==, @<, @>, @=<, @>=,
=:=, =\=, <, >, =<, >= ])
:-op( 600, xfy, [:])
:-op( 500, yfx, [ +, -, \/, /\ ])
:-op( 500, fx, [ +, - ])
:-op( 400, yfx, [ /, //, *, <<, >> div ])
:-op( 300, xfx, [ mod ])
:-op( 200, xfy, [ ^ ])
Two additional operators are provided solely for compatibility with other Prologs:
:- op(1150, fx, [mode, public])
Comments have no effect on the execution of a program, but they are very useful for making programs more comprehensible. Two forms of comments are allowed:
G-1-6: Predicate Specifications
A predicate is uniquely identified by its module (not always specified), name and arity (number of arguments). In Quintus Prolog these are the ways of specifying a predicate as an argument of a predicate:
| ?- predicate_property(put(97), P1),
predicate_property(put(98), P2).
P1 = P2 = built_in ;
no
When the skeletal specification is used as an output argument, Module:Name(Term1,Term2, ...,TermN) is made to be the most general term with name Name and arity N (that is, Term1, Term2,
..., TermN are each made to be variables, distinct from each other and any others in the system). For example,
| ?- compile(user).
| foo(1, 2, 3).
| end_of_file.
[user compiled (0.100 sec 196 bytes)]
yes
| ?- source_file(X, user).
X = foo(_224,_225,_226) ;
no
| ?- source_file(foo(7,8,9), user).
yes
prog1:foo/1 specifies predicate foo, arity 1 in module prog1. foo/1 specifies predicate foo of arity 1 in the current module.NOTES:
abolish/2 is the only predicate which does not use either of the above specifications. Its first argument is the Name of the predicate and the second argument is the Arity. For consistency, it is recommended that abolish/1 be used instead.
The following predicate can be used to convert between the Name/Arity specification and the skeletal specification, or to verify that two specifications identify the same predicate.
predicate_specification(NameAritySpec, SkeletalSpec) :-
(nonvar(NameAritySpec) ; nonvar(SkeletalSpec)),
!,
NameAritySpec = Name/Arity,
functor(SkeletalSpec, Name, Arity),
atom(Name).
A Prolog program consists of a sequence of sentences. Each sentence is a Prolog term. How sentences are interpreted as terms is defined in section G-1-7-2, below. Note that a term representing a sentence may be written in any of its equivalent syntactic forms. For example, the functor ':-'/2 could be written in standard prefix notation instead of as the usual infix operator.
Terms are written as sequences of tokens. Tokens are sequences of characters, which are treated as separate symbols. Tokens include the symbols for variables, constants, and functors, as well as punctuation characters such as parentheses and commas.
The interpretation of sequences of tokens as terms is defined in section G-1-7-3. Each list of tokens which is read in (for interpretation as a term or sentence) must be terminated by a
full-stop (a period followed by a layout character such as newline or space) token. Two tokens must be separated by a space if they could otherwise be interpreted as a single token. Both spaces and comments are ignored when interpreting the token list as a term. A comment may appear at any point in a token list (separated from other tokens by spaces where necessary).
The interpretation of tokens as sequences of characters is defined on section G-1-7-4. The next section describes the notation used in the formal definition of Prolog syntax.
C --> F1
| F2
| F3
.
.
.
which states that an entity of category C may take any of the alternative forms F1, F2, or F3.
G-1-7-2: Syntax of Sentences as Terms
sentence --> clause
| directive
| grammar-rule
clause --> non-unit-clause
| unit-clause
directive --> command
| query
non-unit-clause --> head :- goals
unit-clause --> head {where head is not otherwise a sentence}
command --> :- goals
query --> ?- goals
head --> term {where term is not a number or a variable}
goals --> goals , goals
| goals -> goals ; goals
| goals -> goals
| goals ; goals
| goal
goal --> term {where term is not a number and
is not otherwise a goals}
grammar-rule --> gr-head --> gr-body
gr-head --> nonterminal
| nonterminal , terminals
gr-body --> gr-body , gr-body
| gr-body ; gr-body
| gr-body -> gr-body; gr-body
| gr-body -> gr-body
| nonterminal
| terminals
| gr-condition
nonterminal --> term {where term is not a number or variable
and is not otherwise a gr-body}
terminals --> list
| string
gr-condition --> { goals }
G-1-7-3: Syntax of Terms as Tokens
term-read-in --> subterm(1200) full-stop
subterm(N) --> term(M) {where M is less than or equal to N}
term(N) --> op(N,fx)
| op(N,fy)
| op(N,fx) subterm(N-1)
{except the case '-' number}
{if subterm starts with a '(', op must be
followed by a space}
| op(N,fy) subterm(N)
{if subterm starts with a '(', op must be
followed by a space}
| subterm(N-1) op(N,xfx) subterm(N-1)
| subterm(N-1) op(N,xfy) subterm(N)
| subterm(N) op(N,yfx) subterm(N-1)
| subterm(N-1) op(N,xf)
| subterm(N) op(N,yf)
term(1000) --> subterm(999) , subterm(1000)
term(0) --> functor ( arguments )
{provided there is no space between
functor and the '('}
| ( subterm(1200) )
| { subterm(1200) }
| list
| string
| constant
| variable
op(N,T) --> name {where name has been declared as an
operator of type T and precedence N}
arguments --> subterm(999)
| subterm(999) , arguments
list --> []
| [ listexpr ]
listexpr --> subterm(999)
| subterm(999) , listexpr
| subterm(999) '|' subterm(999)
constant --> atom
| number
number --> integer
| float
atom --> name {where name is not a prefix operator}
integer --> natural-number
| - natural-number
float --> unsigned-float
| - unsigned-float
functor --> name
token --> name
| natural-number
| unsigned-float
| variable
| string
| punctuation-char
| space
| comment
| full-stop
name --> quoted-name
| word
| symbol
| solo-char
| [ layout-char... ]
| { layout-char... }
quoted-name --> ' quoted-item... '
quoted-item --> char {other than '}
| ''
word --> small-letter ?alpha...
symbol --> symbol-char...
{except in the case of a full-stop
or where the first 2 chars are '/*' }
natural-number --> digit...
| base ' alphanumeric...
{where each alphanumeric must be less
than base[B; count 'a' as 10, 'b' as 11, etc.}
| zero ' char
{This yields the ASCII equivalent of char}
base --> digit...
{must be in the range 0 ... 36}
zero --> 0
unsigned-float --> simple-float
| simple-float E exponent
simple-float -->
digit... decimal-point digit...
decimal-point --> .
E --> E
| e
exponent --> digit...
| - digit...
| + digit...
variable --> underline ?alpha...
variable --> capital-letter ?alpha..
string --> " ?string-item... "
string-item --> char {other than "}
| ""
space --> layout-char...
comment --> /* ?char... */
{where ?char... must not contain '*/' }
| % rest-of-line
rest-of-line --> newline
| ?not-end-of-line... newline
not-end-of-line --> {any character except newline}
newline --> {ASCII code 10}
full-stop --> . layout-char
char --> layout-char
| alpha
| symbol-char
| solo-char
| punctuation-char
| quote-char
layout-char --> {ASCII codes 1..32 and 127 --
includes space, tab, newline, and del}
alpha --> alphanumeric
| underline
alphanumeric --> letter
| digit
letter --> capital-letter
| small-letter
capital-letter --> A | B | C | D | E | F | G | H | I | J
| K | L | M | N | O | P | Q | R
| S | T | U | V | W | X | Y | Z
small-letter --> a | b | c | d | e | f | g | h | i | j
| k | l | m | n | o | p | q | r
| s | t | u | v | w | x | y | z
digit --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
symbol-char --> + | - | * | / | \ | ^ | < | >
| = | ` | ~ | : | . | ? | @ | # | $ | &
solo-char --> ; | !
punctuation-char --> () | [] | {} | , | | | %
quote-char --> ' | "
underline --> _
X, Y
denotes the term
','(X, Y)
in standard syntax.
(X)
denotes simply the term X.
{X}
denotes the term
'{}'(X)
in standard syntax.
""""
represents a string of one double quote character only. Similarly, for the single quote character within a quoted atom,
''''
represents an atom whose printed representation is one single quote character.
Detailed information is found in the reference pages for the following:
current_op/3 op/3
contact:
product support
sales information