This is still a draft and is only provided as information. Though this document is still missing some formatting and examples, it can be used to get a precise idea as to how indentation and carriage returns are handled in Acceleo.

Text production rules will apply to all body elements. Each body element can be either stand alone or embedded within other body elements. It will be easier to understand text production rules by splitting these body elements in five main categories : expressions, static text, comments, template invocation and blocks.

"Blocks" include template, for, if, let, protected area, file, trace and macro blocks. A block will be considered "stand-alone" if it is either one of:

Any block that does not fall into these categories will be considered an "embedded" block.

Examples

Stand-alone single-line blocks

Nothing relevant for generation between the line start and the block head, nothing relevant between the block tail and the line end; both head and tail on the same line. All of the following are in this category.

[for (Sequence{false, false, false})][self/][/for]

[if (true)]output[/if]

[/if] [comment .../]  [if (true)]output[/if]

[/if]         [if (true)]output[/if]

Embedded single-line blocks

Head and tail of the block are on the same line, but there is something relevant to the generation other than the block on that same line.

Some text[for (Sequence{false, false, false})]output[/for]

[if (true)]output[/if] and some text

[for (Sequence{false, false, false})]   [self/][/for] and some text.

Stand-alone multi-line blocks

Nothing relevant for generation between the line start and the block head, nothing relevant between the block tail and the line end; head and tail on different lines.

          [for (Sequence{false, false, false})]
              [self/]
          [/for]
        
          [if (true)]output
          [/if]
        
          [if (true)]
              output[/if]          
        
          [comment]Generate booleans [/comment][for (Sequence{false, false, false})]
              [self/][/for]
        
          [for (Sequence{false, false, false})]
              [self/]
          [/for]
        

Embedded multi-line blocks

Head and tail of the block are on different lines, but there is something relevant to the generation other than the block on that same line.

          text[for (Sequence{false, false, false})]
              [self/]
          [/for]
        
          [if (true)]
              output[/if] text
        

Block Body

Single-line block

Body starts after the closing bracket of the block head and ends before the starting bracket of the block tail.

Multi-line block

If the closing bracket of the block head is directly followed by a new line, the block's body starts at the beginning of the next line after the block head. Otherwise the block's body starts after the closing bracket of its head. The body ends before the starting bracket of the block tail, be it directly preceded by a new line or not.

Special handling of "Template" blocks

If the last characters preceding the starting bracket of the block tail is a new line followed by optional white spaces, the template body ends before the last new line character preceding its tail.

Static Text

We need to define the concept of line relevance to properly identify these boundaries. For this purpose, we will describe as "white spaces" the white space characters contained in a static text, whatever their position in the text.

A line is considered "relevant" if it contains anything else than white spaces, block head, block tail and comment. Note, however, that lines consisting of white spaces only are also considered relevant.

Considering the boundaries outlined in section Identifying Body Element Boundaries above, the text production rules stand as follows:

In the following examples, invisible characters have been materialized:

· indicates a space character
↪ indicates a horizontal tab character
¶ indicates a carriage return

Embedded blocks

Example 1

The Acceleo code:

Some · text · [for · (Sequence{false, · false, · false}) · separator · (' · - · ')]output[/for]

produces the following result:

Some · text · output · - · output · - · output

Example 2

The Acceleo code:

[if · (true)]output[/if] · and · some · text

produces:

output · and · some · text

Example 3

The Acceleo code:

↪ [for · (Sequence{false, · false})] · [self/][/for] · and · some · text

produces:

↪ · false · false · and · some · text

Example 4

The Acceleo code:

text[for · (Sequence{false, · false})] ¶

↪ [self/] ¶

[/for]text

produces:

text ↪ false ¶

↪ false ¶

text


Example 5

The Acceleo code:

text[for · (Sequence{false, · false})] ¶

↪ output[/for]text

produces:

text ↪ output ↪ outputtext ¶

Stand alone single-line blocks

Example 1

The Acceleo code:

[for · (Sequence{false, · false, · false})][self/][/for]

produces:

falsefalsefalse

Example 2

The Acceleo code:

[if · (true)]output[/if]

produces:

output

Example 3

The Acceleo code:

↪ [for · (Sequence{false, · false, · false})][self/][/for]

produces:

↪ falsefalsefalse

Example 4

The Acceleo code:

[/if] ↪ ↪ [if · (true)]output[/if]

produces:

↪ ↪ output

Example 5

The Acceleo code:

[/if] · [comment .../] ↪ [if · (true)]output[/if]

produces:

· ↪ output

Stand alone multi-line blocks

Example 1

The Acceleo code:

[for · (Sequence{false, · false, · false})] ¶

↪ [self/] ¶

[/for]

produces:

↪ false ¶

↪ false ¶

↪ false ¶


Example 2

The Acceleo code:

[if · (false)]output ¶

[/if]

produces nothing, neither whitespace nor empty line.


Example 3

The Acceleo code:

[if · (true)] ¶

↪ output[/if]

produces:

↪ output

Example 4

The Acceleo code:

[comment]for · loop[/comment][for · (Sequence{false, · false})] ¶

↪ [if · (self)] ¶

↪ ↪ [self/] ¶

↪ [/if] ¶

[/for]

produces nothing, neither whitespace nor empty line.


Example 5

The Acceleo code:

↪ [for · (Sequence{false, · false, · false})] ¶

[self/] ¶

↪ [/for] ¶

produces:

false ¶

false ¶

false ¶