.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Template::Alloy::Parse 3pm" .TH Template::Alloy::Parse 3pm 2024-03-07 "perl v5.38.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Template::Alloy::Parse \- Common parsing role for creating AST from templates .SH DESCRIPTION .IX Header "DESCRIPTION" The Template::Alloy::Parse role is responsible for storing the majority of directive parsing code, as well as for delegating to the TT, HTE, Tmpl, and Velocity roles for finding variables and directives. .SH "ROLE METHODS" .IX Header "ROLE METHODS" .IP parse_tree 4 .IX Item "parse_tree" Used by load_tree. This is the main grammar engine of the program. It delegates to the syntax found in \f(CW$self\fR\->{'SYNTAX'} (defaults to 'alloy') and calls the function found in the \f(CW$SYNTAX\fR hashref. The majority of these syntaxes use methods found in the \f(CW$DIRECTIVES\fR hashref to parse different DIRECTIVE types for each particular syntax. .Sp A template that looked like the following: .Sp .Vb 4 \& Foo \& [%\- GET foo \-%] \& [%\- GET bar \-%] \& Bar .Ve .Sp would parse to the following AST: .Sp .Vb 6 \& [ \& \*(AqFoo\*(Aq, \& [\*(AqGET\*(Aq, 6, 15, [\*(Aqfoo\*(Aq, 0]], \& [\*(AqGET\*(Aq, 22, 31, [\*(Aqbar\*(Aq, 0]], \& \*(AqBar\*(Aq, \& ] .Ve .Sp The "GET" words represent the directive used. The 6, 15 represent the beginning and ending characters of the directive in the document. The remaining items are the variables necessary for running the particular directive. .IP parse_expr 4 .IX Item "parse_expr" Used to parse a variable, an expression, a literal string, or a number. It returns a parsed variable tree. Samples of parsed variables can be found in the VARIABLE PARSE TREE section. .Sp .Vb 3 \& my $str = "1 + 2 * 3"; \& my $ast = $self\->parse_expr(\e$str); \& # $ast looks like [[undef, \*(Aq+\*(Aq, 1, [[undef, \*(Aq*\*(Aq, 2, 3], 0]], 0] .Ve .ie n .IP """parse_args""" 4 .el .IP \f(CWparse_args\fR 4 .IX Item "parse_args" Allow for the multitudinous ways that TT parses arguments. This allows for positional as well as named arguments. Named arguments can be separated with a "=" or "=>", and positional arguments should be separated by " " or ",". This only returns an array of parsed variables. To get the actual values, you must call play_expr on each value. .ie n .IP """dump_parse_tree""" 4 .el .IP \f(CWdump_parse_tree\fR 4 .IX Item "dump_parse_tree" This method allows for returning a string of perl code representing the AST of the parsed tree. .Sp It is mainly used for testing. .ie n .IP """dump_parse_expr""" 4 .el .IP \f(CWdump_parse_expr\fR 4 .IX Item "dump_parse_expr" This method allows for returning a Data::Dumper dump of a parsed variable. It is mainly used for testing. .ie n .IP """parse_*""" 4 .el .IP \f(CWparse_*\fR 4 .IX Item "parse_*" Methods by these names are used by parse_tree to parse the template. These are the grammar. They are used by all of the various template syntaxes Unless otherwise mentioned, these methods are not exposed via the role. .SH "VARIABLE PARSE TREE" .IX Header "VARIABLE PARSE TREE" Template::Alloy parses templates into an tree of operations (an AST or abstract syntax tree). Even variable access is parsed into a tree. This is done in a manner somewhat similar to the way that TT operates except that nested variables such as foo.bar|baz contain the '.' or \&'|' in between each name level. Operators are parsed and stored as part of the variable (it may be more appropriate to say we are parsing a term or an expression). .PP The following table shows a variable or expression and the corresponding parsed tree (this is what the parse_expr method would return). .PP .Vb 10 \& one [ \*(Aqone\*(Aq, 0 ] \& one() [ \*(Aqone\*(Aq, [] ] \& one.two [ \*(Aqone\*(Aq, 0, \*(Aq.\*(Aq, \*(Aqtwo\*(Aq, 0 ] \& one|two [ \*(Aqone\*(Aq, 0, \*(Aq|\*(Aq, \*(Aqtwo\*(Aq, 0 ] \& one.$two [ \*(Aqone\*(Aq, 0, \*(Aq.\*(Aq, [\*(Aqtwo\*(Aq, 0 ], 0 ] \& one(two) [ \*(Aqone\*(Aq, [ [\*(Aqtwo\*(Aq, 0] ] ] \& one.${two().three} [ \*(Aqone\*(Aq, 0, \*(Aq.\*(Aq, [\*(Aqtwo\*(Aq, [], \*(Aq.\*(Aq, \*(Aqthree\*(Aq, 0], 0] \& 2.34 2.34 \& "one" "one" \& 1 + 2 [ [ undef, \*(Aq+\*(Aq, 1, 2 ], 0] \& a + b [ [ undef, \*(Aq+\*(Aq, [\*(Aqa\*(Aq, 0], [\*(Aqb\*(Aq, 0] ], 0 ] \& "one"|length [ [ undef, \*(Aq~\*(Aq, "one" ], 0, \*(Aq|\*(Aq, \*(Aqlength\*(Aq, 0 ] \& "one $a two" [ [ undef, \*(Aq~\*(Aq, \*(Aqone \*(Aq, [\*(Aqa\*(Aq, 0], \*(Aq two\*(Aq ], 0 ] \& [0, 1, 2] [ [ undef, \*(Aq[]\*(Aq, 0, 1, 2 ], 0 ] \& [0, 1, 2].size [ [ undef, \*(Aq[]\*(Aq, 0, 1, 2 ], 0, \*(Aq.\*(Aq, \*(Aqsize\*(Aq, 0 ] \& [\*(Aqa\*(Aq, a, $a ] [ [ undef, \*(Aq[]\*(Aq, \*(Aqa\*(Aq, [\*(Aqa\*(Aq, 0], [[\*(Aqa\*(Aq, 0], 0] ], 0] \& {a => \*(Aqb\*(Aq} [ [ undef, \*(Aq{}\*(Aq, \*(Aqa\*(Aq, \*(Aqb\*(Aq ], 0 ] \& {a => \*(Aqb\*(Aq}.size [ [ undef, \*(Aq{}\*(Aq, \*(Aqa\*(Aq, \*(Aqb\*(Aq ], 0, \*(Aq.\*(Aq, \*(Aqsize\*(Aq, 0 ] \& {$a => b} [ [ undef, \*(Aq{}\*(Aq, [\*(Aqa\*(Aq, 0], [\*(Aqb\*(Aq, 0] ], 0 ] \& a * (b + c) [ [ undef, \*(Aq*\*(Aq, [\*(Aqa\*(Aq, 0], [ [undef, \*(Aq+\*(Aq, [\*(Aqb\*(Aq, 0], [\*(Aqc\*(Aq, 0]], 0 ]], 0 ] \& (a + b) [ [ undef, \*(Aq+\*(Aq, [\*(Aqa\*(Aq, 0], [\*(Aqb\*(Aq, 0] ]], 0 ] \& (a + b) * c [ [ undef, \*(Aq*\*(Aq, [ [undef, \*(Aq+\*(Aq, [\*(Aqa\*(Aq, 0], [\*(Aqb\*(Aq, 0] ], 0 ], [\*(Aqc\*(Aq, 0] ], 0 ] \& a ? b : c [ [ undef, \*(Aq?\*(Aq, [\*(Aqa\*(Aq, 0], [\*(Aqb\*(Aq, 0], [\*(Aqc\*(Aq, 0] ], 0 ] \& a || b || c [ [ undef, \*(Aq||\*(Aq, [\*(Aqa\*(Aq, 0], [ [undef, \*(Aq||\*(Aq, [\*(Aqb\*(Aq, 0], [\*(Aqc\*(Aq, 0] ], 0 ] ], 0 ] \& ! a [ [ undef, \*(Aq!\*(Aq, [\*(Aqa\*(Aq, 0] ], 0 ] .Ve .PP Some notes on the parsing. .PP .Vb 1 \& Operators are parsed as part of the variable and become part of the variable tree. \& \& Operators are stored in the variable tree using an operator identity array which \& contains undef as the first value, the operator, and the operator arguments. This \& allows for quickly descending the parsed variable tree and determining that the next \& node is an operator. \& \& Parenthesis () can be used at any point in an expression to disambiguate precedence. \& \& "Variables" that appear to be literal strings or literal numbers \& are returned as the literal (no operator tree). .Ve .PP The following perl can be typed at the command line to view the parsed variable tree: .PP .Vb 1 \& perl \-e \*(Aquse Template::Alloy; print Template::Alloy\->dump_parse_expr("foo.bar + 2")."\en"\*(Aq .Ve .PP Also the following can be included in a template to view the output in a template: .PP .Vb 2 \& [% USE cet = Template::Alloy %] \& [%~ cet.dump_parse_expr(\*(Aqfoo.bar + 2\*(Aq).replace(\*(Aq\es+\*(Aq, \*(Aq \*(Aq) %] .Ve .SH AUTHOR .IX Header "AUTHOR" Paul Seamons .SH LICENSE .IX Header "LICENSE" This module may be distributed under the same terms as Perl itself.