
EBNF
====

Program
-------

The template language starts with the non-terminal token: "Program".

::

  Program             ::= Version NewLine Code EOF

  Version             ::= '{?' 'ezt' 'version' '=' '"' FloatLiteral '"' '}'

  Code                ::= ( Text | Block )*

  Text                ::= TextBlock
                      |   LiteralBlock
                      |   DelimiterBlock


  Block               ::= CommentBlock 
                      |   DeclarationBlock
                      |   ModifyingBlock
                      |   OutputBlock
                      |   LiteralBlock
                      |   CycleBlock
                      |   LoopBlock
                      |   CodeFlowBlock
                      |   CustomBlock

Text blocks
-----------
::

  TextBlock           ::= ( ~'{' | '\'! '{' )*

  LiteralBlock        ::= '{' 'literal' '}' Graphic* '{' '/literal' '}'

  DelimiterBlock      :==  '{ldelim}' | '{rdelim}'


Blocks
------
::

  CommentBlock        ::= '{*' Graphic* '*}'

  DeclarationBlock    ::= '{' 'var' SubDefineBlock '}'
                      |   '{' 'cycle' SubDefineBlock '}' 
                      |   '{' 'use' SubDefineBlock '}'

  SubDefineBlock      ::= PrimaryVariable ( '=' Expression )? ( ',' SubDefineBlock )?

  ModifyingBlock      ::= '{' SubAssignBlock (',' SubAssignBlock)* '}'

  SubAssignBlock      ::= AssignmentExpr | IncrementExpr | DecrementExpr

  AssignmentExpr      ::= PrimaryVariable ( '=' | CombinedAssignment) Expression

  IncrementExpr       ::= ( ( '++' PrimaryVariable ) | ( PrimaryVariable '++' ) )

  DecrementExpr       ::= ( ( '--' PrimaryVariable ) | ( PrimaryVariable '--' ) )

  OutputBlock         ::= '{' Expression '}'

  CycleBlock          ::= '{' 'increment' PrimaryVariable ( ',' PrimaryVariable )* '}'
                      |   '{' 'decrement' PrimaryVariable ( ',' PrimaryVariable )* '}'
                      |   '{' 'reset' PrimaryVariable ( ',' PrimaryVariable )* '}'


Loop control
------------
::

  LoopBlock           ::= ForeachStatement
                      |   WhileStatement

  ForeachStatement    ::= '{' 'foreach' Expression 'as' PrimaryVariable ('=>' PrimaryVariable)? (Cycle)* (OffsetAndLimit)? '}' Code '{' '/foreach' '}'

  WhileStatement      ::= '{' 'while' Expression '}' Code '{' '/while' '}'

  Cycle               ::= ('increment' | 'decrement') PrimaryVariable (',' PrimaryVariable)* 

  OffsetAndLimit      ::= ('offset' Expression)? ('limit' Expression)?


Code flow control
-----------------
::

  CodeFlowBlock       ::= IfStatement
                      |   SwitchStatement
                      |   IncludeStatement
                      |   DelimiterStatement
                      |   '{break}'
                      |   '{skip}'
                      |   '{continue}'
                      |   ReturnStatement


  IfStatement         ::= '{' 'if' Expression '}' Code (ElseIf)* (Else)? '{' '/if' '}' 
  ElseIf              ::= '{' 'elseif' Expression '}' Code
  Else                ::= '{' 'else' '}' Code 

  SwitchStatement     ::= '{' 'switch' Expression '}' (Case)* (DefaultCase)? '{' '/switch' '}'

  Case                ::= '{' 'case' Literal ( ',' Literal)* '}' Code '{' '/case' '}'

  DefaultCase         ::= '{' 'default' '}' Code '{' '/default' '}'
                     
  IncludeStatement    ::= '{' 'include' Expression ('send' ExprAsPrimVarList)? ('receive' PrimVarAsPrimVarList)? '}'

  DelimiterStatement  ::= '{' 'delimiter' (modulo Expression ('is' Expression)? )? '}' Code '{' '/delimiter' '}'

  ReturnStatement     ::= '{' 'return' ExprAsPrimVarList '}' 

  ExprAsPrimVarList   ::=  ( Expression 'as' PrimaryVariable | PrimaryVariable ) (',' ExprAsPrimVarList)?

  PrimVarAsPrimVarList::=  PrimaryVariable ('as' PrimaryVariable)? (',' PrimVarAsPrimVarList)?


Custom block
------------
::

  CustomBlock         ::= '{' Identifier ( Expression )? ( CustomArgument )*  '}' (Code '{' '/'Identifier '}')?  

  CustomArgument      ::= Identifier ( ('=')? Expression)? 


Expression
----------
::

  Expression          ::= PreUnaryExpression (BinaryOperator Expression)?

  PreUnaryExpression  ::= '++' PrimaryVariable
                      |   '--' PrimaryVariable
                      |   UnaryExpression
                      |   Expression 'instanceof' Identifier 
                      |   ArrayDeclaration

  ArrayDeclaration    ::= 'array' '(' ( (Expression '=>')? Expression ( ',' Expression )* (',')? )? ')'
                      |   Expression '..' Expression


  UnaryExpression     ::= ( UnaryOperator )* PostFixExpression

  PostFixExpression   ::= PrimaryVariable ( '++' | '--' )?
                      |   Literal
                      |   FunctionCall
                      |   '(' Expression ')'


  PrimaryVariable     ::= '$' Identifier ( '[' Expression ']' | '->' Expression )*

  FunctionCall        ::= Identifier '(' (ParameterList)? ')'  
                                                                  
  ParameterList       ::= Expression ( ',' Expression )* 

  Identifier          ::= Letter ( Letter | Digit | '_' )*


Basic literals
--------------
::

  Literal              ::= NumeralLiteral 
                       |   StringLiteral 
                       |   BooleanLiteral
                       |   NullLiteral

  NumeralLiteral       ::=  HexLiteral | OctLiteral | FloatLiteral

  HexLiteral           ::= '0x' HexDigit+

  OctLiteral           ::= '0' OctDigit+

  FloatLiteral         ::= NonZeroDigit Digit* ( '.' Digit+ )? (('e'|'E') ('+'|'-')? Digit+)?

  StringLiteral        ::= '"' Graphic* '"' 
                       |   "'" Graphic* "'"

  BooleanLiteral       ::= 'true'
                       |   'false'

  NullLiteral          ::= 'null'


Lexicon
-------
::

  Comment             ::= '//' Graphic* ( EOL | '}' )
                      |   '/*' Graphic* '*/'

  Graphic             ::= Digit | Letter | Blank | Operators | Assignment | CombinedAssignment | RemainingCharSet

  EOL                 ::= end-of-line

  EOF                 ::= end-of-file

  Blank               ::= Tab | Space 

  NewLine             ::= '\n'

  Space               ::= ' '

  Tab                 ::= '\t'

  Letter              ::= 'a' ... 'z' | 'A' ... 'Z'  

  Hexdigit            ::= '0' .. '9' | 'A' .. 'F'

  Octdigit            ::= '0' .. '8'

  NonZeroDigit        ::= '1' .. '9' 

  Digit               ::= '0' | NonZeroDigit

  Assignment          ::= '='

  CombinedAssignment  ::= '+=' | '-='  | '*=' | '/=' | '%=' | '.=' 

  Operators           ::= BinaryOperator | UnaryOperator | '++' | '--'

  BinaryOperator      ::= ArithmeticOperator | ComparisonOperator | BooleanOperator | StringOperator

  ArithmeticOperator  ::= '+'  | '-'   | '*' | '/' | '%' 

  ComparisonOperator  ::= '==' | '===' | '!=' | '!==' | '<' | '<=' | '>' | '>=' 

  BooleanOperator     ::= '&&' | '||'

  StringOperator      ::= '.'  | '.='

  UnaryOperator       ::= '+'  | '-'   | '!'

  RemainingCharSet    ::= '.' | ':' | ';' | ',' | '~' | '(' | ')' | '[' | ']' | '{' | '}' | '_' | '|' | "'" | '"' | '`' | '#' | '$' | '@'




Examples
========

Text
----

Normal text output
^^^^^^^^^^^^^^^^^^

The next example writes "hello world"::

  {?ezt version="1.0" }

  Hello world


Using ldelim and rdelim
^^^^^^^^^^^^^^^^^^^^^^^

Template::

  {?ezt version="1.0" }
  
  {ldelim}?ezt version="1.0"{rdelim}

writes {?ezt version="1.0"} to the output.


Comments
--------

Block comments
^^^^^^^^^^^^^^
The following template::

  {?ezt version="1.0"}

  {* Hello *} world

will only output "world".
  

Inline comments
^^^^^^^^^^^^^^^
::

  { // Hello } world
  { // Hello 
  } earth

outputs::

  world
  earth
  

c-comment
^^^^^^^^^
::

  { /* Hello */ "world" }

outputs::

  world


Foreach
-------


Foreach-ing over an array
^^^^^^^^^^^^^^^^^^^^^^^^^
::

  {var $colors = array( "red" => "#FF0000", "green" => "#00FF00" )}

  {foreach $colors as $name => $value}
    <font color="{$value}">$name</font>
  {/foreach}


Counting from 1 to 10
^^^^^^^^^^^^^^^^^^^^^
Using a function::

  {foreach array_range(1, 10) as $value}
      Iteration number: {$value} 
  {/foreach}


Or the short notation::

  {foreach 1..10 as $value}
      Iteration number: {$value} 
  {/foreach}


Using the cycle
^^^^^^^^^^^^^^^
::

  {* Declaring the $blackAndWhite cycle *}
  {cycle $blackAndWhite = array( '#00000', '#FFFFFF' )}

  {foreach 1..10 as $value increment $blackAndWhite}
      <font color="{$blackAndWhite}">Numbers: {$value}</font>
  {/foreach}


Using offset and limit
^^^^^^^^^^^^^^^^^^^^^^
::

  {var $hugeArray = 1..1000

  {*show number 50 to 100 *}
  {foreach $hugeArray as $value offset 50 limit 50}
    My favourite numbers are: {$value}
  {/foreach}



While
-----


Counting from 1 to 10
^^^^^^^^^^^^^^^^^^^^^
::

  {var $i = 0}
  {while $i <= 10}
    Number: {$i}
    {$i++}
  {/while}


Using the cycle
^^^^^^^^^^^^^^^
For the while loop, you have to do the cycling yourself. Note that the 
while loop is used rarely.

::

  {var $i = 0}
  {cycle $oddOrEven = array("odd", "even")}

  {while $i <= 10}
    Number {$i} is {$oddOrEven}
    
    {increment $oddOrEven}
    {$i++}
  {/while}


If
--
::

  {var $i = 10}
  {if $i % 2 == 0}
    The number is even.
  {elseif $i % 2 == 1}
    The number is odd.
  {else}
    The number is neither odd nor even. Which is a tiny bit strange.
  {/if}


Switch
------
::

  {var $number = 4}

  {switch $number}
      {case 1}
          One
      {/case}
      {case 2}
          Two
      {/case}
      {case 3,4,5}
          Three, Four, or Five 
      {/case}
      {default}
          Any number except 1 to 5.
      {/default}
  {/switch}



Properties
----------

Use
^^^
The nodes: $node and $optionalNode come from the application, and need therefore be known in the template code.
If the $optionalNode is not set, it will get the default value "false"::

  {use $node, $optionalNode = false}


Accessing a property
^^^^^^^^^^^^^^^^^^^^
::

  {use $node, $optionalNode = false}

  Impressive title: {$node->impressiveTitle}

  Norwegian title: {$node->titles["norwegian"]}

  {if $optionalNode != false}
    Extra title: {$optionalNode->titles["norwegian"]}
  {/if}


Dynamic names
^^^^^^^^^^^^^
::

  {use $node}

  {$property = "impressive" . "Title"}

  Impressive title: {$node->$property}



Delimiter
---------
::

  {var $columns = 4}
  <table>
  <tr>
  {foreach 1..12 as $nr}
    <td>{$nr}</td>
  
    {delimiter modulo $columns /* is 0 */ }
      </tr><tr>
    {/delimiter}
  
  {/foreach}
  </tr>


Including templates
-------------------
::

  {use $currentNode}
  
  {* Call the template with the variable $node that contains the value $currentNode *} 
  {include 'showAndAlterNode.tpl'
  	send     $currentNode as $node
  	receive  $node as $alteredNode}
  {* The template returns a $node, but we rename it to $alteredNode *} 
  
  
  {* Rename the $alteredNode to $currentNode *}
  {return $alteredNode as $currentNode}


..
   Local Variables:
   mode: rst
   fill-column: 79
   End:
   vim: et syn=rst tw=79
