Templa...:Parse(3pm)
π Template::Alloy::Parse π
okay so bestie, this is the User Contributed Perl Documentation page for Template::Alloy::Parse, and it's literally the parser brain of the whole Template::Alloy situation. let's get into it β¨
πΈ NAME πΈ
Template::Alloy::Parse β the common parsing role that creates an AST (abstract syntax tree, iykyk) out of your templates π«Ά
π¦ DESCRIPTION π¦
so the Template::Alloy::Parse role is the one holding down basically all the directive parsing code. it's also the girl who delegates β she passes stuff off to the TT, HTE, Tmpl, and Velocity roles whenever somebody needs to find variables and directives. teamwork makes the dream work, no cap π
β¨ ROLE METHODS β¨
π parse_tree
this one's used by load_tree, and it is the main grammar engine of the whole program, periodt. it delegates to whatever syntax lives in $self->{'SYNTAX'} (which defaults to 'alloy', iconic) and then calls the function it finds in that $SYNTAX hashref. and like, the majority of these syntaxes then go use methods from the $DIRECTIVES hashref to parse the different DIRECTIVE types for each particular syntax. very modular of her π
so if your template looked like this:
Foo
[%- GET foo -%]
[%- GET bar -%]
Bar
it would parse to this AST:
[
'Foo',
['GET', 6, 15, ['foo', 0]],
['GET', 22, 31, ['bar', 0]],
'Bar',
]
okay let me break that down because it's giving β¨structureβ¨. the "GET" words are the directive that got used. the 6, 15 are the beginning and ending characters of that directive in the document (yes, character positions, she keeps receipts π). and the remaining items are all the variables you need to actually run that particular directive.
π parse_expr
this one parses a variable, an expression, a literal string, or a number β and it hands you back a parsed variable tree. you can find samples of parsed variables down in the VARIABLE PARSE TREE section, go look bestie π
my $str = "1 + 2 * 3";
my $ast = $self->parse_expr(\$str);
# $ast looks like [[undef, '+', 1, [[undef, '*', 2, 3], 0]], 0]
π "parse_args"
this exists because TT parses arguments in like a million different ways and we needed to allow for all of them π. so: positional arguments AND named arguments, both welcome here. named arguments can be separated with a "=" or a "=>", and positional arguments should be separated by " " or ",". and heads up β this only returns an array of parsed variables. if you want the actual values, you gotta call play_expr on each value yourself. do the work, babe πͺ
π "dump_parse_tree"
this method returns a string of perl code that represents the AST of the parsed tree π³
it is mainly used for testing. (she's a testing girlie, respect π)
π "dump_parse_expr"
this method returns a Data::Dumper dump of a parsed variable. also mainly used for testing π§ͺ
π "parse_*"
methods named like this get used by parse_tree to parse the template. these are the grammar. they're used by all of the various template syntaxes. and unless it says otherwise somewhere, these methods are not exposed via the role π
π VARIABLE PARSE TREE π
so Template::Alloy parses templates into a tree of operations (an AST, abstract syntax tree, if you forgot already π). and yes β even variable access gets parsed into a tree. the way this happens is somewhat similar to how TT does it, EXCEPT that nested variables like foo.bar|baz keep the '.' or '|' sitting in between each name level. operators get parsed and stored as part of the variable too (honestly it might be more accurate to say we're parsing a term or an expression, but whatever π
).
the following table shows a variable or expression and the corresponding parsed tree β this is exactly what the parse_expr method would return:
one [ 'one', 0 ]
one() [ 'one', [] ]
one.two [ 'one', 0, '.', 'two', 0 ]
one|two [ 'one', 0, '|', 'two', 0 ]
one.$two [ 'one', 0, '.', ['two', 0 ], 0 ]
one(two) [ 'one', [ ['two', 0] ] ]
one.${two().three} [ 'one', 0, '.', ['two', [], '.', 'three', 0], 0]
2.34 2.34
"one" "one"
1 + 2 [ [ undef, '+', 1, 2 ], 0]
a + b [ [ undef, '+', ['a', 0], ['b', 0] ], 0 ]
"one"|length [ [ undef, '~', "one" ], 0, '|', 'length', 0 ]
"one $a two" [ [ undef, '~', 'one ', ['a', 0], ' two' ], 0 ]
[0, 1, 2] [ [ undef, '[]', 0, 1, 2 ], 0 ]
[0, 1, 2].size [ [ undef, '[]', 0, 1, 2 ], 0, '.', 'size', 0 ]
['a', a, $a ] [ [ undef, '[]', 'a', ['a', 0], [['a', 0], 0] ], 0]
{a => 'b'} [ [ undef, '{}', 'a', 'b' ], 0 ]
{a => 'b'}.size [ [ undef, '{}', 'a', 'b' ], 0, '.', 'size', 0 ]
{$a => b} [ [ undef, '{}', ['a', 0], ['b', 0] ], 0 ]
a * (b + c) [ [ undef, '*', ['a', 0], [ [undef, '+', ['b', 0], ['c', 0]], 0 ]], 0 ]
(a + b) [ [ undef, '+', ['a', 0], ['b', 0] ]], 0 ]
(a + b) * c [ [ undef, '*', [ [undef, '+', ['a', 0], ['b', 0] ], 0 ], ['c', 0] ], 0 ]
a ? b : c [ [ undef, '?', ['a', 0], ['b', 0], ['c', 0] ], 0 ]
a || b || c [ [ undef, '||', ['a', 0], [ [undef, '||', ['b', 0], ['c', 0] ], 0 ] ], 0 ]
! a [ [ undef, '!', ['a', 0] ], 0 ]
π Some notes on the parsing π
- operators get parsed as part of the variable and become part of the variable tree. she's integrated π«
- operators are stored in the variable tree using an operator identity array which contains
undefas the first value, the operator, and the operator arguments. this is what allows you to quickly descend the parsed variable tree and figure out that the next node is an operator. efficient queen π - parenthesis
()can be used at any point in an expression to disambiguate precedence. use them, bestie, they're your friend π«Ά - "Variables" that appear to be literal strings or literal numbers get returned as the literal (no operator tree). no drama, just vibes π
and if you wanna see the parsed variable tree for yourself, you can type this perl right at the command line:
perl -e 'use Template::Alloy; print Template::Alloy->dump_parse_expr("foo.bar + 2")."\n"'
orrrr you can drop this into a template to view the output in a template, which is so fun actually:
[% USE cet = Template::Alloy %]
[%~ cet.dump_parse_expr('foo.bar + 2').replace('\s+', ' ') %]
π AUTHOR π
Paul Seamons <paul@seamons.com> β thank you for your service king π«‘
π LICENSE π
This module may be distributed under the same terms as Perl itself.
okay that's the whole page bestie!! this was documented by the lovely folks at User Contributed Perl Documentation, running under perl v5.38.2, and this version is dated 2024-03-07 β go forth and parse, you absolute icon π β¨π¦
π¦ where this page comes from
- debian trixie: libtemplate-alloy-perl 1.022-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libtemplate-alloy-perl 1.022-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libtemplate-alloy-perl 1.022-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms