← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:35 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm
StatementsExecuted 5683 statements in 38.0ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
771112.1ms30.1msFoswiki::Infix::Parser::::__ANON__[:299]Foswiki::Infix::Parser::__ANON__[:299]
77116.58ms41.6msFoswiki::Infix::Parser::::_parseFoswiki::Infix::Parser::_parse
182214.69ms6.50msFoswiki::Infix::Parser::::_applyFoswiki::Infix::Parser::_apply
77113.49ms4.61msFoswiki::Infix::Parser::::_initialiseFoswiki::Infix::Parser::_initialise
557612.07ms2.07msFoswiki::Infix::Parser::::CORE:regcompFoswiki::Infix::Parser::CORE:regcomp (opcode)
510211.99ms1.99msFoswiki::Infix::Parser::::CORE:substFoswiki::Infix::Parser::CORE:subst (opcode)
77331.68ms47.9msFoswiki::Infix::Parser::::parseFoswiki::Infix::Parser::parse
536611.51ms1.51msFoswiki::Infix::Parser::::CORE:matchFoswiki::Infix::Parser::CORE:match (opcode)
8922994µs994µsFoswiki::Infix::Parser::::addOperatorFoswiki::Infix::Parser::addOperator
111936µs7.29msFoswiki::Infix::Parser::::BEGIN@26Foswiki::Infix::Parser::BEGIN@26
9841276µs276µsFoswiki::Infix::Parser::::CORE:qrFoswiki::Infix::Parser::CORE:qr (opcode)
311153µs165µsFoswiki::Infix::Parser::::newFoswiki::Infix::Parser::new
11129µs129µsFoswiki::Infix::Parser::::BEGIN@29Foswiki::Infix::Parser::BEGIN@29
11128µs35µsFoswiki::Infix::Parser::::BEGIN@21Foswiki::Infix::Parser::BEGIN@21
11121µs423µsFoswiki::Infix::Parser::::BEGIN@24Foswiki::Infix::Parser::BEGIN@24
11116µs33µsFoswiki::Infix::Parser::::BEGIN@22Foswiki::Infix::Parser::BEGIN@22
11116µs55µsFoswiki::Infix::Parser::::BEGIN@23Foswiki::Infix::Parser::BEGIN@23
11111µs11µsFoswiki::Infix::Parser::::BEGIN@25Foswiki::Infix::Parser::BEGIN@25
1118µs8µsFoswiki::Infix::Parser::::finishFoswiki::Infix::Parser::finish
0000s0sFoswiki::Infix::Parser::::__ANON__[:304]Foswiki::Infix::Parser::__ANON__[:304]
0000s0sFoswiki::Infix::Parser::::onCloseExprFoswiki::Infix::Parser::onCloseExpr
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ package Foswiki::Infix::Parser
6
7A simple [[http://en.wikipedia.org/wiki/LL_parser][LL(1) parser]] that parses infix expressions with nonary,
8unary and binary operators specified using an operator table.
9
10The parser works by examining each token in the input stream from left to right, and constructs
11_parse nodes_ as soon as they are identified. The parser doesn't dictate the type of the parse nodes,
12instead using a _factory_ to generate them. the output from the parser is a
13[[http://en.wikipedia.org/wiki/Parse_tree][parse tree]] built using nodes generated by the node factory.
14
15Escapes are supported in strings, using backslash.
16
17=cut
18
19package Foswiki::Infix::Parser;
20
21249µs242µs
# spent 35µs (28+7) within Foswiki::Infix::Parser::BEGIN@21 which was called: # once (28µs+7µs) by Foswiki::Query::Parser::BEGIN@21 at line 21
use strict;
# spent 35µs making 1 call to Foswiki::Infix::Parser::BEGIN@21 # spent 7µs making 1 call to strict::import
22242µs250µs
# spent 33µs (16+17) within Foswiki::Infix::Parser::BEGIN@22 which was called: # once (16µs+17µs) by Foswiki::Query::Parser::BEGIN@21 at line 22
use warnings;
# spent 33µs making 1 call to Foswiki::Infix::Parser::BEGIN@22 # spent 17µs making 1 call to warnings::import
23247µs293µs
# spent 55µs (16+39) within Foswiki::Infix::Parser::BEGIN@23 which was called: # once (16µs+39µs) by Foswiki::Query::Parser::BEGIN@21 at line 23
use Assert;
# spent 55µs making 1 call to Foswiki::Infix::Parser::BEGIN@23 # spent 38µs making 1 call to Assert::import
24252µs2825µs
# spent 423µs (21+402) within Foswiki::Infix::Parser::BEGIN@24 which was called: # once (21µs+402µs) by Foswiki::Query::Parser::BEGIN@21 at line 24
use Error qw( :try );
# spent 423µs making 1 call to Foswiki::Infix::Parser::BEGIN@24 # spent 402µs making 1 call to Error::import
25240µs111µs
# spent 11µs within Foswiki::Infix::Parser::BEGIN@25 which was called: # once (11µs+0s) by Foswiki::Query::Parser::BEGIN@21 at line 25
use Foswiki::Infix::Error ();
# spent 11µs making 1 call to Foswiki::Infix::Parser::BEGIN@25
262163µs17.29ms
# spent 7.29ms (936µs+6.36) within Foswiki::Infix::Parser::BEGIN@26 which was called: # once (936µs+6.36ms) by Foswiki::Query::Parser::BEGIN@21 at line 26
use Foswiki::Infix::Node ();
# spent 7.29ms making 1 call to Foswiki::Infix::Parser::BEGIN@26
27
28# Set to 1 for debug
2922.53ms2229µs
# spent 129µs (29+100) within Foswiki::Infix::Parser::BEGIN@29 which was called: # once (29µs+100µs) by Foswiki::Query::Parser::BEGIN@21 at line 29
use constant MONITOR_PARSER => 0;
# spent 129µs making 1 call to Foswiki::Infix::Parser::BEGIN@29 # spent 100µs making 1 call to constant::import
30
31=begin TML
32
33---++ ClassMethod new($node_factory, \%options) -> $parser_object
34
35Creates a new infix parser. Operators must be added for it to be useful.
36
37The tokeniser matches tokens in the following order: operators,
38quotes (" and '), numbers, words, brackets. If you have any overlaps (e.g.
39an operator '<' and a bracket operator '<<') then the first choice
40will match.
41
42=$node_factory= needs to be ( the name of a package | an object ) that supports the
43following two functions:
44 * =newLeaf($val, $type)= - create a terminal. $type will be:
45 1 if the terminal matched the =words= specification (see below).
46 2 if it is a number matched the =numbers= specification (see below)
47 3 if it is a quoted string
48 * =newNode($op, @params)= - create a new operator node. @params
49 is a variable-length list of parameters, left to right. $op
50 is a reference to the operator hash in the \@opers list.
51These functions should throw Error::Simple in the event of errors.
52Foswiki::Infix::Node is such a class, ripe for subclassing.
53
54The remaining parameters are named, and specify options that affect the
55behaviour of the parser:
56 1 =words=>qr//= - should be an RE specifying legal words (unquoted
57 terminals that are not operators i.e. names and numbers). By default
58 this is =\w+=.
59 It's ok if operator names match this RE; operators always have precedence
60 over names.
61 2 =numbers=>qr//= - should be an RE specifying legal numbers (unquoted
62 terminals that are not operators or words). By default
63 this is =qr/[+-]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][+-]?\d+)?/=,
64 which matches integers and floating-point numbers. Number
65 matching always takes precedence over word matching (i.e. "1xy" will
66 be parsed as a number followed by a word. A typical usage of this option
67 is when you only want to recognise integers, in which case you would set
68 this to =numbers => qr/\d+/=.
69Strings should always be surrounded by 'single-quotes'. Single quotes in values may
70be escaped using backslash (\).
71
72=cut
73
74
# spent 165µs (153+13) within Foswiki::Infix::Parser::new which was called 3 times, avg 55µs/call: # 3 times (153µs+13µs) by Foswiki::Query::Parser::new at line 102 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Query/Parser.pm, avg 55µs/call
sub new {
7515158µs my ( $class, $options ) = @_;
76
77 my $this = bless(
78 {
79 node_factory => $options->{nodeClass},
80 operators => [],
81 initialised => 0,
82 },
83 $class
84 );
85
86313µs $this->{numbers} =
# spent 13µs making 3 calls to Foswiki::Infix::Parser::CORE:qr, avg 4µs/call
87 defined( $options->{numbers} )
88 ? $options->{numbers}
89 : qr/(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?/;
90
91 $this->{words} =
92 defined( $options->{words} )
93 ? $options->{words}
94 : qr/\w+/;
95
96 return $this;
97}
98
99# Break circular references.
100
# spent 8µs within Foswiki::Infix::Parser::finish which was called: # once (8µs+0s) by Foswiki::Search::finish at line 73 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Search.pm
sub finish {
10119µs my $self = shift;
102
103}
104
105=begin TML
106
107---++ ObjectMethod addOperator($oper)
108Add an operator to the parser.
109
110=$oper= is an object that implements the Foswiki::Infix::OP interface.
111
112=cut
113
114
# spent 994µs within Foswiki::Infix::Parser::addOperator which was called 89 times, avg 11µs/call: # 81 times (909µs+0s) by Foswiki::Query::Parser::new at line 105 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Query/Parser.pm, avg 11µs/call # 8 times (85µs+0s) by Foswiki::If::Parser::new at line 42 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/If/Parser.pm, avg 11µs/call
sub addOperator {
1153561.07ms my ( $this, $op ) = @_;
116 push( @{ $this->{operators} }, $op );
117 $this->{initialised} = 0;
118}
119
120# Initialise on demand before a first parse
121
# spent 4.61ms (3.49+1.12) within Foswiki::Infix::Parser::_initialise which was called 77 times, avg 60µs/call: # 77 times (3.49ms+1.12ms) by Foswiki::Infix::Parser::parse at line 190, avg 60µs/call
sub _initialise {
1229054.77ms my $this = shift;
123
124 return if $this->{initialised};
125
126 # Build operator lists
127 my @stdOpsRE;
128 my @bracketOpsRE;
129 foreach my $op ( @{ $this->{operators} } ) {
130
131 # Build a RE for the operator. Note that operators
132 # that end in \w are terminated with \b
133 my $opre = quotemeta( $op->{name} );
13489267µs $opre .= ( $op->{name} =~ /\w$/ ) ? '\b' : '';
# spent 267µs making 89 calls to Foswiki::Infix::Parser::CORE:match, avg 3µs/call
135 if ( $op->{casematters} ) {
136837µs $op->{InfixParser_RE} = qr/$opre/;
# spent 24µs making 4 calls to Foswiki::Infix::Parser::CORE:regcomp, avg 6µs/call # spent 13µs making 4 calls to Foswiki::Infix::Parser::CORE:qr, avg 3µs/call
137 }
138 else {
139170740µs $op->{InfixParser_RE} = qr/$opre/i;
# spent 507µs making 85 calls to Foswiki::Infix::Parser::CORE:regcomp, avg 6µs/call # spent 233µs making 85 calls to Foswiki::Infix::Parser::CORE:qr, avg 3µs/call
140 }
141 if ( defined( $op->{close} ) ) {
142
143 # bracket op
144 $this->{bracket_ops}->{ lc( $op->{name} ) } = $op;
145
146 $opre = quotemeta( $op->{close} );
147619µs $opre .= ( $op->{close} =~ /\w$/ ) ? '\b' : '';
# spent 19µs making 6 calls to Foswiki::Infix::Parser::CORE:match, avg 3µs/call
148 if ( $op->{casematters} ) {
149 $op->{InfixParser_closeRE} = qr/$opre/;
150 }
151 else {
1521255µs $op->{InfixParser_closeRE} = qr/$opre/i;
# spent 37µs making 6 calls to Foswiki::Infix::Parser::CORE:regcomp, avg 6µs/call # spent 18µs making 6 calls to Foswiki::Infix::Parser::CORE:qr, avg 3µs/call
153 }
154 push( @bracketOpsRE, $op->{InfixParser_RE} );
155 }
156 else {
157 if ( $op->{arity} == 1 ) {
158 $this->{unary_ops}->{ lc( $op->{name} ) } = $op;
159 }
160 else {
161 $this->{standard_ops}->{ lc( $op->{name} ) } = $op;
162 }
163 push( @stdOpsRE, $op->{InfixParser_RE} );
164 }
165 }
166
167 # Build regular expression of all standard operators.
168 $this->{standard_op_REs} = join( '|', @stdOpsRE );
169
170 # and repeat for bracket operators
171 $this->{bracket_op_REs} = join( '|', @bracketOpsRE );
172
173 $this->{initialised} = 1;
174}
175
176=begin TML
177
178---++ ObjectMethod parse($string) -> $parseTree
179Parses =$string=, calling =newLeaf= and =newNode= in the client class
180as necessary to create a parse tree. Returns the result of calling =newNode=
181on the root of the parse.
182
183Throws Foswiki::Infix::Error in the event of parse errors.
184
185=cut
186
187
# spent 47.9ms (1.68+46.2) within Foswiki::Infix::Parser::parse which was called 77 times, avg 622µs/call: # 75 times (1.63ms+42.6ms) by Foswiki::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/IF.pm:43] at line 34 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/IF.pm, avg 589µs/call # once (23µs+2.00ms) by Foswiki::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/QUERY.pm:56] at line 53 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/QUERY.pm # once (27µs+1.68ms) by Foswiki::Search::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Search.pm:137] at line 136 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Search.pm
sub parse {
1883081.52ms my ( $this, $expr ) = @_;
189 my $data = $expr;
190774.61ms $this->_initialise();
# spent 4.61ms making 77 calls to Foswiki::Infix::Parser::_initialise, avg 60µs/call
1917741.6ms return _parse( $this, $expr, \$data );
# spent 41.6ms making 77 calls to Foswiki::Infix::Parser::_parse, avg 541µs/call
192}
193
194# Simple stack parser, after Knuth
195
# spent 41.6ms (6.58+35.1) within Foswiki::Infix::Parser::_parse which was called 77 times, avg 541µs/call: # 77 times (6.58ms+35.1ms) by Foswiki::Infix::Parser::parse at line 191, avg 541µs/call
sub _parse {
1969246.60ms my ( $this, $expr, $input, $term ) = @_;
197
198 throw Foswiki::Infix::Error("Empty expression")
199 unless defined($expr);
20077263µs $$input = "()" unless $$input =~ /\S/;
# spent 263µs making 77 calls to Foswiki::Infix::Parser::CORE:match, avg 3µs/call
201
202 my @opers = ();
203 my @opands = ();
204
205 $input ||= \$expr;
206
207 print STDERR "Parse: $$input\n" if MONITOR_PARSER;
208 my $lastTokWasOper = 1;
209
# spent 30.1ms (12.1+18.1) within Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] which was called 77 times, avg 391µs/call: # 77 times (12.1ms+18.1ms) by Error::subs::try at line 416 of Error.pm, avg 391µs/call
try {
210177216.2ms77229µs while ( $$input =~ /\S/ ) {
# spent 229µs making 77 calls to Foswiki::Infix::Parser::CORE:match, avg 3µs/call
21110173.50ms if ( $$input =~ s/^\s*($this->{standard_op_REs})// ) {
# spent 1.87ms making 456 calls to Foswiki::Infix::Parser::CORE:subst, avg 4µs/call # spent 1.14ms making 341 calls to Foswiki::Infix::Parser::CORE:regcomp, avg 3µs/call # spent 494µs making 220 calls to Foswiki::Infix::Parser::CORE:match, avg 2µs/call
212 my $opname = $1;
213 my $op = $this->{unary_ops}->{ lc($opname) }
214 || $this->{standard_ops}->{ lc($opname) };
215134431µs if ( $lastTokWasOper
# spent 236µs making 67 calls to Foswiki::Infix::Parser::CORE:match, avg 4µs/call # spent 195µs making 67 calls to Foswiki::Infix::Parser::CORE:regcomp, avg 3µs/call
216 && $opname =~ $this->{words}
217 && $op->{arity} > 1 )
218 {
219
220 # op is a word name, and is in an operand position,
221 # and is not unary. Treat it as an operand.
222 push( @opands,
223 $this->{node_factory}
224 ->newLeaf( $opname, Foswiki::Infix::Node::NAME ) );
225 print STDERR "Operand: name '$opname'\n" if MONITOR_PARSER;
226 $lastTokWasOper = 0;
227 next;
228 }
229 if ( $lastTokWasOper && $this->{unary_ops}->{ lc($opname) } ) {
230
231 # Op immediately follows another op, and allows unary.
232 $op = $this->{unary_ops}->{ lc($opname) };
233 }
234 else {
235 $op = $this->{standard_ops}->{ lc($opname) }
236 || $this->{unary_ops}->{ lc($opname) };
237 }
238 print STDERR "Operator: $op\n" if MONITOR_PARSER;
239105429µs ASSERT( $op, $opname ) if DEBUG;
# spent 429µs making 105 calls to Assert::ASSERTS_OFF, avg 4µs/call
2401051.59ms _apply( $this, $op->{prec}, \@opers, \@opands );
# spent 1.59ms making 105 calls to Foswiki::Infix::Parser::_apply, avg 15µs/call
241 push( @opers, $op );
242 $lastTokWasOper = 1;
243 }
244 elsif ( $$input =~ s/^\s*(['"])(|.*?[^\\])\1// ) {
245 my $q = $1;
246 my $val = $2;
247 print STDERR "Operand: qs '$val'\n" if MONITOR_PARSER;
248
249 # Handle escaped characters in the string. This is where
250 # expansions such as \n are handled
251 $val =~
252108281µss/(?<!\\)\\(0[0-7]{2}|x[a-fA-F0-9]{2}|x{[a-fA-F0-9]+}|n|t|\\|$q)/eval('"\\'.$1.'"')/ge;
# spent 164µs making 54 calls to Foswiki::Infix::Parser::CORE:regcomp, avg 3µs/call # spent 116µs making 54 calls to Foswiki::Infix::Parser::CORE:subst, avg 2µs/call
253542.90ms push( @opands,
# spent 2.90ms making 54 calls to Foswiki::Query::Node::newLeaf, avg 54µs/call
254 $this->{node_factory}
255 ->newLeaf( $val, Foswiki::Infix::Node::STRING ) );
256 $lastTokWasOper = 0;
257 }
258 elsif ( $$input =~ s/^\s*($this->{numbers})// ) {
259 my $val = 0 + $1;
260 print STDERR "Operand: number $val\n" if MONITOR_PARSER;
261186µs push( @opands,
# spent 86µs making 1 call to Foswiki::Query::Node::newLeaf
262 $this->{node_factory}
263 ->newLeaf( $val, Foswiki::Infix::Node::NUMBER ) );
264 $lastTokWasOper = 0;
265 }
266 elsif ( $$input =~ s/^\s*($this->{words})// ) {
267 print STDERR "Operand: word '$1'\n" if MONITOR_PARSER;
268 my $val = $1;
269603.69ms push( @opands,
# spent 3.69ms making 60 calls to Foswiki::Query::Node::newLeaf, avg 62µs/call
270 $this->{node_factory}
271 ->newLeaf( $val, Foswiki::Infix::Node::NAME ) );
272 $lastTokWasOper = 0;
273 }
274 elsif ( $$input =~ s/^\s*($this->{bracket_op_REs})// ) {
275 my $opname = $1;
276 print STDERR "Tok: open bracket $opname\n" if MONITOR_PARSER;
277 my $op = $this->{bracket_ops}->{ lc($opname) };
278 ASSERT($op) if DEBUG;
279 _apply( $this, $op->{prec}, \@opers, \@opands );
280 push( @opers, $op );
281 push( @opands,
282 $this->_parse( $expr, $input, $op->{InfixParser_closeRE} )
283 );
284 $lastTokWasOper = 0;
285 }
286 elsif ( defined($term) && $$input =~ s/^\s*$term// ) {
287 print STDERR "Tok: close bracket $term\n" if MONITOR_PARSER;
288
289 # if the operand stack is empty, push an empty array
290 # nonary operator
291 $this->onCloseExpr( \@opands );
292 last;
293 }
294 else {
295 throw Foswiki::Infix::Error( 'Syntax error', $expr, $$input );
296 }
297 }
298774.91ms _apply( $this, 0, \@opers, \@opands );
# spent 4.91ms making 77 calls to Foswiki::Infix::Parser::_apply, avg 64µs/call
299 }
300 catch Error::Simple with {
301
302 # Catch errors thrown during the tree building process
303 throw Foswiki::Infix::Error( shift, $expr, $$input );
3042311.40ms };
# spent 1.07ms making 77 calls to Error::catch, avg 14µs/call # spent 326µs making 77 calls to Error::subs::with, avg 4µs/call # spent 33.4ms making 77 calls to Error::subs::try, avg 434µs/call, recursion: max depth 4, sum of overlapping time 33.4ms
305 throw Foswiki::Infix::Error( 'Missing operator', $expr, $$input )
306 unless scalar(@opands) == 1;
307 throw Foswiki::Infix::Error(
308 'Excess operators (' . join( ' ', map { $_->{name} } @opers ) . ')',
309 $expr, $$input )
310 if scalar(@opers);
311 my $result = pop(@opands);
312 print STDERR "Return " . $result->stringify() . "\n" if MONITOR_PARSER;
313 return $result;
314}
315
316# Apply ops on the stack while their precedence is higher than $prec
317# For each operator on the stack with precedence >= $prec, pop the
318# required number of operands, construct a new parse node and push
319# the node back onto the operand stack.
320
# spent 6.50ms (4.69+1.81) within Foswiki::Infix::Parser::_apply which was called 182 times, avg 36µs/call: # 105 times (1.33ms+261µs) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 240, avg 15µs/call # 77 times (3.37ms+1.55ms) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 298, avg 64µs/call
sub _apply {
32113874.76ms my ( $this, $prec, $opers, $opands ) = @_;
322
323 while (scalar(@$opers)
324 && $opers->[-1]->{prec} >= $prec
325 && scalar(@$opands) >= $opers->[-1]->{arity} )
326 {
327 my $op = pop(@$opers);
328 my $arity = $op->{arity};
329 my @prams;
330 while ( $arity-- ) {
331 unshift( @prams, pop(@$opands) );
332
333 # Should never get thrown, but just in case...
334 throw Foswiki::Infix::Error("Missing operand to '$op->{name}'")
335 unless $prams[0];
336 }
337 if (MONITOR_PARSER) {
338 print STDERR "Apply $op->{name}("
339 . join( ', ', map { $_->stringify() } @prams ) . ")\n";
340 }
341 my $folded;
342 if ( ref( $prams[0]->{op} )
343 && $op == $prams[0]->{op}
344 && $op->{canfold} )
345 {
346 push( @{ $prams[0]->{params} }, $prams[1] );
347 push( @$opands, $prams[0] );
348 }
349 else {
3501041.81ms push( @$opands, $this->{node_factory}->newNode( $op, @prams ) );
# spent 1.81ms making 104 calls to Foswiki::Infix::Node::newNode, avg 17µs/call
351 }
352 }
353}
354
355=begin TML
356
357---++ ObjectMethod onCloseExpr($@opands)
358Designed to be overridden by subclasses that need to perform an action on the
359operand stack (such as pushing) when a sub-expression is closed. Also called
360when the root expression is closed. The default is a no-op.
361
362=cut
363
364sub onCloseExpr {
365 my ( $this, $opands ) = @_;
366}
367
36814µs1;
369__END__
 
# spent 1.51ms within Foswiki::Infix::Parser::CORE:match which was called 536 times, avg 3µs/call: # 220 times (494µs+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 211, avg 2µs/call # 89 times (267µs+0s) by Foswiki::Infix::Parser::_initialise at line 134, avg 3µs/call # 77 times (263µs+0s) by Foswiki::Infix::Parser::_parse at line 200, avg 3µs/call # 77 times (229µs+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 210, avg 3µs/call # 67 times (236µs+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 215, avg 4µs/call # 6 times (19µs+0s) by Foswiki::Infix::Parser::_initialise at line 147, avg 3µs/call
sub Foswiki::Infix::Parser::CORE:match; # opcode
# spent 276µs within Foswiki::Infix::Parser::CORE:qr which was called 98 times, avg 3µs/call: # 85 times (233µs+0s) by Foswiki::Infix::Parser::_initialise at line 139, avg 3µs/call # 6 times (18µs+0s) by Foswiki::Infix::Parser::_initialise at line 152, avg 3µs/call # 4 times (13µs+0s) by Foswiki::Infix::Parser::_initialise at line 136, avg 3µs/call # 3 times (13µs+0s) by Foswiki::Infix::Parser::new at line 86, avg 4µs/call
sub Foswiki::Infix::Parser::CORE:qr; # opcode
# spent 2.07ms within Foswiki::Infix::Parser::CORE:regcomp which was called 557 times, avg 4µs/call: # 341 times (1.14ms+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 211, avg 3µs/call # 85 times (507µs+0s) by Foswiki::Infix::Parser::_initialise at line 139, avg 6µs/call # 67 times (195µs+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 215, avg 3µs/call # 54 times (164µs+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 252, avg 3µs/call # 6 times (37µs+0s) by Foswiki::Infix::Parser::_initialise at line 152, avg 6µs/call # 4 times (24µs+0s) by Foswiki::Infix::Parser::_initialise at line 136, avg 6µs/call
sub Foswiki::Infix::Parser::CORE:regcomp; # opcode
# spent 1.99ms within Foswiki::Infix::Parser::CORE:subst which was called 510 times, avg 4µs/call: # 456 times (1.87ms+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 211, avg 4µs/call # 54 times (116µs+0s) by Foswiki::Infix::Parser::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Infix/Parser.pm:299] at line 252, avg 2µs/call
sub Foswiki::Infix::Parser::CORE:subst; # opcode