### 5.1 Lexical Structure ¶

#### Whitespace and Comments ¶

Comments are semantically equivalent to whitespace and can be used anyplace that whitespace is (with one exception in multi-line strings, as described below).

There are two kinds of comments: hash comments, that begin with a ‘`#`’ character that is not contained within a string and continue until the next newline, and C-style or bracketed comments, that are delimited by ‘`/*`’ and ‘`*/`’ tokens. The bracketed comments may span multiple lines. E.g.:

    if size :over 100K
      { # this is a comment
        discard;
      }

    if size :over 100K
      { /* this is a comment
           this is still a comment */ discard /* this is a comment again
         */ ;
      }

Like in C, bracketed comments do not nest.

#### Lexical Tokens ¶

The basic lexical entities are identifiers and literals.

An identifier is a sequence of letters, digits and underscores, that begins with a letter or underscore. For example, `header` and `check_822_again` are valid identifiers, whereas `1st` is not. A special form of identifier is tag: it is an identifier prefixed with a colon (‘`:`’), e.g.: `:comparator`.

A literal is a data that is not executed, merely evaluated “as is”, to be used as arguments to commands. There are four kinds of literals:

- Number

  Numbers are given as ordinary unsigned decimal numbers. An optional suffix may be used to indicate a multiple of a power of two. The suffixes are: ‘`K`’ specifying “kibi-”, or 1,024 (2^10) times the value of the number; ‘`M`’ specifying “mebi-”, or 1,048,576 (2^20) times the value of the number; and ‘`G`’ specifying “tebi-”, or 1,073,741,824 (2^30) times the value of the number.

  The numbers have 32 bits of magnitude.

- String A string is any sequence of characters enclosed in double quotes (‘`"`’). A string cannot contain newlines and double quote characters. This limitation will disappear in future releases.
- Multiline Strings A multiline string is used to represent large blocks of text with embedded newlines and special characters. It starts with the keyword `text:` followed by a newline and ends with a dot (‘`.`’) on a newline by itself. Any characters between these two markers are taken verbatim. For example:

      text:
      ** This is an automatic response from my message **
      ** filtering program.                            **

      I can not attend your message right now.  However it
      will be saved, and I will read it as soon as I am back.

      Regards,
      Fred
      .

  Notice that a hashed comment or whitespace may occur between `text:` and the newline. However, when used inside the multiline string a hash sign looses its special meaning (except in one case, see below) and is taken as is, as well as bracketed comment delimiters. In other words, no comments are allowed within a multiline string. E.g.:

      text: # This is a comment

      Sample text
      # This line is taken verbatim
      /* And this line too */
      .

  The only exception to this rule is that preprocessor `include` statement is expanded as usual when found within a multiline string (see Preprocessor), e.g.:

      text:
      #include <myresponse.txt>
      .

  This results in the contents of file `myresponse.txt` being read and interpreted as the contents of the multiline string.

  GNU libmu_sieve extends the described syntax as follows. If the keyword `text:` is immediately followed by a dash (‘`-`’), then all leading tab characters are stripped from input lines and the line containing delimiter (‘`.`’). This allows multiline strings within scripts to be indented in a natural fashion.

  Furthermore, if the `text:` (optionally followed by ‘`-`’) is immediately followed by a word, this word will be used as ending delimiter of multiline string instead of the default dot. For example:

      if header "from" "me@example.com"
        {
          reject text:-EOT
              I do not accept messages from
              this address.
              .
              .
              EOT
           # Notice that this the multiline string ends here.
           # The single dots above will be part of it.
          ;
        }

- String Lists

  A string list is a comma-delimited list of quoted strings, enclosed in a pair of square brackets, e.g.:

      ["me@example.com", "me00@landru.example.edu"]

  For convenience, in any context where a list of strings is appropriate, a single string is allowed without being a member of a list: it is equivalent to a list with a single member. For example, the following two statements are equivalent:

      exists "To";
      exists ["To"];