Seed7 
 FAQ 
 Manual 
 Screenshots 
 Examples 
 Algorithms 
 Download 
 Links 

 Manual 
 Introduction 
 Tutorial 
 Syntax 
 Statements 
 Types 
 Parameters 
 Objects 
 File System 
 Declarations 
 Tokens 
 Expressions 
 OS access 
 Actions 
 Errors 

3. SYNTAX

A syntax declaration defines the way a usage of a statement or operator must be written. For example a call of the 'not' operator looks like:

    not okay

To describe the syntax of the 'not' operator we write:

    $ syntax expr: .not.() is <- 13;

This means that a 'not' expression is constructed with the symbol 'not' followed by a parameter. The place of the parameter is marked with the () sign. The syntax description contains no information about the types of the parameters. At the syntax level a parameter may be anything. With '<-' the associativity of the 'not' operator is specified as right associative. This means that the right operand is allowed to have the same priority as the operator symbol. So the expression

    not not okay

is legal and means

    not (not okay)

When the associativity of the 'not' operator is specified with '->' instead of '<-' the 'not not' expression above is not legal. With 13 the priority of the whole 'not' operator is determined. As convention priorities from 1 to 20 are used by operators and priority 25 is used by statements. Arithmetic operators have priorities from 1 to 11 and comparisons have priority 12.

To define the 'not' operator completely there must be also a semantic definition which is as follows:

    const func boolean: not (in boolean: aBool) is func
      result
        var boolean: result is FALSE;
      begin
        if aBool then
          result := FALSE;
        else
          result := TRUE;
        end if;
      end func;

In the declaration the 'not' operator is written exactly in the same way it is written when it is called. The syntax definition is used at both places: declaration and call. The syntax and semantic declarations define precisely how the 'not' operator works.

As next example we try an infix operator like the 'and' operator. A call of the 'and' operator may look like:

    okay and not error

To describe the syntax of the 'and' operator we write:

    $ syntax expr: ().and.() is     -> 14;

This means that an 'and' expression is constructed with the symbol 'and' surrounded by parameters. The '->' defines the 'and' operator as left associative. This means that an expression like

    A and B and C

is interpreted as

    (A and B) and C

With 14 the priority of the whole 'and' operator is determined. Since priority 14 is weaker than the priority of the 'not' operator which is 13 the example expression is evaluated as:

    okay and (not error)

Note that the expression

    okay and not error

makes no sense when the 'and' operator has priority 12 instead of 14.

As next let's try the syntax declaration of a statement. For example a call of the while-statement looks like:

    while element_index > 0 and okay do
      processElement;
      write(".");
    end while;

To describe the syntax of the while-statement we write:

    $ syntax expr: while.().do.().end.while is -> 25;

This means that the while-statement is an expression with the symbols 'while', 'do', 'end' and 'while'. With '->' the associativity of the while-statement is specified as left associative. The associativity has no meaning for the while-statement since there is no parameter before the first symbol or after the last symbol. With 25 the priority of the whole while-statement is determined.

The semantic definition of the while-statement is as follows:

    const proc: while (ref func boolean: condition) do
        (ref proc: statement) end while is func
      begin
        if condition then
          statement;
          while condition do
            statement;
          end while;
        end if;
      end func;

The syntax definition is used at the declaration and at the call. This declaration defines precisely how the while-statement works. It is based on the if-statement and uses recursion to emulate the repetition of the loop body. Another example for a syntax description is the repeat-statement

    repeat
      processElement;
      write(".");
    until element_index = 0 or not okay;

which has the following syntax description:

    $ syntax expr: repeat.().until.() is -> 25;

This means that the repeat-statement is an expression with the symbols 'repeat' and 'until' and a parameter between 'repeat' and 'until' and after 'until'. With 25 the priority of the whole repeat-statement is determined. With '->' the associativity of the repeat-statement is specified as left associative. This allows priorities from 0 to 24 for the parameter after 'until'. Since statements have priority 25 it is not possible to write a statement direct behind 'until'.

As next let's take a more complex statement: The if-statement. A usage of the if-statement might be:

    if okay then
      writeln("okay");
    else
      writeln("not okay");
    end if;

As syntax description we use

    $ syntax expr: .if.().then.().end.if is            -> 25;
    $ syntax expr: .if.().then.().else.().end.if is    -> 25;

Note that this description allows if-statements with and without else-parts. As semantic description we use

    const proc: if (in boolean: condition) then
                  (in proc: statement)
                end if is func
      begin
        case condition of
          when {TRUE}: statement;
        end case;
      end func;

    const proc: if (in boolean: condition) then
                  (in proc: statement1)
                else
                  (in proc: statement2)
                end if is func
      begin
        case condition of
          when {TRUE}:  statement1;
          when {FALSE}: statement2;
        end case;
      end func;

We define the two forms of the if statement based on the case statement. A more complex if-statement can be:

    if number < 0 then
      write("less");
    elsif number = 0 then
      write("equal");
    else
      write("greater");
    end if;

Here we use a more complex syntax description:

    $ syntax expr: .if.().then.().end.if is            -> 25;
    $ syntax expr: .if.().then.().().end.if is         -> 25;
    $ syntax expr: .elsif.().then.() is                <- 60;
    $ syntax expr: .elsif.().then.().() is             <- 60;
    $ syntax expr: .else.() is                         <- 60;

Note that the second line of syntax description is different to the syntax description of the previous example. The 'else' is taken out to form an expression of its own.