Lexical structure
Before anything is evaluated, the parser in lib/eztemplate/classes/eztemplatemultipassparser.php cuts the template
into pieces in three passes: text elements and tags (parseIntoTextElements()), whitespace removal around tags
(parseWhitespaceRemoval()), and the node tree (parseIntoTree()). This page describes the first two, which decide
what is text, what is a tag and which newlines reach the output.
Contents
- Delimiters
- Kinds of tags
- Comments
- Literal text, ldelim and rdelim
- A brace inside a tag
- Whitespace around tags
- Single tags with a slash
- Parser errors: line and column
- Unknown function tags
- Related pages
Delimiters
A tag starts at { and ends at the next }. The delimiters are set in the constructor of eZTemplate
($this->LDelim = "{", $this->RDelim = "}"); there is no setting to change them.
Kinds of tags
The parser looks at the first characters inside the braces:
| The tag starts with | It is | Example |
|---|---|---|
$ | an output tag: a variable, possibly with attributes and operators | {$node.name|wash} |
' or " | an output tag with a string | {'text'|upcase} |
a digit, or - and a digit | an output tag with a number | {42}, {-7} |
lowercase letters, digits, _ or - followed by ( | an output tag with an operator call | {concat( 'a', 'b' )} |
* | a comment, up to *} | {* note *} |
/ | an end tag | {/if} |
| anything else | a function tag; it is a single tag when it ends with / | {if ...}, {include ... /} |
Every kind in one template:
def $who = 'world'
text | $who | 'literal string' | {42} | $who|upcase | concat( 'a', 'b' ) | if true()block/ifOutput:
text | world | literal string | 42 | WORLD | ab | blockComments
{* ... *} may span lines. The comment itself is dropped, but the text around it is untouched: the newlines before
and after a comment stay, unlike those around function tags.
line 1
{* a comment
over two lines *}
line 3 {* inline *} still line 3Output:
line 1
line 3 still line 3Literal text, ldelim and rdelim
{literal} is registered as a literal tag (registerLiteral( 'literal' ) in the constructor). Everything up to
{/literal} is plain text, braces included. {ldelim} and {rdelim} (eZTemplateDelimitFunction) print a single
brace. Both are shown in the differences page, which
also shows what an unprotected CSS rule does to a template.
A brace inside a tag
The tag ends at the first } that is not preceded by a backslash. Inside a tag, \} is a literal brace. Without the
backslash the string is cut, the tag ends early and the rest is printed as text:
['a\}b']
['a}b']Output:
[a}b]
[ab'}]Whitespace around tags
The second pass removes one newline right before a function tag (normal, single or end tag) and one newline
right after it. Text and output tags ({$x}, {'...'}) are not touched. In this template every function tag sits on its
own line, so the newlines around {def}, {if} and {/if} disappear, while those around {$x} stay:
def $x = 'X'
A
if true()
B
/if
C
$x
DOutput:
ABC
X
DOnly one newline is removed on each side. A blank line before or after a function tag therefore still leaves one newline:
A
if true()
B
/if
COutput:
A
B
CSpaces and tabs are never removed. Indentation in front of a function tag stays in the output.
Single tags with a slash
A tag ending in / is a single tag: it has no end tag. Functions with a special syntax (if, elseif, foreach, def, undef, set,
let, default, set-block, append-block, section, while, for) are parsed with their own grammar only in the
normal form. Written with a slash, {set $n = 2 /} goes to the generic parameter parser, which does not accept it, and
the variable keeps its value:
def $n = 1[set $n = 2 /$n]Output:
[1]Logged by the template engine:
ERROR : parser error @ tl-lex/08-single-tag-slash.tpl:1[15]
Invalid parameter characters in function 'set': '$n = 2'Write these functions without the slash. The slash works for functions that take plain name=value parameters, such as
include:
[include uri='file:var/tmp/examples/tl-smarty/parts/greeting.tpl' who='single tag' /]Output:
[<p>Hello, single tag!</p>
]Parser errors: line and column
Parser errors name the template, the line and the column in brackets, then the problem. An unterminated tag:
first line
second {$brokenOutput:
first line
second {$brokenLogged by the template engine:
ERROR : parser error @ tl-lex/06-unterminated-tag.tpl:1[0]
Unterminated tag, needs a } to end the tag.
{$brokenThe text from the broken tag to the end of the file is printed as it is. The position is where the parser was when it gave up, which for an unterminated tag is the start of the text before it; look at the quoted tag after the message.
Unknown function tags
A function tag with a name the engine does not know produces a warning ("Function ... is not registered") and no output. Because a normal tag opens a block, everything up to its end tag, or to the end of the file when there is none, belongs to that block and is lost with it:
[before nosuchfunction param=1 after]Output:
[beforeLogged by the template engine:
WARNING : Function "nosuchfunction" is not registeredA misspelled {fi} or {foreahc ...} therefore swallows the rest of the template. If a page ends early, look for such a
warning in the debug output.
Related pages
- Previous: Moving from .tpl to .stpl
- Next: Values and literals
- TPL syntax basics
- Comments
- Literal and delimiters
- Template debugging
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.