use Template::Parser; my $parser = Template::Parser->new(); my $result = $parser->parse_template( $text ) || die $parser->error();
The parser's role is to parse the input text of a template and generate a compiled form, which in the general case will be a a Perl code equivalent of the template. However, the code generation is performed by a separate Template::Compiler backend module and this can be subclassed and registered for use with a parser to generate different compiled forms such as a parse tree or some other intermediate code representation.
The template is first split into plain text and embedded
directives according to the START_TAG and END_TAG definitions
in effect. The INTERPOLATE flag also determines if the parser
should attempt to resolve variable reference in plain text.
At this stage, chomping is also performing according to the
PRE_CHOMP and POST_CHOMP flags and also any directive markers,
e.g. [% blah -%]
The parser maintains a stack of hash arrays which contain the
current configuration details for the current lexical parser
scope, e.g. START_TAG, END_TAG, INTERPOLATE, POST_CHOMP, etc.
The new_scope()
can be used to create a new
local parser scope in which these options can be changed. It
accepts a list or reference to hash array of configuration
parameters which are used to modify the new scope
configuration. Any values not explicitly set default to the
values of the parent content. The
old_scope()
method can be used to restore
the previous scope and hence, parser configuration. In
summary, this allows different parser options to be locally
scoped within template blocks,
e.g.
[% PARSER interpolate = 0 %] The $animal sat on the $place [% END %] [% BLOCK foo PARSER interpolate = 0 %] The $animal sat on the $place [% END %]
The parser also maintains a stack of HANDLERS, implemented as
Template::Parser::Handler objects. The top
item receives method calls from the parser as it identifies
these different elements within the template, e.g. directive()
and text()
.
The new_handler($handler)
and old_handler()
methods can be used to
install and later remove parser handlers.
The handler is responsible for dispatching a directive to the
correct facility parser registered to parse it. For example,
the directive might be [% INCLUDE foo %]
, and
the handler identifies this as an INCLUDE
directive for which is has a callback defined. It calls the
facility parser passing a reference to the main parser object
and passing the remaining directive text. This should return
a compiled representation of the template which the handler
appends to its current content model. The handler also
receives notification of text blocks which are also added to
the internal content list.
The facility parser registered to parse a particular directive
can make calls back against the main parser to parse common
elements of the Template Toolkit language. For example, the
INCLUDE
directive expects one or more names
and then a list of arguments.
sub parse_include { my ($self, $parser, $text) = @_; my ($names, $args); # must provide one (or more) template names defined ($names = $parser->parse_names(\$text)) || return $self->error("INCLUDE expects one or more names"); # args are optional $args = $parser->parse_args(\$text); . . . return $some_perl_code; }
use Template::Parser; $Template::Parser::TAG_STYLE->{ mystyle } => [ '\[--', '--\]' ];
[% TAGS mystyle %] [-- INCLUDE header --]
print $Template::Parser::DEFAULT_STYLE->{ INTERPOLATE }; # 0
new( \%vars )
Constructor method implemented by Template::Base.
use Template::Parser; my $parser = Template::Parser->new({ INTERPOLATE => 1, });
init( \%config )
Initialiser method called by base class new() constructor method.
new_scope( \%config )
new_scope( key => value, key => value, ... )
Create a new configuration for a localised parser scope.
Parser configuration items (e.g. POST_CHOMP
,
INTERPOLATE
, etc) can be passed as reference
to a hash array or list of key => value
pairs.
$parser->new_scope( POST_CHOMP => 1 );
current_scope()
Returns a reference to a hash array representing the configuration within
the current parser scope.
$scope = $parser->current_scope();
old_scope()
Restores the configuration of the parent scope, masked by a
previous call to new_scope()
.
push_scope( $scope )
Push a new scope (reference to a hash array) directly onto the internal
stack.
pop_scope()
Pop the current scope from the top of the internal stack and return it.
new_handler( $handler )
new_handler( key => value, key => value, ... )
Install a new parser handler to receive subsequent parse events by
pushing it onto the top of the internal handler stack.
Instantiates a new handler with any arguments passed if the first
argument passed isn't already a Template::Parser::Handler
object.
current_handler()
Returns the current handler object from the top of the
internal handler stack.
old_handler()
Restores the parent handler, masked by a previous call to
new_handler()
.
push_handler( $handler )
Push a new handler directly onto the top of the internal handler stack.
pop_handler()
Pop the current handler off the top of the internal handler
stack and return it.
tags( $tagstyle )
tags( $start_tag, $end_tag )
Specify a new tag style, or a pair of values to indicate
separate start and end tags.
interpolate( $switch )
Increment (true $switch) or decrement (false $switch) the
interpolate flag.
parse_template( $text )
parse_template( \$text )
Main method to parse template text.
parse_block( $text )
parse_block( \$text )
Currently redundant.
parse_statement( $text )
parse_statement( \$text )
Parse a statement as a list of assignments or an expression.
[% pi = 3.14 %] [% pi = 3.14 e = 2.718 %] [% E = m * c * c %] [% pi %] [% pi > e ? 'Good Universe' : 'Bad Universe' %]
parse_expression( $text )
parse_expression( \$text )
Parse a complex expression.
[% foo %] [% foo + bar %] [% foo + bar < 3 ? abc : [ xyz ] %]
parse_assign( $text )
parse_assign( \$text )
Parse an assignment.
[% pi = 3.14 %] [% pi => 3.14 %]
parse_embedded( $text )
parse_embedded( \$text )
Parse a directive embedded within ${ ... }
[% user.${my.id} %]
parse_term( $text )
parse_term( \$text )
Parse a term which can be a number, literal or interpolated string, a variable,
hash, list or quoted list.
[% 3.14 %] [% 'Hello World' %] [% "$greet $place\n" %] [% foo %] [% foo(10).bar(20) %] [% { ten => 10, twenty => 20, thirty => 30 } %] [% [ 10, 20, 30 ] %] [% [ 'foo', 'bar', 'baz' ] %] [% qw[ 'foo', 'bar', 'baz' ] %]
parse_variable( $text )
parse_variable( \$text )
Parse a variable.
[% foo %] [% foo(10).bar(20) %]
parse_node( $text )
parse_node( \$text )
Parse a single node of a variable.
[% foo %] [% foo(10) %] [% bar(20) %]
parse_hash( $text )
parse_hash( \$text )
Parse the content (e.g. not the enclosing '{' and '}') of
a hash array definition.
[% myhash = { ten => 10, twenty => 20, thirty => 30 } %] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
parse_list( $text )
parse_list( \$text )
Parse the content (e.g. not the enclosing '[' and ']') of
a list definition.
[% mylist = [ 10, 20, 30 ] %] ^^^^^^^^^^
parse_args( $text )
parse_args( \$text )
Parse the content (e.g. not the enclosing '(' and ')') of
an argument list that can contain simple values and named
parameters.
[% mycode( 10, 20, 30, foo = 'bar' ) %] ^^^^^^^^^^^^^^^^^^^^^^^
parse_filename( $text )
parse_filename( \$text )
Parse a filename which can be a quoted or unquoted string or
a variable reference.
[% INCLUDE header %] ^^^^^^ [% INCLUDE $header %] ^^^^^^^ [% INCLUDE foo/bar/header.txt %] ^^^^^^^^^^^^^^^^^^ [% INCLUDE 'foo/bar/header.txt' %] ^^^^^^^^^^^^^^^^^^^^
parse_interpolate( $text )
parse_interpolate( \$text )
Parse a double quoted string, allowing interpolation of embedded
variables.
[% "The $animal sat on the $place" %]
location()
Returns the line number of the current parser position,
e.g. "23", or in the case of directives that span multiple
lines, a string of the form "n-m", e.g. "23-26".
parse_error( $error, $directive )
Method used to report parser errors. Error message passed
is passed as the first argument, the directive in which the
error occurred is passed as the second. Returns a string of
the form "line $number: $error\n [% $directive %]"
;
parse_warning( $error, $directive )
Method used to report parser warnings. Error message passed
is passed as the first argument, the directive in which the
warning occurred is passed as the optional second argument.
_tokenise( \$text )
Generates a regular expression for parsing templates based on the current
configuration style in effect.
_tokenise_regex()
Generates a regular expression for tokenising templates based
on the configuration style in effect for the current parser scope.
The Template::Parser module implements a hand-crafted recursive descent parser to parse the basic elements of the language. It supports only very basic knowledge of Perl's binary operators, simply collecting them up and spitting them out again as Perl code. Thus we retain the same precedence rules as Perl but without having to code any precedence rules ourselves.
The grammar looks something like this:
directive: KEYWORD ... | statement statement: assignment+ | expression assignment: variable =>? expression expression: ! expression | ( expression ) | ( assignment ) | expression ? expression : expression | term BINOP expression | term term: number | literal | quoted | variable | qw[ list ] # or qw( ), qw< >, qw{ }, qw| | | [ list ] | { hash } variable: varnode ( . varnode )* varnode: node | node ( args ) node: number | ident | $ident | ${directive} list: expression ,? list hash: hashitem ,? hash hashitem: hashkey =>? expression hashkey: ident | literal args: arg ,? args args: hashitem | expression literal: 'literal string' quoted: "quoted $var string with ${vars} interpolated" ident: \w+ number: [-+]\d+(\.\d+)?