| Filename | /usr/lib/x86_64-linux-gnu/perl5/5.28/Template/Parser.pm |
| Statements | Executed 229996342 statements in 218s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 376400 | 1 | 1 | 120s | 171s | Template::Parser::_parse |
| 376400 | 1 | 1 | 28.5s | 57.4s | Template::Parser::split_text |
| 375387 | 1 | 1 | 23.0s | 49.2s | Template::Parser::new |
| 314713 | 1 | 1 | 16.1s | 21.3s | Template::Parser::tokenise_directive |
| 376400 | 1 | 1 | 10.7s | 239s | Template::Parser::parse |
| 375387 | 1 | 1 | 10.3s | 17.5s | Template::Parser::new_style |
| 1846064 | 11 | 1 | 6.08s | 6.08s | Template::Parser::CORE:subst (opcode) |
| 375387 | 1 | 1 | 5.41s | 7.19s | Template::Parser::text_splitter |
| 2643427 | 7 | 1 | 5.23s | 5.23s | Template::Parser::CORE:match (opcode) |
| 313428 | 1 | 1 | 2.84s | 3.20s | Template::Parser::location |
| 2010639 | 6 | 1 | 2.33s | 2.33s | Template::Parser::CORE:regcomp (opcode) |
| 2490942 | 1 | 1 | 1.83s | 1.83s | Template::Parser::__ANON__[:955] |
| 751789 | 4 | 1 | 1.22s | 1.22s | Template::Parser::CORE:qr (opcode) |
| 1991 | 1 | 1 | 78.9ms | 86.4ms | Template::Parser::interpolate_text |
| 5968 | 1 | 1 | 70.5ms | 121ms | Template::Parser::leave_block |
| 5968 | 1 | 1 | 50.2ms | 50.2ms | Template::Parser::block_label |
| 5968 | 1 | 1 | 32.0ms | 32.0ms | Template::Parser::enter_block |
| 1 | 1 | 1 | 14.6ms | 14.7ms | Template::Parser::BEGIN@41 |
| 3982 | 1 | 1 | 5.01ms | 5.01ms | Template::Parser::CORE:substcont (opcode) |
| 1 | 1 | 1 | 3.70ms | 3.94ms | Template::Parser::BEGIN@40 |
| 1 | 1 | 1 | 15µs | 20µs | Template::Parser::BEGIN@35 |
| 1 | 1 | 1 | 12µs | 83µs | Template::Parser::BEGIN@44 |
| 1 | 1 | 1 | 9µs | 102µs | Template::Parser::BEGIN@37 |
| 1 | 1 | 1 | 8µs | 246µs | Template::Parser::BEGIN@39 |
| 1 | 1 | 1 | 7µs | 31µs | Template::Parser::BEGIN@45 |
| 1 | 1 | 1 | 6µs | 32µs | Template::Parser::BEGIN@36 |
| 1 | 1 | 1 | 5µs | 27µs | Template::Parser::BEGIN@46 |
| 1 | 1 | 1 | 5µs | 26µs | Template::Parser::BEGIN@47 |
| 2 | 2 | 1 | 4µs | 4µs | Template::Parser::__ANON__ (xsub) |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::_dump |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::_parse_error |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::add_metadata |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::define_block |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::in_block |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::old_style |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::pop_defblock |
| 0 | 0 | 0 | 0s | 0s | Template::Parser::push_defblock |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | #============================================================= -*-Perl-*- | ||||
| 2 | # | ||||
| 3 | # Template::Parser | ||||
| 4 | # | ||||
| 5 | # DESCRIPTION | ||||
| 6 | # This module implements a LALR(1) parser and associated support | ||||
| 7 | # methods to parse template documents into the appropriate "compiled" | ||||
| 8 | # format. Much of the parser DFA code (see _parse() method) is based | ||||
| 9 | # on Francois Desarmenien's Parse::Yapp module. Kudos to him. | ||||
| 10 | # | ||||
| 11 | # AUTHOR | ||||
| 12 | # Andy Wardley <abw@wardley.org> | ||||
| 13 | # | ||||
| 14 | # COPYRIGHT | ||||
| 15 | # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. | ||||
| 16 | # | ||||
| 17 | # This module is free software; you can redistribute it and/or | ||||
| 18 | # modify it under the same terms as Perl itself. | ||||
| 19 | # | ||||
| 20 | # The following copyright notice appears in the Parse::Yapp | ||||
| 21 | # documentation. | ||||
| 22 | # | ||||
| 23 | # The Parse::Yapp module and its related modules and shell | ||||
| 24 | # scripts are copyright (c) 1998 Francois Desarmenien, | ||||
| 25 | # France. All rights reserved. | ||||
| 26 | # | ||||
| 27 | # You may use and distribute them under the terms of either | ||||
| 28 | # the GNU General Public License or the Artistic License, as | ||||
| 29 | # specified in the Perl README file. | ||||
| 30 | # | ||||
| 31 | #============================================================================ | ||||
| 32 | |||||
| 33 | package Template::Parser; | ||||
| 34 | |||||
| 35 | 2 | 24µs | 2 | 24µs | # spent 20µs (15+4) within Template::Parser::BEGIN@35 which was called:
# once (15µs+4µs) by Template::Config::load at line 35 # spent 20µs making 1 call to Template::Parser::BEGIN@35
# spent 4µs making 1 call to strict::import |
| 36 | 2 | 23µs | 2 | 58µs | # spent 32µs (6+26) within Template::Parser::BEGIN@36 which was called:
# once (6µs+26µs) by Template::Config::load at line 36 # spent 32µs making 1 call to Template::Parser::BEGIN@36
# spent 26µs making 1 call to warnings::import |
| 37 | 2 | 30µs | 2 | 196µs | # spent 102µs (9+94) within Template::Parser::BEGIN@37 which was called:
# once (9µs+94µs) by Template::Config::load at line 37 # spent 102µs making 1 call to Template::Parser::BEGIN@37
# spent 94µs making 1 call to base::import |
| 38 | |||||
| 39 | 2 | 30µs | 2 | 484µs | # spent 246µs (8+238) within Template::Parser::BEGIN@39 which was called:
# once (8µs+238µs) by Template::Config::load at line 39 # spent 246µs making 1 call to Template::Parser::BEGIN@39
# spent 238µs making 1 call to Exporter::import |
| 40 | 2 | 179µs | 2 | 3.95ms | # spent 3.94ms (3.70+246µs) within Template::Parser::BEGIN@40 which was called:
# once (3.70ms+246µs) by Template::Config::load at line 40 # spent 3.94ms making 1 call to Template::Parser::BEGIN@40
# spent 2µs making 1 call to Template::Parser::__ANON__ |
| 41 | 2 | 258µs | 2 | 14.7ms | # spent 14.7ms (14.6+58µs) within Template::Parser::BEGIN@41 which was called:
# once (14.6ms+58µs) by Template::Config::load at line 41 # spent 14.7ms making 1 call to Template::Parser::BEGIN@41
# spent 3µs making 1 call to Template::Parser::__ANON__ |
| 42 | |||||
| 43 | # parser state constants | ||||
| 44 | 2 | 30µs | 2 | 153µs | # spent 83µs (12+71) within Template::Parser::BEGIN@44 which was called:
# once (12µs+71µs) by Template::Config::load at line 44 # spent 83µs making 1 call to Template::Parser::BEGIN@44
# spent 71µs making 1 call to constant::import |
| 45 | 2 | 23µs | 2 | 55µs | # spent 31µs (7+24) within Template::Parser::BEGIN@45 which was called:
# once (7µs+24µs) by Template::Config::load at line 45 # spent 31µs making 1 call to Template::Parser::BEGIN@45
# spent 24µs making 1 call to constant::import |
| 46 | 2 | 21µs | 2 | 49µs | # spent 27µs (5+22) within Template::Parser::BEGIN@46 which was called:
# once (5µs+22µs) by Template::Config::load at line 46 # spent 27µs making 1 call to Template::Parser::BEGIN@46
# spent 22µs making 1 call to constant::import |
| 47 | 2 | 3.52ms | 2 | 48µs | # spent 26µs (5+21) within Template::Parser::BEGIN@47 which was called:
# once (5µs+21µs) by Template::Config::load at line 47 # spent 26µs making 1 call to Template::Parser::BEGIN@47
# spent 21µs making 1 call to constant::import |
| 48 | |||||
| 49 | 1 | 400ns | our $VERSION = 2.89; | ||
| 50 | 1 | 400ns | our $DEBUG = 0 unless defined $DEBUG; | ||
| 51 | 1 | 400ns | our $ERROR = ''; | ||
| 52 | |||||
| 53 | # The ANYCASE option can cause conflicts when reserved words are used as | ||||
| 54 | # variable names, hash keys, template names, plugin names, etc. The | ||||
| 55 | # | ||||
| 56 | # $ANYCASE_BEFORE regex identifies where such a word precedes an assignment, | ||||
| 57 | # either as a variable (C<wrapper = 'html'>) or hash key (C<{ wrapper => 'html' }). | ||||
| 58 | # In that case it is treated as a simple words rather than being the lower case | ||||
| 59 | # equivalent of the upper case keyword (e.g. WRAPPER). | ||||
| 60 | # | ||||
| 61 | # $ANYCASE_AFTER is used to identify when such a word follows a symbols that | ||||
| 62 | # suggests it can't be a keyword, e.g. after BLOCK INCLUDE WRAPPER, USE, etc. | ||||
| 63 | 1 | 11µs | 1 | 2µs | our $ANYCASE_BEFORE = qr/\G((?=\s*[=\.]))/; # spent 2µs making 1 call to Template::Parser::CORE:qr |
| 64 | our $ANYCASE_AFTER = { | ||||
| 65 | 1 | 22µs | map { $_ => 1 } | ||
| 66 | qw( | ||||
| 67 | GET SET CALL DEFAULT INSERT INCLUDE PROCESS WRAPPER BLOCK USE | ||||
| 68 | PLUGIN FILTER MACRO IN TO STEP AND OR NOT DIV MOD DOT | ||||
| 69 | IF UNLESS ELSIF FOR WHILE SWITCH CASE META THROW CATCH VIEW | ||||
| 70 | CMPOP BINOP COMMA | ||||
| 71 | ), | ||||
| 72 | '(', '[', '{' | ||||
| 73 | # not sure about ASSIGN as it breaks C<header_html = include header> | ||||
| 74 | }; | ||||
| 75 | |||||
| 76 | |||||
| 77 | #======================================================================== | ||||
| 78 | # -- COMMON TAG STYLES -- | ||||
| 79 | #======================================================================== | ||||
| 80 | |||||
| 81 | 1 | 8µs | our $TAG_STYLE = { | ||
| 82 | 'outline' => [ '\[%', '%\]', '%%' ], # NEW! Outline tag | ||||
| 83 | 'default' => [ '\[%', '%\]' ], | ||||
| 84 | 'template1' => [ '[\[%]%', '%[\]%]' ], | ||||
| 85 | 'metatext' => [ '%%', '%%' ], | ||||
| 86 | 'html' => [ '<!--', '-->' ], | ||||
| 87 | 'mason' => [ '<%', '>' ], | ||||
| 88 | 'asp' => [ '<%', '%>' ], | ||||
| 89 | 'php' => [ '<\?', '\?>' ], | ||||
| 90 | 'star' => [ '\[\*', '\*\]' ], | ||||
| 91 | }; | ||||
| 92 | 1 | 1µs | $TAG_STYLE->{ template } = $TAG_STYLE->{ tt2 } = $TAG_STYLE->{ default }; | ||
| 93 | |||||
| 94 | |||||
| 95 | our $DEFAULT_STYLE = { | ||||
| 96 | START_TAG => $TAG_STYLE->{ default }->[0], | ||||
| 97 | END_TAG => $TAG_STYLE->{ default }->[1], | ||||
| 98 | 1 | 7µs | OUTLINE_TAG => $TAG_STYLE->{ default }->[2], | ||
| 99 | # TAG_STYLE => 'default', | ||||
| 100 | ANYCASE => 0, | ||||
| 101 | INTERPOLATE => 0, | ||||
| 102 | PRE_CHOMP => 0, | ||||
| 103 | POST_CHOMP => 0, | ||||
| 104 | V1DOLLAR => 0, | ||||
| 105 | EVAL_PERL => 0, | ||||
| 106 | }; | ||||
| 107 | |||||
| 108 | 1 | 2µs | our $QUOTED_ESCAPES = { | ||
| 109 | n => "\n", | ||||
| 110 | r => "\r", | ||||
| 111 | t => "\t", | ||||
| 112 | }; | ||||
| 113 | |||||
| 114 | # note that '-' must come first so Perl doesn't think it denotes a range | ||||
| 115 | 1 | 3µs | 1 | 600ns | our $CHOMP_FLAGS = qr/[-=~+]/; # spent 600ns making 1 call to Template::Parser::CORE:qr |
| 116 | |||||
| - - | |||||
| 119 | #======================================================================== | ||||
| 120 | # ----- PUBLIC METHODS ----- | ||||
| 121 | #======================================================================== | ||||
| 122 | |||||
| 123 | #------------------------------------------------------------------------ | ||||
| 124 | # new(\%config) | ||||
| 125 | # | ||||
| 126 | # Constructor method. | ||||
| 127 | #------------------------------------------------------------------------ | ||||
| 128 | |||||
| 129 | # spent 49.2s (23.0+26.2) within Template::Parser::new which was called 375387 times, avg 131µs/call:
# 375387 times (23.0s+26.2s) by Template::Config::parser at line 103 of Template/Config.pm, avg 131µs/call | ||||
| 130 | 375387 | 155ms | my $class = shift; | ||
| 131 | 375387 | 706ms | my $config = $_[0] && ref($_[0]) eq 'HASH' ? shift(@_) : { @_ }; | ||
| 132 | 375387 | 168ms | my ($tagstyle, $debug, $start, $end, $defaults, $grammar, $hash, $key, $udef); | ||
| 133 | |||||
| 134 | my $self = bless { | ||||
| 135 | START_TAG => undef, | ||||
| 136 | END_TAG => undef, | ||||
| 137 | OUTLINE_TAG => undef, | ||||
| 138 | TAG_STYLE => 'default', | ||||
| 139 | ANYCASE => 0, | ||||
| 140 | INTERPOLATE => 0, | ||||
| 141 | PRE_CHOMP => 0, | ||||
| 142 | POST_CHOMP => 0, | ||||
| 143 | V1DOLLAR => 0, | ||||
| 144 | EVAL_PERL => 0, | ||||
| 145 | FILE_INFO => 1, | ||||
| 146 | GRAMMAR => undef, | ||||
| 147 | _ERROR => '', | ||||
| 148 | IN_BLOCK => [ ], | ||||
| 149 | TRACE_VARS => $config->{ TRACE_VARS }, | ||||
| 150 | 375387 | 5.56s | FACTORY => $config->{ FACTORY } || 'Template::Directive', | ||
| 151 | }, $class; | ||||
| 152 | |||||
| 153 | # update self with any relevant keys in config | ||||
| 154 | 375387 | 1.40s | foreach $key (keys %$self) { | ||
| 155 | 6006192 | 1.73s | $self->{ $key } = $config->{ $key } if defined $config->{ $key }; | ||
| 156 | } | ||||
| 157 | 375387 | 510ms | $self->{ FILEINFO } = [ ]; | ||
| 158 | |||||
| 159 | # DEBUG config item can be a bitmask | ||||
| 160 | 375387 | 805ms | if (defined ($debug = $config->{ DEBUG })) { | ||
| 161 | $self->{ DEBUG } = $debug & ( Template::Constants::DEBUG_PARSER | ||||
| 162 | | Template::Constants::DEBUG_FLAGS ); | ||||
| 163 | $self->{ DEBUG_DIRS } = $debug & Template::Constants::DEBUG_DIRS; | ||||
| 164 | } | ||||
| 165 | # package variable can be set to 1 to support previous behaviour | ||||
| 166 | elsif ($DEBUG == 1) { | ||||
| 167 | $self->{ DEBUG } = Template::Constants::DEBUG_PARSER; | ||||
| 168 | $self->{ DEBUG_DIRS } = 0; | ||||
| 169 | } | ||||
| 170 | # otherwise let $DEBUG be a bitmask | ||||
| 171 | else { | ||||
| 172 | 375387 | 341ms | $self->{ DEBUG } = $DEBUG & ( Template::Constants::DEBUG_PARSER | ||
| 173 | | Template::Constants::DEBUG_FLAGS ); | ||||
| 174 | 375387 | 285ms | $self->{ DEBUG_DIRS } = $DEBUG & Template::Constants::DEBUG_DIRS; | ||
| 175 | } | ||||
| 176 | |||||
| 177 | 375387 | 427ms | $grammar = $self->{ GRAMMAR } ||= do { | ||
| 178 | 375387 | 229ms | require Template::Grammar; | ||
| 179 | 375387 | 1.34s | 375387 | 1.92s | Template::Grammar->new(); # spent 1.92s making 375387 calls to Template::Grammar::new, avg 5µs/call |
| 180 | }; | ||||
| 181 | |||||
| 182 | # instantiate a FACTORY object | ||||
| 183 | 375387 | 553ms | unless (ref $self->{ FACTORY }) { | ||
| 184 | 375387 | 272ms | my $fclass = $self->{ FACTORY }; | ||
| 185 | $self->{ FACTORY } = $self->{ FACTORY }->new( | ||||
| 186 | NAMESPACE => $config->{ NAMESPACE } | ||||
| 187 | ) | ||||
| 188 | 375387 | 1.66s | 375387 | 6.75s | || return $class->error($self->{ FACTORY }->error()); # spent 6.75s making 375387 calls to Template::Base::new, avg 18µs/call |
| 189 | } | ||||
| 190 | |||||
| 191 | # load grammar rules, states and lex table | ||||
| 192 | @$self{ qw( LEXTABLE STATES RULES ) } | ||||
| 193 | 375387 | 1.39s | = @$grammar{ qw( LEXTABLE STATES RULES ) }; | ||
| 194 | |||||
| 195 | 375387 | 1.25s | 375387 | 17.5s | $self->new_style($config) # spent 17.5s making 375387 calls to Template::Parser::new_style, avg 47µs/call |
| 196 | || return $class->error($self->error()); | ||||
| 197 | |||||
| 198 | 375387 | 1.93s | return $self; | ||
| 199 | } | ||||
| 200 | |||||
| 201 | #----------------------------------------------------------------------- | ||||
| 202 | # These methods are used to track nested IF and WHILE blocks. Each | ||||
| 203 | # generated if/while block is given a label indicating the directive | ||||
| 204 | # type and nesting depth, e.g. FOR0, WHILE1, FOR2, WHILE3, etc. The | ||||
| 205 | # NEXT and LAST directives use the innermost label, e.g. last WHILE3; | ||||
| 206 | #----------------------------------------------------------------------- | ||||
| 207 | |||||
| 208 | # spent 32.0ms within Template::Parser::enter_block which was called 5968 times, avg 5µs/call:
# 5968 times (32.0ms+0s) by Template::Grammar::__ANON__[Parser.yp:167] at line 167 of /root/tor-browser-build/Parser.yp, avg 5µs/call | ||||
| 209 | 5968 | 3.94ms | my ($self, $name) = @_; | ||
| 210 | 5968 | 6.57ms | my $blocks = $self->{ IN_BLOCK }; | ||
| 211 | 5968 | 43.7ms | push(@{ $self->{ IN_BLOCK } }, $name); | ||
| 212 | } | ||||
| 213 | |||||
| 214 | # spent 121ms (70.5+50.2) within Template::Parser::leave_block which was called 5968 times, avg 20µs/call:
# 5968 times (70.5ms+50.2ms) by Template::Grammar::__ANON__[Parser.yp:168] at line 168 of /root/tor-browser-build/Parser.yp, avg 20µs/call | ||||
| 215 | 5968 | 3.33ms | my $self = shift; | ||
| 216 | 5968 | 23.9ms | 5968 | 50.2ms | my $label = $self->block_label; # spent 50.2ms making 5968 calls to Template::Parser::block_label, avg 8µs/call |
| 217 | 5968 | 8.52ms | pop(@{ $self->{ IN_BLOCK } }); | ||
| 218 | 5968 | 35.1ms | return $label; | ||
| 219 | } | ||||
| 220 | |||||
| 221 | sub in_block { | ||||
| 222 | my ($self, $name) = @_; | ||||
| 223 | my $blocks = $self->{ IN_BLOCK }; | ||||
| 224 | return @$blocks && $blocks->[-1] eq $name; | ||||
| 225 | } | ||||
| 226 | |||||
| 227 | # spent 50.2ms within Template::Parser::block_label which was called 5968 times, avg 8µs/call:
# 5968 times (50.2ms+0s) by Template::Parser::leave_block at line 216, avg 8µs/call | ||||
| 228 | 5968 | 5.99ms | my ($self, $prefix, $suffix) = @_; | ||
| 229 | 5968 | 7.18ms | my $blocks = $self->{ IN_BLOCK }; | ||
| 230 | 5968 | 14.0ms | my $name = @$blocks | ||
| 231 | ? $blocks->[-1] . scalar @$blocks | ||||
| 232 | : undef; | ||||
| 233 | 5968 | 45.5ms | return join('', grep { defined $_ } $prefix, $name, $suffix); | ||
| 234 | } | ||||
| 235 | |||||
| - - | |||||
| 238 | #------------------------------------------------------------------------ | ||||
| 239 | # new_style(\%config) | ||||
| 240 | # | ||||
| 241 | # Install a new (stacked) parser style. This feature is currently | ||||
| 242 | # experimental but should mimic the previous behaviour with regard to | ||||
| 243 | # TAG_STYLE, START_TAG, END_TAG, etc. | ||||
| 244 | #------------------------------------------------------------------------ | ||||
| 245 | |||||
| 246 | # spent 17.5s (10.3+7.19) within Template::Parser::new_style which was called 375387 times, avg 47µs/call:
# 375387 times (10.3s+7.19s) by Template::Parser::new at line 195, avg 47µs/call | ||||
| 247 | 375387 | 246ms | my ($self, $config) = @_; | ||
| 248 | 375387 | 661ms | my $styles = $self->{ STYLE } ||= [ ]; | ||
| 249 | 375387 | 171ms | my ($tagstyle, $tags, $start, $end, $out, $key); | ||
| 250 | |||||
| 251 | # clone new style from previous or default style | ||||
| 252 | 375387 | 2.47s | my $style = { %{ $styles->[-1] || $DEFAULT_STYLE } }; | ||
| 253 | |||||
| 254 | # expand START_TAG and END_TAG from specified TAG_STYLE | ||||
| 255 | 375387 | 351ms | if ($tagstyle = $config->{ TAG_STYLE }) { | ||
| 256 | return $self->error("Invalid tag style: $tagstyle") | ||||
| 257 | unless defined ($tags = $TAG_STYLE->{ $tagstyle }); | ||||
| 258 | ($start, $end, $out) = @$tags; | ||||
| 259 | $config->{ START_TAG } ||= $start; | ||||
| 260 | $config->{ END_TAG } ||= $end; | ||||
| 261 | $config->{ OUTLINE_TAG } ||= $out; | ||||
| 262 | } | ||||
| 263 | |||||
| 264 | 375387 | 832ms | foreach $key (keys %$DEFAULT_STYLE) { | ||
| 265 | 3378483 | 1.08s | $style->{ $key } = $config->{ $key } if defined $config->{ $key }; | ||
| 266 | } | ||||
| 267 | |||||
| 268 | 375387 | 305ms | $start = $style->{ START_TAG }; | ||
| 269 | 375387 | 317ms | $end = $style->{ END_TAG }; | ||
| 270 | 375387 | 227ms | $out = $style->{ OUTLINE_TAG }; | ||
| 271 | 375387 | 1.26s | 375387 | 7.19s | $style->{ TEXT_SPLIT } = $self->text_splitter($start, $end, $out); # spent 7.19s making 375387 calls to Template::Parser::text_splitter, avg 19µs/call |
| 272 | |||||
| 273 | 375387 | 166ms | push(@$styles, $style); | ||
| 274 | 375387 | 2.12s | return $style; | ||
| 275 | } | ||||
| 276 | |||||
| 277 | # spent 7.19s (5.41+1.78) within Template::Parser::text_splitter which was called 375387 times, avg 19µs/call:
# 375387 times (5.41s+1.78s) by Template::Parser::new_style at line 271, avg 19µs/call | ||||
| 278 | 375387 | 365ms | my ($self, $start, $end, $out) = @_; | ||
| 279 | |||||
| 280 | 375387 | 262ms | if (defined $out) { | ||
| 281 | return qr/ | ||||
| 282 | \A(.*?) # $1 - start of line up to directive | ||||
| 283 | (?: | ||||
| 284 | (?: | ||||
| 285 | ^$out # outline tag at start of line | ||||
| 286 | (.*?) # $2 - content of that line | ||||
| 287 | (?:\n|$) # end of that line or file | ||||
| 288 | ) | ||||
| 289 | | | ||||
| 290 | (?: | ||||
| 291 | $start # start of tag | ||||
| 292 | (.*?) # $3 - tag contents | ||||
| 293 | $end # end of tag | ||||
| 294 | ) | ||||
| 295 | ) | ||||
| 296 | /msx; | ||||
| 297 | } | ||||
| 298 | else { | ||||
| 299 | 375387 | 7.85s | 750774 | 1.78s | return qr/ # spent 996ms making 375387 calls to Template::Parser::CORE:regcomp, avg 3µs/call
# spent 788ms making 375387 calls to Template::Parser::CORE:qr, avg 2µs/call |
| 300 | ^(.*?) # $1 - start of line up to directive | ||||
| 301 | (?: | ||||
| 302 | $start # start of tag | ||||
| 303 | (.*?) # $2 - tag contents | ||||
| 304 | $end # end of tag | ||||
| 305 | ) | ||||
| 306 | /sx; | ||||
| 307 | } | ||||
| 308 | } | ||||
| 309 | |||||
| 310 | #------------------------------------------------------------------------ | ||||
| 311 | # old_style() | ||||
| 312 | # | ||||
| 313 | # Pop the current parser style and revert to the previous one. See | ||||
| 314 | # new_style(). ** experimental ** | ||||
| 315 | #------------------------------------------------------------------------ | ||||
| 316 | |||||
| 317 | sub old_style { | ||||
| 318 | my $self = shift; | ||||
| 319 | my $styles = $self->{ STYLE }; | ||||
| 320 | return $self->error('only 1 parser style remaining') | ||||
| 321 | unless (@$styles > 1); | ||||
| 322 | pop @$styles; | ||||
| 323 | return $styles->[-1]; | ||||
| 324 | } | ||||
| 325 | |||||
| 326 | |||||
| 327 | #------------------------------------------------------------------------ | ||||
| 328 | # parse($text, $data) | ||||
| 329 | # | ||||
| 330 | # Parses the text string, $text and returns a hash array representing | ||||
| 331 | # the compiled template block(s) as Perl code, in the format expected | ||||
| 332 | # by Template::Document. | ||||
| 333 | #------------------------------------------------------------------------ | ||||
| 334 | |||||
| 335 | # spent 239s (10.7+228) within Template::Parser::parse which was called 376400 times, avg 634µs/call:
# 376400 times (10.7s+228s) by Template::Provider::_compile at line 844 of Template/Provider.pm, avg 634µs/call | ||||
| 336 | 376400 | 321ms | my ($self, $text, $info) = @_; | ||
| 337 | 376400 | 134ms | my ($tokens, $block); | ||
| 338 | |||||
| 339 | $info->{ DEBUG } = $self->{ DEBUG_DIRS } | ||||
| 340 | 376400 | 629ms | unless defined $info->{ DEBUG }; | ||
| 341 | |||||
| 342 | # print "info: { ", join(', ', map { "$_ => $info->{ $_ }" } keys %$info), " }\n"; | ||||
| 343 | |||||
| 344 | # store for blocks defined in the template (see define_block()) | ||||
| 345 | 376400 | 456ms | my $defblock = $self->{ DEFBLOCK } = { }; | ||
| 346 | 376400 | 416ms | my $metadata = $self->{ METADATA } = [ ]; | ||
| 347 | 376400 | 432ms | my $variables = $self->{ VARIABLES } = { }; | ||
| 348 | 376400 | 327ms | $self->{ DEFBLOCKS } = [ ]; | ||
| 349 | |||||
| 350 | 376400 | 340ms | $self->{ _ERROR } = ''; | ||
| 351 | |||||
| 352 | # split file into TEXT/DIRECTIVE chunks | ||||
| 353 | 376400 | 980ms | 376400 | 57.4s | $tokens = $self->split_text($text) # spent 57.4s making 376400 calls to Template::Parser::split_text, avg 153µs/call |
| 354 | || return undef; ## RETURN ## | ||||
| 355 | |||||
| 356 | 376400 | 487ms | push(@{ $self->{ FILEINFO } }, $info); | ||
| 357 | |||||
| 358 | # parse chunks | ||||
| 359 | 376400 | 1.21s | 376400 | 171s | $block = $self->_parse($tokens, $info); # spent 171s making 376400 calls to Template::Parser::_parse, avg 453µs/call |
| 360 | |||||
| 361 | 376400 | 300ms | pop(@{ $self->{ FILEINFO } }); | ||
| 362 | |||||
| 363 | 376400 | 149ms | return undef unless $block; ## RETURN ## | ||
| 364 | |||||
| 365 | $self->debug("compiled main template document block:\n$block") | ||||
| 366 | 376400 | 377ms | if $self->{ DEBUG } & Template::Constants::DEBUG_PARSER; | ||
| 367 | |||||
| 368 | return { | ||||
| 369 | 376400 | 2.95s | BLOCK => $block, | ||
| 370 | DEFBLOCKS => $defblock, | ||||
| 371 | VARIABLES => $variables, | ||||
| 372 | METADATA => { @$metadata }, | ||||
| 373 | }; | ||||
| 374 | } | ||||
| 375 | |||||
| - - | |||||
| 378 | #------------------------------------------------------------------------ | ||||
| 379 | # split_text($text) | ||||
| 380 | # | ||||
| 381 | # Split input template text into directives and raw text chunks. | ||||
| 382 | #------------------------------------------------------------------------ | ||||
| 383 | |||||
| 384 | # spent 57.4s (28.5+28.9) within Template::Parser::split_text which was called 376400 times, avg 153µs/call:
# 376400 times (28.5s+28.9s) by Template::Parser::parse at line 353, avg 153µs/call | ||||
| 385 | 376400 | 245ms | my ($self, $text) = @_; | ||
| 386 | 376400 | 198ms | my ($pre, $dir, $prelines, $dirlines, $postlines, $chomp, $tags, @tags); | ||
| 387 | 376400 | 412ms | my $style = $self->{ STYLE }->[-1]; | ||
| 388 | my ($start, $end, $out, $prechomp, $postchomp, $interp ) = | ||||
| 389 | 376400 | 1.11s | @$style{ qw( START_TAG END_TAG OUTLINE_TAG PRE_CHOMP POST_CHOMP INTERPOLATE ) }; | ||
| 390 | 376400 | 2.38s | 376400 | 434ms | my $tags_dir = $self->{ANYCASE} ? qr<TAGS>i : qr<TAGS>; # spent 434ms making 376400 calls to Template::Parser::CORE:qr, avg 1µs/call |
| 391 | 376400 | 281ms | my $split = $style->{ TEXT_SPLIT }; | ||
| 392 | 376400 | 303ms | my $has_out = defined $out; | ||
| 393 | |||||
| 394 | 376400 | 265ms | my @tokens = (); | ||
| 395 | 376400 | 192ms | my $line = 1; | ||
| 396 | |||||
| 397 | return \@tokens ## RETURN ## | ||||
| 398 | 376400 | 315ms | unless defined $text && length $text; | ||
| 399 | |||||
| 400 | # extract all directives from the text | ||||
| 401 | 376400 | 5.54s | 752800 | 1.92s | while ($text =~ s/$split//) { # spent 1.30s making 376400 calls to Template::Parser::CORE:subst, avg 3µs/call
# spent 619ms making 376400 calls to Template::Parser::CORE:regcomp, avg 2µs/call |
| 402 | 314713 | 436ms | $pre = $1; | ||
| 403 | 314713 | 521ms | $dir = defined($2) ? $2 : $3; | ||
| 404 | 314713 | 123ms | $pre = '' unless defined $pre; | ||
| 405 | 314713 | 118ms | $dir = '' unless defined $dir; | ||
| 406 | |||||
| 407 | 314713 | 272ms | $prelines = ($pre =~ tr/\n//); # newlines in preceding text | ||
| 408 | 314713 | 128ms | $dirlines = ($dir =~ tr/\n//); # newlines in directive tag | ||
| 409 | 314713 | 97.7ms | $postlines = 0; # newlines chomped after tag | ||
| 410 | |||||
| 411 | 314713 | 284ms | for ($dir) { | ||
| 412 | 314713 | 1.61s | 314713 | 175ms | if (/^\#/) { # spent 175ms making 314713 calls to Template::Parser::CORE:match, avg 557ns/call |
| 413 | # comment out entire directive except for any end chomp flag | ||||
| 414 | $dir = ($dir =~ /($CHOMP_FLAGS)$/o) ? $1 : ''; | ||||
| 415 | } | ||||
| 416 | else { | ||||
| 417 | |||||
| 418 | 314713 | 3.52s | 629426 | 718ms | if(s/^($CHOMP_FLAGS)?(\s*)//so && $2) { # spent 651ms making 314713 calls to Template::Parser::CORE:subst, avg 2µs/call
# spent 67.2ms making 314713 calls to Template::Parser::CORE:regcomp, avg 214ns/call |
| 419 | 314713 | 205ms | my $chomped = $2; | ||
| 420 | 314713 | 180ms | my $linecount = ($chomped =~ tr/\n//); # newlines in chomped whitespace | ||
| 421 | 314713 | 105ms | $linecount ||= 0; | ||
| 422 | 314713 | 56.2ms | $prelines += $linecount; | ||
| 423 | 314713 | 120ms | $dirlines -= $linecount; | ||
| 424 | } | ||||
| 425 | # PRE_CHOMP: process whitespace before tag | ||||
| 426 | 314713 | 173ms | $chomp = $1 ? $1 : $prechomp; | ||
| 427 | 314713 | 149ms | $chomp =~ tr/-=~+/1230/; | ||
| 428 | 314713 | 107ms | if ($chomp && $pre) { | ||
| 429 | # chomp off whitespace and newline preceding directive | ||||
| 430 | 1991 | 1.11ms | if ($chomp == CHOMP_ALL) { | ||
| 431 | 1991 | 27.6ms | 1991 | 6.47ms | $pre =~ s{ (\r?\n|^) [^\S\n]* \z }{}mx; # spent 6.47ms making 1991 calls to Template::Parser::CORE:subst, avg 3µs/call |
| 432 | } | ||||
| 433 | elsif ($chomp == CHOMP_COLLAPSE) { | ||||
| 434 | $pre =~ s{ (\s+) \z }{ }x; | ||||
| 435 | } | ||||
| 436 | elsif ($chomp == CHOMP_GREEDY) { | ||||
| 437 | $pre =~ s{ (\s+) \z }{}x; | ||||
| 438 | } | ||||
| 439 | } | ||||
| 440 | } | ||||
| 441 | |||||
| 442 | # POST_CHOMP: process whitespace after tag | ||||
| 443 | 314713 | 5.32s | 629426 | 3.05s | s/\s*($CHOMP_FLAGS)?\s*$//so; # spent 3.01s making 314713 calls to Template::Parser::CORE:subst, avg 10µs/call
# spent 36.7ms making 314713 calls to Template::Parser::CORE:regcomp, avg 117ns/call |
| 444 | 314713 | 205ms | $chomp = $1 ? $1 : $postchomp; | ||
| 445 | 314713 | 122ms | $chomp =~ tr/-=~+/1230/; | ||
| 446 | 314713 | 215ms | if ($chomp) { | ||
| 447 | 47165 | 32.1ms | if ($chomp == CHOMP_ALL) { | ||
| 448 | 47165 | 364ms | 47165 | 122ms | $text =~ s{ ^ ([^\S\n]* \n) }{}x # spent 122ms making 47165 calls to Template::Parser::CORE:subst, avg 3µs/call |
| 449 | && $postlines++; | ||||
| 450 | } | ||||
| 451 | elsif ($chomp == CHOMP_COLLAPSE) { | ||||
| 452 | $text =~ s{ ^ (\s+) }{ }x | ||||
| 453 | && ($postlines += $1=~y/\n//); | ||||
| 454 | } | ||||
| 455 | # any trailing whitespace | ||||
| 456 | elsif ($chomp == CHOMP_GREEDY) { | ||||
| 457 | $text =~ s{ ^ (\s+) }{}x | ||||
| 458 | && ($postlines += $1=~y/\n//); | ||||
| 459 | } | ||||
| 460 | } | ||||
| 461 | } | ||||
| 462 | |||||
| 463 | # any text preceding the directive can now be added | ||||
| 464 | 314713 | 392ms | if (length $pre) { | ||
| 465 | push(@tokens, $interp | ||||
| 466 | ? [ $pre, $line, 'ITEXT' ] | ||||
| 467 | : ('TEXT', $pre) ); | ||||
| 468 | } | ||||
| 469 | 314713 | 112ms | $line += $prelines; | ||
| 470 | |||||
| 471 | # and now the directive, along with line number information | ||||
| 472 | 314713 | 138ms | if (length $dir) { | ||
| 473 | # the TAGS directive is a compile-time switch | ||||
| 474 | 314713 | 2.72s | 629426 | 472ms | if ($dir =~ /^$tags_dir\s+(.*)/) { # spent 360ms making 314713 calls to Template::Parser::CORE:regcomp, avg 1µs/call
# spent 112ms making 314713 calls to Template::Parser::CORE:match, avg 357ns/call |
| 475 | my @tags = split(/\s+/, $1); | ||||
| 476 | if (scalar @tags > 1) { | ||||
| 477 | ($start, $end, $out) = map { quotemeta($_) } @tags; | ||||
| 478 | $split = $self->text_splitter($start, $end, $out); | ||||
| 479 | } | ||||
| 480 | elsif ($tags = $TAG_STYLE->{ $tags[0] }) { | ||||
| 481 | ($start, $end, $out) = @$tags; | ||||
| 482 | $split = $self->text_splitter($start, $end, $out); | ||||
| 483 | } | ||||
| 484 | else { | ||||
| 485 | warn "invalid TAGS style: $tags[0]\n"; | ||||
| 486 | } | ||||
| 487 | } | ||||
| 488 | else { | ||||
| 489 | # DIRECTIVE is pushed as: | ||||
| 490 | # [ $dirtext, $line_no(s), \@tokens ] | ||||
| 491 | 314713 | 1.16s | 314713 | 21.3s | push(@tokens, # spent 21.3s making 314713 calls to Template::Parser::tokenise_directive, avg 68µs/call |
| 492 | [ $dir, | ||||
| 493 | ($dirlines | ||||
| 494 | ? sprintf("%d-%d", $line, $line + $dirlines) | ||||
| 495 | : $line), | ||||
| 496 | $self->tokenise_directive($dir) ]); | ||||
| 497 | } | ||||
| 498 | } | ||||
| 499 | |||||
| 500 | # update line counter to include directive lines and any extra | ||||
| 501 | # newline chomped off the start of the following text | ||||
| 502 | 314713 | 3.23s | 629426 | 777ms | $line += $dirlines + $postlines; # spent 530ms making 314713 calls to Template::Parser::CORE:subst, avg 2µs/call
# spent 248ms making 314713 calls to Template::Parser::CORE:regcomp, avg 787ns/call |
| 503 | } | ||||
| 504 | |||||
| 505 | # anything remaining in the string is plain text | ||||
| 506 | 376400 | 389ms | push(@tokens, $interp | ||
| 507 | ? [ $text, $line, 'ITEXT' ] | ||||
| 508 | : ( 'TEXT', $text) ) | ||||
| 509 | if length $text; | ||||
| 510 | |||||
| 511 | 376400 | 2.69s | return \@tokens; ## RETURN ## | ||
| 512 | } | ||||
| 513 | |||||
| - - | |||||
| 516 | #------------------------------------------------------------------------ | ||||
| 517 | # interpolate_text($text, $line) | ||||
| 518 | # | ||||
| 519 | # Examines $text looking for any variable references embedded like | ||||
| 520 | # $this or like ${ this }. | ||||
| 521 | #------------------------------------------------------------------------ | ||||
| 522 | |||||
| 523 | # spent 86.4ms (78.9+7.44) within Template::Parser::interpolate_text which was called 1991 times, avg 43µs/call:
# 1991 times (78.9ms+7.44ms) by Template::Parser::tokenise_directive at line 656, avg 43µs/call | ||||
| 524 | 1991 | 2.18ms | my ($self, $text, $line) = @_; | ||
| 525 | 1991 | 3.16ms | my @tokens = (); | ||
| 526 | 1991 | 674µs | my ($pre, $var, $dir); | ||
| 527 | |||||
| 528 | |||||
| 529 | 1991 | 21.4ms | 1991 | 6.75ms | while ($text =~ # spent 6.75ms making 1991 calls to Template::Parser::CORE:match, avg 3µs/call |
| 530 | / | ||||
| 531 | ( (?: \\. | [^\$] ){1,3000} ) # escaped or non-'$' character [$1] | ||||
| 532 | | | ||||
| 533 | ( \$ (?: # embedded variable [$2] | ||||
| 534 | (?: \{ ([^\}]*) \} ) # ${ ... } [$3] | ||||
| 535 | | | ||||
| 536 | ([\w\.]+) # $word [$4] | ||||
| 537 | ) | ||||
| 538 | ) | ||||
| 539 | /gx) { | ||||
| 540 | |||||
| 541 | 1991 | 4.32ms | ($pre, $var, $dir) = ($1, $3 || $4, $2); | ||
| 542 | |||||
| 543 | # preceding text | ||||
| 544 | 1991 | 2.28ms | if (defined($pre) && length($pre)) { | ||
| 545 | 1991 | 2.01ms | $line += $pre =~ tr/\n//; | ||
| 546 | 1991 | 19.5ms | 1991 | 355µs | $pre =~ s/\\\$/\$/g; # spent 355µs making 1991 calls to Template::Parser::CORE:subst, avg 178ns/call |
| 547 | 1991 | 2.72ms | push(@tokens, 'TEXT', $pre); | ||
| 548 | } | ||||
| 549 | # $variable reference | ||||
| 550 | 1991 | 21.3ms | 1991 | 330µs | if ($var) { # spent 330µs making 1991 calls to Template::Parser::CORE:match, avg 166ns/call |
| 551 | $line += $dir =~ tr/\n/ /; | ||||
| 552 | push(@tokens, [ $dir, $line, $self->tokenise_directive($var) ]); | ||||
| 553 | } | ||||
| 554 | # other '$' reference - treated as text | ||||
| 555 | elsif ($dir) { | ||||
| 556 | $line += $dir =~ tr/\n//; | ||||
| 557 | push(@tokens, 'TEXT', $dir); | ||||
| 558 | } | ||||
| 559 | } | ||||
| 560 | |||||
| 561 | 1991 | 16.5ms | return \@tokens; | ||
| 562 | } | ||||
| 563 | |||||
| - - | |||||
| 566 | #------------------------------------------------------------------------ | ||||
| 567 | # tokenise_directive($text) | ||||
| 568 | # | ||||
| 569 | # Called by the private _parse() method when it encounters a DIRECTIVE | ||||
| 570 | # token in the list provided by the split_text() or interpolate_text() | ||||
| 571 | # methods. The directive text is passed by parameter. | ||||
| 572 | # | ||||
| 573 | # The method splits the directive into individual tokens as recognised | ||||
| 574 | # by the parser grammar (see Template::Grammar for details). It | ||||
| 575 | # constructs a list of tokens each represented by 2 elements, as per | ||||
| 576 | # split_text() et al. The first element contains the token type, the | ||||
| 577 | # second the token itself. | ||||
| 578 | # | ||||
| 579 | # The method tokenises the string using a complex (but fast) regex. | ||||
| 580 | # For a deeper understanding of the regex magic at work here, see | ||||
| 581 | # Jeffrey Friedl's excellent book "Mastering Regular Expressions", | ||||
| 582 | # from O'Reilly, ISBN 1-56592-257-3 | ||||
| 583 | # | ||||
| 584 | # Returns a reference to the list of chunks (each one being 2 elements) | ||||
| 585 | # identified in the directive text. On error, the internal _ERROR string | ||||
| 586 | # is set and undef is returned. | ||||
| 587 | #------------------------------------------------------------------------ | ||||
| 588 | |||||
| 589 | # spent 21.3s (16.1+5.12) within Template::Parser::tokenise_directive which was called 314713 times, avg 68µs/call:
# 314713 times (16.1s+5.12s) by Template::Parser::split_text at line 491, avg 68µs/call | ||||
| 590 | 314713 | 182ms | my ($self, $text, $line) = @_; | ||
| 591 | 314713 | 101ms | my ($token, $uctoken, $type, $lookup); | ||
| 592 | 314713 | 247ms | my $lextable = $self->{ LEXTABLE }; | ||
| 593 | 314713 | 211ms | my $style = $self->{ STYLE }->[-1]; | ||
| 594 | 314713 | 412ms | my ($anycase, $start, $end) = @$style{ qw( ANYCASE START_TAG END_TAG ) }; | ||
| 595 | 314713 | 156ms | my @tokens = ( ); | ||
| 596 | |||||
| 597 | 314713 | 3.03s | 316704 | 1.70s | while ($text =~ # spent 1.70s making 316704 calls to Template::Parser::CORE:match, avg 5µs/call |
| 598 | / | ||||
| 599 | # strip out any comments | ||||
| 600 | (\#[^\n]*) | ||||
| 601 | | | ||||
| 602 | # a quoted phrase matches in $3 | ||||
| 603 | (["']) # $2 - opening quote, ' or " | ||||
| 604 | ( # $3 - quoted text buffer | ||||
| 605 | (?: # repeat group (no backreference) | ||||
| 606 | \\\\ # an escaped backslash \\ | ||||
| 607 | | # ...or... | ||||
| 608 | \\\2 # an escaped quote \" or \' (match $1) | ||||
| 609 | | # ...or... | ||||
| 610 | . # any other character | ||||
| 611 | | \n | ||||
| 612 | )*? # non-greedy repeat | ||||
| 613 | ) # end of $3 | ||||
| 614 | \2 # match opening quote | ||||
| 615 | | | ||||
| 616 | # an unquoted number matches in $4 | ||||
| 617 | (-?\d+(?:\.\d+)?) # numbers | ||||
| 618 | | | ||||
| 619 | # filename matches in $5 | ||||
| 620 | ( \/?\w+(?:(?:\/|::?)\w*)+ | \/\w+) | ||||
| 621 | | | ||||
| 622 | # an identifier matches in $6 | ||||
| 623 | (\w+) # variable identifier | ||||
| 624 | | | ||||
| 625 | # an unquoted word or symbol matches in $7 | ||||
| 626 | ( [(){}\[\]:;,\/\\] # misc parenthesis and symbols | ||||
| 627 | # | \-> # arrow operator (for future?) | ||||
| 628 | | [+\-*] # math operations | ||||
| 629 | | \$\{? # dollar with option left brace | ||||
| 630 | | => # like '=' | ||||
| 631 | | [=!<>]?= | [!<>] # eqality tests | ||||
| 632 | | &&? | \|\|? # boolean ops | ||||
| 633 | | \.\.? # n..n sequence | ||||
| 634 | | \S+ # something unquoted | ||||
| 635 | ) # end of $7 | ||||
| 636 | /gmxo) { | ||||
| 637 | |||||
| 638 | # ignore comments to EOL | ||||
| 639 | 1536347 | 345ms | next if $1; | ||
| 640 | |||||
| 641 | # quoted string | ||||
| 642 | 1536347 | 2.32s | if (defined ($token = $3)) { | ||
| 643 | # double-quoted string may include $variable references | ||||
| 644 | 243677 | 175ms | if ($2 eq '"') { | ||
| 645 | 158959 | 736ms | 158959 | 106ms | if ($token =~ /[\$\\]/) { # spent 106ms making 158959 calls to Template::Parser::CORE:match, avg 664ns/call |
| 646 | 1991 | 1.37ms | $type = 'QUOTED'; | ||
| 647 | # unescape " and \ but leave \$ escaped so that | ||||
| 648 | # interpolate_text() doesn't incorrectly treat it | ||||
| 649 | # as a variable reference | ||||
| 650 | # $token =~ s/\\([\\"])/$1/g; | ||||
| 651 | 1991 | 2.66ms | for ($token) { | ||
| 652 | 1991 | 10.2ms | 1991 | 4.44ms | s/\\([^\$nrt])/$1/g; # spent 4.44ms making 1991 calls to Template::Parser::CORE:subst, avg 2µs/call |
| 653 | 1991 | 53.1ms | 5973 | 9.94ms | s/\\([nrt])/$QUOTED_ESCAPES->{ $1 }/ge; # spent 5.01ms making 3982 calls to Template::Parser::CORE:substcont, avg 1µs/call
# spent 4.93ms making 1991 calls to Template::Parser::CORE:subst, avg 2µs/call |
| 654 | } | ||||
| 655 | push(@tokens, ('"') x 2, | ||||
| 656 | 1991 | 14.2ms | 1991 | 86.4ms | @{ $self->interpolate_text($token) }, # spent 86.4ms making 1991 calls to Template::Parser::interpolate_text, avg 43µs/call |
| 657 | ('"') x 2); | ||||
| 658 | 1991 | 1.71ms | next; | ||
| 659 | } | ||||
| 660 | else { | ||||
| 661 | 156968 | 74.4ms | $type = 'LITERAL'; | ||
| 662 | 156968 | 666ms | 156968 | 80.9ms | $token =~ s['][\\']g; # spent 80.9ms making 156968 calls to Template::Parser::CORE:subst, avg 515ns/call |
| 663 | 156968 | 89.1ms | $token = "'$token'"; | ||
| 664 | } | ||||
| 665 | } | ||||
| 666 | else { | ||||
| 667 | 84718 | 19.9ms | $type = 'LITERAL'; | ||
| 668 | 84718 | 37.2ms | $token = "'$token'"; | ||
| 669 | } | ||||
| 670 | } | ||||
| 671 | # number | ||||
| 672 | elsif (defined ($token = $4)) { | ||||
| 673 | $type = 'NUMBER'; | ||||
| 674 | } | ||||
| 675 | elsif (defined($token = $5)) { | ||||
| 676 | $type = 'FILENAME'; | ||||
| 677 | } | ||||
| 678 | elsif (defined($token = $6)) { | ||||
| 679 | # Fold potential keywords to UPPER CASE if the ANYCASE option is | ||||
| 680 | # set, unless (we've got some preceding tokens and) the previous | ||||
| 681 | # token is a DOT op. This prevents the 'last' in 'data.last' | ||||
| 682 | # from being interpreted as the LAST keyword. | ||||
| 683 | 571294 | 229ms | if ($anycase) { | ||
| 684 | # if the token follows a dot or precedes an assignment then | ||||
| 685 | # it's not for folding, e.g. the 'wrapper' in this: | ||||
| 686 | # [% page = { wrapper='html' }; page.wrapper %] | ||||
| 687 | if ((@tokens && $ANYCASE_AFTER->{ $tokens[-2] }) | ||||
| 688 | || ($text =~ /$ANYCASE_BEFORE/gc)) { | ||||
| 689 | # keep the token unmodified | ||||
| 690 | $uctoken = $token; | ||||
| 691 | } | ||||
| 692 | else { | ||||
| 693 | $uctoken = uc $token; | ||||
| 694 | } | ||||
| 695 | } | ||||
| 696 | else { | ||||
| 697 | 571294 | 160ms | $uctoken = $token; | ||
| 698 | } | ||||
| 699 | 571294 | 616ms | if (defined ($type = $lextable->{ $uctoken })) { | ||
| 700 | $token = $uctoken; | ||||
| 701 | } | ||||
| 702 | else { | ||||
| 703 | 431260 | 163ms | $type = 'IDENT'; | ||
| 704 | } | ||||
| 705 | } | ||||
| 706 | elsif (defined ($token = $7)) { | ||||
| 707 | # reserved words may be in lower case unless case sensitive | ||||
| 708 | 707297 | 145ms | $uctoken = $anycase ? uc $token : $token; | ||
| 709 | 707297 | 473ms | unless (defined ($type = $lextable->{ $uctoken })) { | ||
| 710 | $type = 'UNQUOTED'; | ||||
| 711 | } | ||||
| 712 | } | ||||
| 713 | |||||
| 714 | 1534356 | 9.64s | 1534356 | 3.13s | push(@tokens, $type, $token); # spent 3.13s making 1534356 calls to Template::Parser::CORE:match, avg 2µs/call |
| 715 | |||||
| 716 | # print(STDERR " +[ $type, $token ]\n") | ||||
| 717 | # if $DEBUG; | ||||
| 718 | } | ||||
| 719 | |||||
| 720 | # print STDERR "tokenise directive() returning:\n [ @tokens ]\n" | ||||
| 721 | # if $DEBUG; | ||||
| 722 | |||||
| 723 | 314713 | 1.88s | return \@tokens; ## RETURN ## | ||
| 724 | } | ||||
| 725 | |||||
| 726 | |||||
| 727 | #------------------------------------------------------------------------ | ||||
| 728 | # define_block($name, $block) | ||||
| 729 | # | ||||
| 730 | # Called by the parser 'defblock' rule when a BLOCK definition is | ||||
| 731 | # encountered in the template. The name of the block is passed in the | ||||
| 732 | # first parameter and a reference to the compiled block is passed in | ||||
| 733 | # the second. This method stores the block in the $self->{ DEFBLOCK } | ||||
| 734 | # hash which has been initialised by parse() and will later be used | ||||
| 735 | # by the same method to call the store() method on the calling cache | ||||
| 736 | # to define the block "externally". | ||||
| 737 | #------------------------------------------------------------------------ | ||||
| 738 | |||||
| 739 | sub define_block { | ||||
| 740 | my ($self, $name, $block) = @_; | ||||
| 741 | my $defblock = $self->{ DEFBLOCK } | ||||
| 742 | || return undef; | ||||
| 743 | |||||
| 744 | $self->debug("compiled block '$name':\n$block") | ||||
| 745 | if $self->{ DEBUG } & Template::Constants::DEBUG_PARSER; | ||||
| 746 | |||||
| 747 | $defblock->{ $name } = $block; | ||||
| 748 | |||||
| 749 | return undef; | ||||
| 750 | } | ||||
| 751 | |||||
| 752 | sub push_defblock { | ||||
| 753 | my $self = shift; | ||||
| 754 | my $stack = $self->{ DEFBLOCK_STACK } ||= []; | ||||
| 755 | push(@$stack, $self->{ DEFBLOCK } ); | ||||
| 756 | $self->{ DEFBLOCK } = { }; | ||||
| 757 | } | ||||
| 758 | |||||
| 759 | sub pop_defblock { | ||||
| 760 | my $self = shift; | ||||
| 761 | my $defs = $self->{ DEFBLOCK }; | ||||
| 762 | my $stack = $self->{ DEFBLOCK_STACK } || return $defs; | ||||
| 763 | return $defs unless @$stack; | ||||
| 764 | $self->{ DEFBLOCK } = pop @$stack; | ||||
| 765 | return $defs; | ||||
| 766 | } | ||||
| 767 | |||||
| 768 | |||||
| 769 | #------------------------------------------------------------------------ | ||||
| 770 | # add_metadata(\@setlist) | ||||
| 771 | #------------------------------------------------------------------------ | ||||
| 772 | |||||
| 773 | sub add_metadata { | ||||
| 774 | my ($self, $setlist) = @_; | ||||
| 775 | my $metadata = $self->{ METADATA } | ||||
| 776 | || return undef; | ||||
| 777 | |||||
| 778 | push(@$metadata, @$setlist); | ||||
| 779 | |||||
| 780 | return undef; | ||||
| 781 | } | ||||
| 782 | |||||
| 783 | |||||
| 784 | #------------------------------------------------------------------------ | ||||
| 785 | # location() | ||||
| 786 | # | ||||
| 787 | # Return Perl comment indicating current parser file and line | ||||
| 788 | #------------------------------------------------------------------------ | ||||
| 789 | |||||
| 790 | # spent 3.20s (2.84+362ms) within Template::Parser::location which was called 313428 times, avg 10µs/call:
# 313428 times (2.84s+362ms) by Template::Grammar::__ANON__[Parser.yp:79] at line 78 of /root/tor-browser-build/Parser.yp, avg 10µs/call | ||||
| 791 | 313428 | 122ms | my $self = shift; | ||
| 792 | 313428 | 160ms | return "\n" unless $self->{ FILE_INFO }; | ||
| 793 | 313428 | 218ms | my $line = ${ $self->{ LINE } }; | ||
| 794 | 313428 | 242ms | my $info = $self->{ FILEINFO }->[-1]; | ||
| 795 | my $file = $info->{ path } || $info->{ name } | ||||
| 796 | 313428 | 275ms | || '(unknown template)'; | ||
| 797 | 313428 | 1.41s | 313428 | 362ms | $line =~ s/\-.*$//; # might be 'n-n' # spent 362ms making 313428 calls to Template::Parser::CORE:subst, avg 1µs/call |
| 798 | 313428 | 115ms | $line ||= 1; | ||
| 799 | 313428 | 1.43s | return "#line $line \"$file\"\n"; | ||
| 800 | } | ||||
| 801 | |||||
| 802 | |||||
| 803 | #======================================================================== | ||||
| 804 | # ----- PRIVATE METHODS ----- | ||||
| 805 | #======================================================================== | ||||
| 806 | |||||
| 807 | #------------------------------------------------------------------------ | ||||
| 808 | # _parse(\@tokens, \@info) | ||||
| 809 | # | ||||
| 810 | # Parses the list of input tokens passed by reference and returns a | ||||
| 811 | # Template::Directive::Block object which contains the compiled | ||||
| 812 | # representation of the template. | ||||
| 813 | # | ||||
| 814 | # This is the main parser DFA loop. See embedded comments for | ||||
| 815 | # further details. | ||||
| 816 | # | ||||
| 817 | # On error, undef is returned and the internal _ERROR field is set to | ||||
| 818 | # indicate the error. This can be retrieved by calling the error() | ||||
| 819 | # method. | ||||
| 820 | #------------------------------------------------------------------------ | ||||
| 821 | |||||
| 822 | # spent 171s (120+51.0) within Template::Parser::_parse which was called 376400 times, avg 453µs/call:
# 376400 times (120s+51.0s) by Template::Parser::parse at line 359, avg 453µs/call | ||||
| 823 | 376400 | 209ms | my ($self, $tokens, $info) = @_; | ||
| 824 | 376400 | 208ms | my ($token, $value, $text, $line, $inperl); | ||
| 825 | my ($state, $stateno, $status, $action, $lookup, $coderet, @codevars); | ||||
| 826 | my ($lhs, $len, $code); # rule contents | ||||
| 827 | 376400 | 556ms | my $stack = [ [ 0, undef ] ]; # DFA stack | ||
| 828 | |||||
| 829 | # DEBUG | ||||
| 830 | # local $" = ', '; | ||||
| 831 | |||||
| 832 | # retrieve internal rule and state tables | ||||
| 833 | 376400 | 381ms | my ($states, $rules) = @$self{ qw( STATES RULES ) }; | ||
| 834 | |||||
| 835 | # If we're tracing variable usage then we need to give the factory a | ||||
| 836 | # reference to our $self->{ VARIABLES } for it to fill in. This is a | ||||
| 837 | # bit of a hack to back-patch this functionality into TT2. | ||||
| 838 | $self->{ FACTORY }->trace_vars($self->{ VARIABLES }) | ||||
| 839 | 376400 | 373ms | if $self->{ TRACE_VARS }; | ||
| 840 | |||||
| 841 | # call the grammar set_factory method to install emitter factory | ||||
| 842 | 376400 | 1.39s | 376400 | 747ms | $self->{ GRAMMAR }->install_factory($self->{ FACTORY }); # spent 747ms making 376400 calls to Template::Grammar::install_factory, avg 2µs/call |
| 843 | |||||
| 844 | 376400 | 179ms | $line = $inperl = 0; | ||
| 845 | 376400 | 425ms | $self->{ LINE } = \$line; | ||
| 846 | 376400 | 581ms | $self->{ FILE } = $info->{ name }; | ||
| 847 | 376400 | 430ms | $self->{ INPERL } = \$inperl; | ||
| 848 | |||||
| 849 | 376400 | 190ms | $status = CONTINUE; | ||
| 850 | 376400 | 179ms | my $in_string = 0; | ||
| 851 | |||||
| 852 | 376400 | 9.36s | while(1) { | ||
| 853 | # get state number and state | ||||
| 854 | 9928655 | 2.17s | $stateno = $stack->[-1]->[0]; | ||
| 855 | 9928655 | 2.96s | $state = $states->[$stateno]; | ||
| 856 | |||||
| 857 | # see if any lookaheads exist for the current state | ||||
| 858 | 9928655 | 5.39s | if (exists $state->{'ACTIONS'}) { | ||
| 859 | |||||
| 860 | # get next token and expand any directives (i.e. token is an | ||||
| 861 | # array ref) onto the front of the token list | ||||
| 862 | 4616236 | 1.81s | while (! defined $token && @$tokens) { | ||
| 863 | 2665397 | 1.03s | $token = shift(@$tokens); | ||
| 864 | 2665397 | 1.71s | if (ref $token) { | ||
| 865 | 314713 | 338ms | ($text, $line, $token) = @$token; | ||
| 866 | 314713 | 135ms | if (ref $token) { | ||
| 867 | 314713 | 247ms | if ($info->{ DEBUG } && ! $in_string) { | ||
| 868 | # - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 869 | # This is gnarly. Look away now if you're easily | ||||
| 870 | # frightened. We're pushing parse tokens onto the | ||||
| 871 | # pending list to simulate a DEBUG directive like so: | ||||
| 872 | # [% DEBUG msg line='20' text='INCLUDE foo' %] | ||||
| 873 | # - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 874 | my $dtext = $text; | ||||
| 875 | $dtext =~ s[(['\\])][\\$1]g; | ||||
| 876 | unshift(@$tokens, | ||||
| 877 | DEBUG => 'DEBUG', | ||||
| 878 | IDENT => 'msg', | ||||
| 879 | IDENT => 'line', | ||||
| 880 | ASSIGN => '=', | ||||
| 881 | LITERAL => "'$line'", | ||||
| 882 | IDENT => 'text', | ||||
| 883 | ASSIGN => '=', | ||||
| 884 | LITERAL => "'$dtext'", | ||||
| 885 | IDENT => 'file', | ||||
| 886 | ASSIGN => '=', | ||||
| 887 | LITERAL => "'$info->{ name }'", | ||||
| 888 | (';') x 2, | ||||
| 889 | @$token, | ||||
| 890 | (';') x 2); | ||||
| 891 | } | ||||
| 892 | else { | ||||
| 893 | 314713 | 1.22s | unshift(@$tokens, @$token, (';') x 2); | ||
| 894 | } | ||||
| 895 | 314713 | 74.1ms | $token = undef; # force redo | ||
| 896 | } | ||||
| 897 | elsif ($token eq 'ITEXT') { | ||||
| 898 | if ($inperl) { | ||||
| 899 | # don't perform interpolation in PERL blocks | ||||
| 900 | $token = 'TEXT'; | ||||
| 901 | $value = $text; | ||||
| 902 | } | ||||
| 903 | else { | ||||
| 904 | unshift(@$tokens, | ||||
| 905 | @{ $self->interpolate_text($text, $line) }); | ||||
| 906 | $token = undef; # force redo | ||||
| 907 | } | ||||
| 908 | } | ||||
| 909 | } | ||||
| 910 | else { | ||||
| 911 | # toggle string flag to indicate if we're crossing | ||||
| 912 | # a string boundary | ||||
| 913 | 2350684 | 558ms | $in_string = ! $in_string if $token eq '"'; | ||
| 914 | 2350684 | 687ms | $value = shift(@$tokens); | ||
| 915 | } | ||||
| 916 | }; | ||||
| 917 | # clear undefined token to avoid 'undefined variable blah blah' | ||||
| 918 | # warnings and let the parser logic pick it up in a minute | ||||
| 919 | 4616236 | 740ms | $token = '' unless defined $token; | ||
| 920 | |||||
| 921 | # get the next state for the current lookahead token | ||||
| 922 | $action = defined ($lookup = $state->{'ACTIONS'}->{ $token }) | ||||
| 923 | ? $lookup | ||||
| 924 | 4616236 | 3.99s | : defined ($lookup = $state->{'DEFAULT'}) | ||
| 925 | ? $lookup | ||||
| 926 | : undef; | ||||
| 927 | } | ||||
| 928 | else { | ||||
| 929 | # no lookahead actions | ||||
| 930 | 5312419 | 1.39s | $action = $state->{'DEFAULT'}; | ||
| 931 | } | ||||
| 932 | |||||
| 933 | # ERROR: no ACTION | ||||
| 934 | 9928655 | 1.09s | last unless defined $action; | ||
| 935 | |||||
| 936 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 937 | # shift (+ive ACTION) | ||||
| 938 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 939 | 9928655 | 1.57s | if ($action > 0) { | ||
| 940 | 2727084 | 1.58s | push(@$stack, [ $action, $value ]); | ||
| 941 | 2727084 | 596ms | $token = $value = undef; | ||
| 942 | 2727084 | 583ms | redo; | ||
| 943 | }; | ||||
| 944 | |||||
| 945 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 946 | # reduce (-ive ACTION) | ||||
| 947 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 948 | 7201571 | 8.02s | ($lhs, $len, $code) = @{ $rules->[ -$action ] }; | ||
| 949 | |||||
| 950 | # no action imples ACCEPTance | ||||
| 951 | 7201571 | 834ms | $action | ||
| 952 | or $status = ACCEPT; | ||||
| 953 | |||||
| 954 | # use dummy sub if code ref doesn't exist | ||||
| 955 | 2490942 | 15.9s | # spent 1.83s within Template::Parser::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.28/Template/Parser.pm:955] which was called 2490942 times, avg 734ns/call:
# 2490942 times (1.83s+0s) by Template::Parser::_parse at line 963, avg 734ns/call | ||
| 956 | 7201571 | 3.95s | unless $code; | ||
| 957 | |||||
| 958 | @codevars = $len | ||||
| 959 | 7201571 | 9.32s | ? map { $_->[1] } @$stack[ -$len .. -1 ] | ||
| 960 | : (); | ||||
| 961 | |||||
| 962 | 7201571 | 1.96s | eval { | ||
| 963 | 7201571 | 11.4s | 7201571 | 50.2s | $coderet = &$code( $self, @codevars ); # spent 15.4s making 495642 calls to Template::Grammar::__ANON__[Parser.yp:76], avg 31µs/call
# spent 7.08s making 376400 calls to Template::Grammar::__ANON__[Parser.yp:64], avg 19µs/call
# spent 5.53s making 321403 calls to Template::Grammar::__ANON__[Parser.yp:79], avg 17µs/call
# spent 4.75s making 431466 calls to Template::Grammar::__ANON__[Parser.yp:67], avg 11µs/call
# spent 4.59s making 372329 calls to Template::Grammar::__ANON__[Parser.yp:305], avg 12µs/call
# spent 2.66s making 250383 calls to Template::Grammar::__ANON__[Parser.yp:90], avg 11µs/call
# spent 2.37s making 242791 calls to Template::Grammar::__ANON__[Parser.yp:342], avg 10µs/call
# spent 1.83s making 2490942 calls to Template::Parser::__ANON__[Template/Parser.pm:955], avg 734ns/call
# spent 1.11s making 431466 calls to Template::Grammar::__ANON__[Parser.yp:73], avg 3µs/call
# spent 923ms making 385579 calls to Template::Grammar::__ANON__[Parser.yp:72], avg 2µs/call
# spent 739ms making 424294 calls to Template::Grammar::__ANON__[Parser.yp:345], avg 2µs/call
# spent 588ms making 37103 calls to Template::Grammar::__ANON__[Parser.yp:141], avg 16µs/call
# spent 506ms making 285731 calls to Template::Grammar::__ANON__[Parser.yp:382], avg 2µs/call
# spent 423ms making 159453 calls to Template::Grammar::__ANON__[Parser.yp:341], avg 3µs/call
# spent 357ms making 5968 calls to Template::Grammar::__ANON__[Parser.yp:168], avg 60µs/call
# spent 307ms making 249772 calls to Template::Grammar::__ANON__[Parser.yp:387], avg 1µs/call
# spent 130ms making 4031 calls to Template::Grammar::__ANON__[Parser.yp:115], avg 32µs/call
# spent 123ms making 3982 calls to Template::Grammar::__ANON__[Parser.yp:95], avg 31µs/call
# spent 89.7ms making 5968 calls to Template::Grammar::__ANON__[Parser.yp:167], avg 15µs/call
# spent 70.2ms making 6966 calls to Template::Grammar::__ANON__[Parser.yp:113], avg 10µs/call
# spent 67.4ms making 21902 calls to Template::Grammar::__ANON__[Parser.yp:334], avg 3µs/call
# spent 57.0ms making 22050 calls to Template::Grammar::__ANON__[Parser.yp:331], avg 3µs/call
# spent 53.4ms making 28096 calls to Template::Grammar::__ANON__[Parser.yp:152], avg 2µs/call
# spent 49.3ms making 1991 calls to Template::Grammar::__ANON__[Parser.yp:440], avg 25µs/call
# spent 46.9ms making 42940 calls to Template::Grammar::__ANON__[Parser.yp:386], avg 1µs/call
# spent 44.0ms making 22921 calls to Template::Grammar::__ANON__[Parser.yp:358], avg 2µs/call
# spent 43.9ms making 1013 calls to Template::Grammar::__ANON__[Parser.yp:118], avg 43µs/call
# spent 42.1ms making 3982 calls to Template::Grammar::__ANON__[Parser.yp:114], avg 11µs/call
# spent 36.4ms making 18052 calls to Template::Grammar::__ANON__[Parser.yp:302], avg 2µs/call
# spent 29.2ms making 1991 calls to Template::Grammar::__ANON__[Parser.yp:307], avg 15µs/call
# spent 24.9ms making 9007 calls to Template::Grammar::__ANON__[Parser.yp:151], avg 3µs/call
# spent 17.9ms making 6015 calls to Template::Grammar::__ANON__[Parser.yp:361], avg 3µs/call
# spent 15.8ms making 5988 calls to Template::Grammar::__ANON__[Parser.yp:325], avg 3µs/call
# spent 15.2ms making 8013 calls to Template::Grammar::__ANON__[Parser.yp:374], avg 2µs/call
# spent 14.1ms making 2984 calls to Template::Grammar::__ANON__[Parser.yp:175], avg 5µs/call
# spent 11.5ms making 2984 calls to Template::Grammar::__ANON__[Parser.yp:176], avg 4µs/call
# spent 8.12ms making 2988 calls to Template::Grammar::__ANON__[Parser.yp:150], avg 3µs/call
# spent 7.43ms making 1990 calls to Template::Grammar::__ANON__[Parser.yp:360], avg 4µs/call
# spent 6.88ms making 1991 calls to Template::Grammar::__ANON__[Parser.yp:435], avg 3µs/call
# spent 5.54ms making 2016 calls to Template::Grammar::__ANON__[Parser.yp:359], avg 3µs/call
# spent 4.79ms making 1991 calls to Template::Grammar::__ANON__[Parser.yp:299], avg 2µs/call
# spent 4.44ms making 1990 calls to Template::Grammar::__ANON__[Parser.yp:322], avg 2µs/call
# spent 3.56ms making 1991 calls to Template::Grammar::__ANON__[Parser.yp:301], avg 2µs/call
# spent 3.50ms making 1991 calls to Template::Grammar::__ANON__[Parser.yp:436], avg 2µs/call
# spent 3.42ms making 1013 calls to Template::Grammar::__ANON__[Parser.yp:412], avg 3µs/call
# spent 3.08ms making 1013 calls to Template::Grammar::__ANON__[Parser.yp:407], avg 3µs/call
# spent 2.94ms making 998 calls to Template::Grammar::__ANON__[Parser.yp:416], avg 3µs/call
# spent 3µs making 1 call to Template::Grammar::__ANON__[Parser.yp:362] |
| 964 | }; | ||||
| 965 | 7201571 | 731ms | if ($@) { | ||
| 966 | my $err = $@; | ||||
| 967 | chomp $err; | ||||
| 968 | return $self->_parse_error($err); | ||||
| 969 | } | ||||
| 970 | |||||
| 971 | # reduce stack by $len | ||||
| 972 | 7201571 | 3.51s | splice(@$stack, -$len, $len); | ||
| 973 | |||||
| 974 | # ACCEPT | ||||
| 975 | 7201571 | 3.64s | return $coderet ## RETURN ## | ||
| 976 | if $status == ACCEPT; | ||||
| 977 | |||||
| 978 | # ABORT | ||||
| 979 | return undef ## RETURN ## | ||||
| 980 | 6825171 | 1.01s | if $status == ABORT; | ||
| 981 | |||||
| 982 | # ERROR | ||||
| 983 | last | ||||
| 984 | 6825171 | 1.07s | if $status == ERROR; | ||
| 985 | } | ||||
| 986 | continue { | ||||
| 987 | push(@$stack, [ $states->[ $stack->[-1][0] ]->{'GOTOS'}->{ $lhs }, | ||||
| 988 | $coderet ]), | ||||
| 989 | } | ||||
| 990 | |||||
| 991 | # ERROR ## RETURN ## | ||||
| 992 | return $self->_parse_error('unexpected end of input') | ||||
| 993 | unless defined $value; | ||||
| 994 | |||||
| 995 | # munge text of last directive to make it readable | ||||
| 996 | # $text =~ s/\n/\\n/g; | ||||
| 997 | |||||
| 998 | return $self->_parse_error("unexpected end of directive", $text) | ||||
| 999 | if $value eq ';'; # end of directive SEPARATOR | ||||
| 1000 | |||||
| 1001 | return $self->_parse_error("unexpected token ($value)", $text); | ||||
| 1002 | } | ||||
| 1003 | |||||
| - - | |||||
| 1006 | #------------------------------------------------------------------------ | ||||
| 1007 | # _parse_error($msg, $dirtext) | ||||
| 1008 | # | ||||
| 1009 | # Method used to handle errors encountered during the parse process | ||||
| 1010 | # in the _parse() method. | ||||
| 1011 | #------------------------------------------------------------------------ | ||||
| 1012 | |||||
| 1013 | sub _parse_error { | ||||
| 1014 | my ($self, $msg, $text) = @_; | ||||
| 1015 | my $line = $self->{ LINE }; | ||||
| 1016 | $line = ref($line) ? $$line : $line; | ||||
| 1017 | $line = 'unknown' unless $line; | ||||
| 1018 | |||||
| 1019 | $msg .= "\n [% $text %]" | ||||
| 1020 | if defined $text; | ||||
| 1021 | |||||
| 1022 | return $self->error("line $line: $msg"); | ||||
| 1023 | } | ||||
| 1024 | |||||
| 1025 | |||||
| 1026 | #------------------------------------------------------------------------ | ||||
| 1027 | # _dump() | ||||
| 1028 | # | ||||
| 1029 | # Debug method returns a string representing the internal state of the | ||||
| 1030 | # object. | ||||
| 1031 | #------------------------------------------------------------------------ | ||||
| 1032 | |||||
| 1033 | sub _dump { | ||||
| 1034 | my $self = shift; | ||||
| 1035 | my $output = "[Template::Parser] {\n"; | ||||
| 1036 | my $format = " %-16s => %s\n"; | ||||
| 1037 | my $key; | ||||
| 1038 | |||||
| 1039 | foreach $key (qw( START_TAG END_TAG TAG_STYLE ANYCASE INTERPOLATE | ||||
| 1040 | PRE_CHOMP POST_CHOMP V1DOLLAR )) { | ||||
| 1041 | my $val = $self->{ $key }; | ||||
| 1042 | $val = '<undef>' unless defined $val; | ||||
| 1043 | $output .= sprintf($format, $key, $val); | ||||
| 1044 | } | ||||
| 1045 | |||||
| 1046 | $output .= '}'; | ||||
| 1047 | return $output; | ||||
| 1048 | } | ||||
| 1049 | |||||
| 1050 | |||||
| 1051 | 1 | 18µs | 1; | ||
| 1052 | |||||
| 1053 | __END__ | ||||
# spent 5.23s within Template::Parser::CORE:match which was called 2643427 times, avg 2µs/call:
# 1534356 times (3.13s+0s) by Template::Parser::tokenise_directive at line 714, avg 2µs/call
# 316704 times (1.70s+0s) by Template::Parser::tokenise_directive at line 597, avg 5µs/call
# 314713 times (175ms+0s) by Template::Parser::split_text at line 412, avg 557ns/call
# 314713 times (112ms+0s) by Template::Parser::split_text at line 474, avg 357ns/call
# 158959 times (106ms+0s) by Template::Parser::tokenise_directive at line 645, avg 664ns/call
# 1991 times (6.75ms+0s) by Template::Parser::interpolate_text at line 529, avg 3µs/call
# 1991 times (330µs+0s) by Template::Parser::interpolate_text at line 550, avg 166ns/call | |||||
# spent 1.22s within Template::Parser::CORE:qr which was called 751789 times, avg 2µs/call:
# 376400 times (434ms+0s) by Template::Parser::split_text at line 390, avg 1µs/call
# 375387 times (788ms+0s) by Template::Parser::text_splitter at line 299, avg 2µs/call
# once (2µs+0s) by Template::Config::load at line 63
# once (600ns+0s) by Template::Config::load at line 115 | |||||
# spent 2.33s within Template::Parser::CORE:regcomp which was called 2010639 times, avg 1µs/call:
# 376400 times (619ms+0s) by Template::Parser::split_text at line 401, avg 2µs/call
# 375387 times (996ms+0s) by Template::Parser::text_splitter at line 299, avg 3µs/call
# 314713 times (360ms+0s) by Template::Parser::split_text at line 474, avg 1µs/call
# 314713 times (248ms+0s) by Template::Parser::split_text at line 502, avg 787ns/call
# 314713 times (67.2ms+0s) by Template::Parser::split_text at line 418, avg 214ns/call
# 314713 times (36.7ms+0s) by Template::Parser::split_text at line 443, avg 117ns/call | |||||
# spent 6.08s within Template::Parser::CORE:subst which was called 1846064 times, avg 3µs/call:
# 376400 times (1.30s+0s) by Template::Parser::split_text at line 401, avg 3µs/call
# 314713 times (3.01s+0s) by Template::Parser::split_text at line 443, avg 10µs/call
# 314713 times (651ms+0s) by Template::Parser::split_text at line 418, avg 2µs/call
# 314713 times (530ms+0s) by Template::Parser::split_text at line 502, avg 2µs/call
# 313428 times (362ms+0s) by Template::Parser::location at line 797, avg 1µs/call
# 156968 times (80.9ms+0s) by Template::Parser::tokenise_directive at line 662, avg 515ns/call
# 47165 times (122ms+0s) by Template::Parser::split_text at line 448, avg 3µs/call
# 1991 times (6.47ms+0s) by Template::Parser::split_text at line 431, avg 3µs/call
# 1991 times (4.93ms+0s) by Template::Parser::tokenise_directive at line 653, avg 2µs/call
# 1991 times (4.44ms+0s) by Template::Parser::tokenise_directive at line 652, avg 2µs/call
# 1991 times (355µs+0s) by Template::Parser::interpolate_text at line 546, avg 178ns/call | |||||
# spent 5.01ms within Template::Parser::CORE:substcont which was called 3982 times, avg 1µs/call:
# 3982 times (5.01ms+0s) by Template::Parser::tokenise_directive at line 653, avg 1µs/call | |||||
sub Template::Parser::__ANON__; # xsub |