What follows is the specification of the syntax. The terminal symbols are written in UPPER CASE or as the character sequence they consist of.
program ::= clause EOCL | clause EOCL program clause ::= head | head rulech goals | rulech goals head ::= term_h goals ::= term_g | goals , goals | goals ; goals | goals -> goals | goals -> goals ; goals term_h ::= term_h(0) | term(1200) term_g ::= term_g(0) | term(1200) term(0) ::= VAR /* not a term_h */ | attr_var /* not a term_h */ | ATOM | structure | structure_with_fields | subscript | list | STRING /* not a term_h nor a term_g */ | number /* not a term_h nor a term_g */ | bterm term(N) ::= term(0) | prefix_expression(N) | infix_expression(N) | postfix_expression(N) prefix_expression(N) ::= fx(N) term(N-1) | fy(N) term(N) | fxx(N) term(N-1) term(N-1) | fxy(N) term(N-1) term(N)
infix_expression(N) ::= term(N-1) xfx(N) term(N-1) | term(N) yfx(N) term(N-1) | term(N-1) xfy(N) term(N) postfix_expression(N) ::= term(N-1) xf(N) | term(N) yf(N) attr_var ::= VAR { attributes } /* Note: no space before { */ attributes ::= attribute | attribute , attributes attribute ::= qualified_attribute | nonqualified_attribute qualified_attribute ::= ATOM : nonqualified_attribute nonqualified_attribute ::= term_a structure ::= functor ( termlist ) /* Note: no space before ( */ structure_with_fields ::= functor { termlist } | functor { } /* Note: no space before { */ subscript ::= structure list | VAR list /* Note: no space before list */ termlist ::= term_a | term_a , termlist list ::= [ listexpr ] | .(term_a, term_a) listexpr ::= term_a | term_a | term_a | term_a , listexpr term_a ::= term(1200) /* Note: it depends on syntax_options */
number ::= INT | INTBAS | INTCHAR | RAT | FLOAT | BREAL bterm ::= ( clause ) | { clause } functor ::= ATOM /* arity > 0 */ rulech ::= :- | ?-
There are two types of comments: bracketed comments, which are enclosed by CM1-CM2 and CM2-CM1, and the end-of-line comment, which is enclosed by CM and NL. Both types of comment behave as separators. When the syntax option nested_comments is on (the default is off), bracketed comments can be nested.
In Prolog, the user is able to modify the syntax dynamically by explicitly declaring new operators. The built-in op/3 performs this task. As in Edinburgh Prolog, a lower precedence value means that the operator binds more strongly (1 strongest, 1200 weakest).
Any atom (whether symbolic, alphanumeric, or quoted) can be declared as an operator. Once an operator has been declared, the parser will accept the corresponding operator notation, and certain output built-ins will produce the operator notation if possible. There are three classes of operators: prefix, infix and postfix.
An operator can belong to more than one class, e.g., the plus sign is both a prefix and an infix operator at the same time.
In the associativity specification of an operator (e.g., fx, yfx), x represents an argument whose precedence must be lower than that of the operator. y represents an argument whose precedence must be lower or equal to that of the operator. y should be used if one wants to allow chaining of operators (i.e., if one wants them to be associative). The position of the y will determine the grouping within a chain of operators. For example:
Example declaration will allow to stand for --------------------------------------------------------------- :- op(500,xfx,in). A in B in(A,B) :- op(500,xfy,in). A in B in C in(A,in(B,C)) :- op(500,yfx,in). A in B in C in(in(A,B),C) :- op(500,fx ,pre). pre A pre(A) :- op(500,fy ,pre). pre pre A pre(pre(A)) :- op(500, xf,post). A post post(A) :- op(500, yf,post). A post post post(post(A)) :- op(500,fxx,bin). bin A B bin(A,B) :- op(500,fxy,bin). bin A bin B C bin(A,bin(B,C))
Operator declarations are usually local to a module, but they can be exported and imported. The operator visible in a module is either the local one (if any), an imported one, or a predefined one. Some operators are pre-defined (see Appendix B on page ??). They may be locally redefined if desired.
Note that parentheses are used to build expressions with precedence zero and thus to override operator declarations.1
Unlike the canonical syntax, operator syntax can lead to ambiguities.