Previous Up Next

A.3  Formal definition of clause syntax

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                  ::=     :-
                         |      ?-

A.3.1  Comments

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.

A.3.2  Operators

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

A.3.3  Operator Ambiguities

Unlike the canonical syntax, operator syntax can lead to ambiguities.


1
Quotes, on the other hand, are used to build atoms from characters with different or mixed character classes; they do not change the precedence of operators.

Previous Up Next