SWI-Prolog 7.1.10 Reference Manual: Section B.3

## B.3 Syntax extensions

Prolog is commonly used to define domain specific languages (DSL) as well as to interact with external languages that have a concrete syntax, such as HTML, JavaScript or SQL. Standard Prolog provides operators (see section 4.25) for extending its syntax. Unfortunately, Prolog's syntax is rather peculiar and operators do not allow for commonly seen syntactical patterns such as array subscripting, expressing attributes, scope or a body using curly brackets, distinguishing identifiers or strings from `functions', etc.

The syntactic extensions described in section B.3.1 provide additional constructs to extend the syntax. These extensions allow for coping with a large part of the curly bracket languages, which allows for defining DSLs that are more natural to use, in particular for people that are less familiar with Prolog.

For some external languages it can be sufficient to support the simple data model using a completely different Prolog concrete syntax. This is for example the case for HTML, as implemented by the library `library(http/html_write)`. With the extensions of section B.3.1, this also becomes true for the statistics language R, which was one of the motivations for these extensions. These extensions are motivated in Wielemaker & Angelopoulos,.

Other languages, such as full JavaScript, are too different from Prolog for dealing with them using (extended) Prolog operator. While most of the JavaScript syntax can be covered with the extended notion of operators, the produced Prolog term does not unambiguishly describe the JavaScript abstract syntax. For example, both `++a` and `a++` are, with the appropriate operator declarations, valid Prolog syntax. However, they both map to the term `++(a)` and thus a Prolog JavaScript serialization does not know which these two forms the generate.126This example comes from Richard O'Keefe. More classical, `"string"` produces the same Prolog term as `[115,116,114,105,110,103]`.

An alternative to syntax extension using (extended) operators are quasi quotations Mainland, 2007. Quasi quotations embed external languages in a Prolog term using their native syntax. The language is specified in the quotation. Parsing such a term causes Prolog to call the associated parser which creates an abstract syntax tree that unambiguosly represents the code fragment and which can be processed in Prolog or serialized for external processing. Quasi quotations are realised by library `library(quasi_quotations)`, which is documented in section A.23.

### B.3.1 Block operators

Introducing curly bracket, array subscripting and empty argument lists is achieved using block operators.127Introducing block operators was proposed by Jose Morales. It was discussed in the Prolog standardization mailing list, but there were too many conflicts with existing extensions (ECLiPSe and B-Prolog) and doubt their need to reach an agreement. Increasing need to get to some solution resulted in what is documented in this section. The atoms `[]`, `{}` and `()` may be declared as an operator, which has the following effect:

[ ]
  This operator is typically declared as a low-priority `yf` postfix operator, which allows for `array[index]` notation. This syntax produces a term `[]([index],array)`.
{ }
  This operator is typically declared as a low-priority `xf` postfix operator, which allows for `head(arg) { body }` notation. This syntax produces a term `{}({body},head(arg))`.
( )
  This operator can only meaningfully be declared as a low-priority `xf` postfix operator, which allows for `name()` notation. This syntax produces a term `'()'(name)`. This transformation only applies if the opening bracket immediately follows the functor name, i.e., following the same rules as for constructing a compound term.

Below is an example that illustrates the representation of a typical `curly bracket language' in Prolog.

    ?- op(1, xf, '()').
    ?- op(100, xf, {}).
    ?- op(100, yf, []).
    ?- op(1100, yf, ;).

    ?- displayq(func(arg)
                { a[10] = 5;
                  update();
                }).
    {}({}(;(=([]('.'(10,[]),a),5),;('()'(update)))),func(arg))