File Coverage

blib/lib/HTML/Mason/Compiler.pm
Criterion Covered Total %
statement 305 339 89.9
branch 102 132 77.2
condition 18 29 62.0
subroutine 41 44 93.1
pod 18 25 72.0
total 484 569 85.0


line stmt bran cond sub pod time code
1             # Copyright (c) 1998-2005 by Jonathan Swartz. All rights reserved.
2             # This program is free software; you can redistribute it and/or modify it
3             # under the same terms as Perl itself.
4              
5             package HTML::Mason::Compiler;
6             $HTML::Mason::Compiler::VERSION = '1.60';
7 30     30   226 use strict;
  30         180  
  30         863  
8 30     30   152 use warnings;
  30         55  
  30         991  
9 30     30   20025 use Data::Dumper;
  30         200120  
  30         2294  
10 30     30   13932 use HTML::Mason::Component::FileBased;
  30         92  
  30         863  
11 30     30   13271 use HTML::Mason::Component::Subcomponent;
  30         86  
  30         1075  
12 30     30   226 use HTML::Mason::Exceptions( abbr => [qw(param_error compiler_error syntax_error)] );
  30         70  
  30         211  
13 30     30   14791 use HTML::Mason::Lexer;
  30         79  
  30         1046  
14 30     30   223 use HTML::Mason::Tools qw(checksum);
  30         91  
  30         1821  
15 30     30   218 use Params::Validate qw(:all);
  30         89  
  30         5081  
16             Params::Validate::validation_options( on_fail => sub { param_error join '', @_ } );
17              
18 30     30   360 use Class::Container;
  30         76  
  30         602  
19 30     30   146 use base qw(Class::Container);
  30         72  
  30         8245  
20              
21             BEGIN
22             {
23 30     30   1027 __PACKAGE__->valid_params
24             (
25             allow_globals =>
26             { parse => 'list', type => ARRAYREF, default => [],
27             descr => "An array of names of Perl variables that are allowed globally within components" },
28              
29             default_escape_flags =>
30             { parse => 'string', type => SCALAR|ARRAYREF, default => [],
31             descr => "Escape flags that will apply by default to all Mason tag output" },
32              
33             enable_autoflush =>
34             { parse => 'boolean', type => SCALAR, default => 1,
35             descr => "Whether to include support for autoflush when compiling components" },
36              
37             lexer =>
38             { isa => 'HTML::Mason::Lexer',
39             descr => "A Lexer object that will scan component text during compilation" },
40              
41             preprocess =>
42             { parse => 'code', type => CODEREF, optional => 1,
43             descr => "A subroutine through which all component text will be sent during compilation" },
44              
45             postprocess_perl =>
46             { parse => 'code', type => CODEREF, optional => 1,
47             descr => "A subroutine through which all Perl code will be sent during compilation" },
48              
49             postprocess_text =>
50             { parse => 'code', type => CODEREF, optional => 1,
51             descr => "A subroutine through which all plain text will be sent during compilation" },
52              
53             use_source_line_numbers =>
54             { parse => 'boolean', type => SCALAR, default => 1,
55             descr => "Whether to use source line numbers in errors and debugger" },
56             );
57              
58 30         1441 __PACKAGE__->contained_objects
59             ( lexer => { class => 'HTML::Mason::Lexer',
60             descr => "This class generates compiler events based on the components source" },
61             );
62              
63             # Define an IN_PERL_DB compile-time constant indicating whether we are
64             # in the Perl debugger. This is used in the object file to
65             # determine whether to call $m->debug_hook.
66             #
67 30 50       586 if (defined($DB::sub)) {
68 0         0 *IN_PERL_DB = sub () { 1 };
69             } else {
70 30         1484 *IN_PERL_DB = sub () { 0 };
71             }
72             }
73              
74             use HTML::Mason::MethodMaker
75 30         266 ( read_only => [qw(
76             enable_autoflush
77             lexer
78             object_id
79             preprocess
80             postprocess_perl
81             postprocess_text
82             use_source_line_numbers
83             )
84             ],
85 30     30   259 );
  30         80  
86              
87             my $old_escape_re = qr/^[hnu]+$/;
88              
89             sub new
90             {
91 391     391 1 188396 my $class = shift;
92 391         1873 my $self = $class->SUPER::new(@_);
93              
94             $self->default_escape_flags( $self->{default_escape_flags} )
95 391 50       106362 if defined $self->{default_escape_flags};
96              
97             # Verify the validity of the global names
98 391         654 $self->allow_globals( @{$self->{allow_globals}} );
  391         1955  
99              
100             # Compute object_id once, on the assumption that all of compiler's
101             # and lexer's parameters are read-only.
102 391         1507 $self->compute_object_id;
103            
104 391         1246 return $self;
105             }
106              
107             sub compute_object_id
108             {
109 391     391 0 656 my $self = shift;
110              
111             # Can't use object keys because they stringify differently every
112             # time the program is loaded, whether they are a reference to the
113             # same object or not.
114 391         1226 my $spec = $self->validation_spec;
115             my @id_keys =
116 6648   66     19190 ( grep { ! exists $spec->{$_}{isa} && ! exists $spec->{$_}{can} }
117 391         5097 grep { $_ ne 'container' } keys %$spec );
  7039         11318  
118              
119 391         1303 my @vals = ('HTML::Mason::VERSION', $HTML::Mason::VERSION);
120 391         2913 foreach my $k ( sort @id_keys ) {
121 6257         10277 push @vals, $k, $self->{$k};
122             }
123 391         3179 my $dumped_vals = Data::Dumper->new(\@vals)->Indent(0)->Sortkeys(1)->Dump;
124 391         61509 $self->{object_id} = checksum($dumped_vals);
125             }
126              
127             my %top_level_only_block = map { $_ => 1 } qw( cleanup once shared );
128             my %valid_comp_flag = map { $_ => 1 } qw( inherit );
129              
130             sub add_allowed_globals
131             {
132 12     12 0 24 my $self = shift;
133 12         34 my @globals = @_;
134              
135 12 50       31 if ( my @bad = grep { ! /^[\$@%]/ } @globals )
  12         101  
136             {
137 0         0 param_error "add_allowed_globals: bad parameters '@bad', must begin with one of \$, \@, %\n";
138             }
139              
140 12         29 $self->{allow_globals} = [ sort keys %{ { map { $_ => 1 } @globals, @{ $self->{allow_globals} } } } ];
  12         21  
  12         79  
  12         30  
141 12         36 return @{ $self->{allow_globals} };
  12         35  
142             }
143              
144             sub allow_globals
145             {
146 922     922 1 1520 my $self = shift;
147              
148 922 100       2170 if (@_)
149             {
150 5         14 $self->{allow_globals} = [];
151 5 50 33     54 return if @_ == 1 and not defined $_[0]; # @_ is (undef)
152 5         33 $self->add_allowed_globals(@_);
153             }
154              
155 922         1362 return @{ $self->{allow_globals} };
  922         3853  
156             }
157              
158             sub default_escape_flags
159             {
160 413     413 1 848 my $self = shift;
161              
162 413 100       1239 return $self->{default_escape_flags} unless @_;
163              
164 391         675 my $flags = shift;
165              
166 391 50       965 unless ( defined $flags )
167             {
168 0         0 $self->{default_escape_flags} = [];
169 0         0 return;
170             }
171              
172             # make sure this is always an arrayref
173 391 100       1068 unless ( ref $flags )
174             {
175 4 50       33 if ( $flags =~ /^[hu]+$/ )
176             {
177 4         20 $self->{default_escape_flags} = [ split //, $flags ];
178             }
179             else
180             {
181 0         0 $self->{default_escape_flags} = [ $flags ];
182             }
183             }
184              
185 391         787 return $self->{default_escape_flags};
186             }
187              
188             sub compile
189             {
190 547     547 1 984 my $self = shift;
191 547         20393 my %p = validate( @_, { comp_source => { type => SCALAR|SCALARREF },
192             name => { type => SCALAR },
193             comp_path => { type => SCALAR },
194             fh => { type => HANDLE, optional => 1 },
195             } );
196 547 100       5197 my $src = ref($p{comp_source}) ? $p{comp_source} : \$p{comp_source};
197              
198             # The current compile - initially the main component, then each subcomponent/method
199 547         1582 local $self->{current_compile} = {};
200            
201             # Useful for implementing features that affect both main body and methods/subcomps
202 547         1253 local $self->{main_compile} = $self->{current_compile};
203              
204             # So we're re-entrant in subcomps
205 547         1166 local $self->{paused_compiles} = [];
206              
207 547         1145 local $self->{comp_path} = $p{comp_path};
208              
209             # Preprocess the source. The preprocessor routine is handed a
210             # reference to the entire source.
211 547 100       1857 if ($self->preprocess)
212             {
213 1         12 eval { $self->preprocess->( $src ) };
  1         4  
214 1 50       32 compiler_error "Error during custom preprocess step: $@" if $@;
215             }
216              
217 547         1506 $self->lexer->lex( comp_source => $src, name => $p{name}, compiler => $self );
218              
219 530 100       2712 return $self->compiled_component( exists($p{fh}) ? (fh => $p{fh}) : () );
220             }
221              
222             sub start_component
223             {
224 547     547 1 992 my $self = shift;
225 547         915 my $c = $self->{current_compile};
226              
227 547         1118 $c->{in_main} = 1;
228              
229 547         1011 $c->{in_block} = undef;
230              
231 547         1446 $self->_init_comp_data($c);
232             }
233              
234             sub _init_comp_data
235             {
236 661     661   1006 my $self = shift;
237 661         920 my $data = shift;
238              
239 661         1363 $data->{body} = '';
240 661         1166 $data->{last_body_code_type} = '';
241              
242 661         1393 foreach ( qw( def method ) )
243             {
244 1322         3239 $data->{$_} = {};
245             }
246              
247 661         1321 $data->{args} = [];
248 661         1855 $data->{flags} = {};
249 661         1457 $data->{attr} = {};
250              
251 661         1320 $data->{comp_with_content_stack} = [];
252              
253 661         1283 foreach ( qw( cleanup filter init once shared ) )
254             {
255 3305         7529 $data->{blocks}{$_} = [];
256             }
257             }
258              
259             sub end_component
260             {
261 547     547 1 932 my $self = shift;
262 547         906 my $c = $self->{current_compile};
263              
264             $self->lexer->throw_syntax_error("Not enough component-with-content ending tags found")
265 547 100       785 if @{ $c->{comp_with_content_stack} };
  547         2015  
266             }
267              
268             sub start_block
269             {
270 265     265 1 462 my $self = shift;
271 265         484 my $c = $self->{current_compile};
272 265         799 my %p = @_;
273              
274             $self->lexer->throw_syntax_error("Cannot define a $p{block_type} section inside a method or subcomponent")
275 265 50 66     1102 if $top_level_only_block{ $p{block_type} } && ! $c->{in_main};
276              
277             $self->lexer->throw_syntax_error("Cannot nest a $p{block_type} inside a $c->{in_block} block")
278 265 50       666 if $c->{in_block};
279              
280 265         803 $c->{in_block} = $p{block_type};
281             }
282              
283             sub raw_block
284             {
285             # These blocks contain Perl code - so don't include <%text> and so on.
286              
287 163     163 0 444 my $self = shift;
288 163         387 my $c = $self->{current_compile};
289 163         591 my %p = @_;
290              
291 163 100       318 eval { $self->postprocess_perl->( \$p{block} ) if $self->postprocess_perl };
  163         492  
292 163 50       442 compiler_error $@ if $@;
293              
294 163         440 my $method = "$p{block_type}_block";
295 163 100       1189 return $self->$method(%p) if $self->can($method);
296              
297 129         341 my $comment = '';
298 129 50 33     339 if ( $self->lexer->line_number && $self->use_source_line_numbers )
299             {
300 129         354 my $line = $self->lexer->line_number;
301 129         409 my $file = $self->_escape_filename( $self->lexer->name );
302 129         533 $comment = qq{#line $line "$file"\n};
303             }
304              
305 129         231 push @{ $self->{current_compile}{blocks}{ $p{block_type} } }, "$comment$p{block}";
  129         669  
306             }
307              
308             sub doc_block
309       2 0   {
310             # Don't do anything - just discard the comment.
311             }
312              
313             sub perl_block
314             {
315 34     34 0 77 my $self = shift;
316 34         110 my %p = @_;
317              
318 34         166 $self->_add_body_code( $p{block} );
319              
320 34         205 $self->{current_compile}{last_body_code_type} = 'perl_block';
321             }
322              
323             sub text
324             {
325 1133     1133 1 3761 my ($self, %p) = @_;
326 1133 100       3145 my $tref = ref($p{text}) ? $p{text} : \$p{text}; # Allow a reference
327              
328 1133 100       3068 eval { $self->postprocess_text->($tref) } if $self->postprocess_text;
  5         11  
329 1133 50       2339 compiler_error $@ if $@;
330              
331 1133         2772 $$tref =~ s,([\'\\]),\\$1,g;
332              
333 1133 100       2614 if ($self->enable_autoflush) {
334 1115         2663 $self->_add_body_code("\$m->print( '", $$tref, "' );\n");
335             } else {
336 18         59 $self->_add_body_code("\$\$_outbuf .= '", $$tref, "';\n");
337             }
338              
339 1133         3286 $self->{current_compile}{last_body_code_type} = 'text';
340             }
341              
342             sub text_block
343             {
344 2     2 0 9 my $self = shift;
345 2         10 my %p = @_;
346 2         11 $self->text(text => \$p{block});
347             }
348              
349             sub end_block
350             {
351 263     263 1 471 my $self = shift;
352 263         483 my $c = $self->{current_compile};
353 263         690 my %p = @_;
354              
355             $self->lexer->throw_syntax_error("End of $p{block_type} encountered while in $c->{in_block} block")
356 263 50       770 unless $c->{in_block} eq $p{block_type};
357              
358 263         836 $c->{in_block} = undef;
359             }
360              
361             sub variable_declaration
362             {
363 85     85 1 171 my $self = shift;
364 85         459 my %p = @_;
365              
366             $self->lexer->throw_syntax_error("variable_declaration called inside a $p{block_type} block")
367 85 50       340 unless $p{block_type} eq 'args';
368              
369 85         237 my $arg = "$p{type}$p{name}";
370              
371             $self->lexer->throw_syntax_error("$arg already defined")
372 85 50       135 if grep { "$_->{type}$_->{name}" eq $arg } @{ $self->{current_compile}{args} };
  56         196  
  85         296  
373              
374 85         364 push @{ $self->{current_compile}{args} }, { type => $p{type},
375             name => $p{name},
376             default => $p{default},
377 85         154 line => $self->lexer->line_number,
378             file => $self->lexer->name,
379             };
380             }
381              
382             sub key_value_pair
383             {
384 62     62 1 110 my $self = shift;
385 62         467 my %p = @_;
386              
387             compiler_error "key_value_pair called inside a $p{block_type} block"
388 62 50 66     296 unless $p{block_type} eq 'flags' || $p{block_type} eq 'attr';
389              
390 62 100       222 my $type = $p{block_type} eq 'flags' ? 'flag' : 'attribute';
391             $self->lexer->throw_syntax_error("$p{key} $type already defined")
392 62 50       215 if exists $self->{current_compile}{ $p{block_type} }{ $p{key} };
393              
394             $self->{current_compile}{ $p{block_type} }{ $p{key} } = $p{value}
395 62         313 }
396              
397             sub start_named_block
398             {
399 119     119 1 236 my $self = shift;
400 119         358 my $c = $self->{current_compile};
401 119         414 my %p = @_;
402              
403             # Error if defining one def or method inside another
404             $self->lexer->throw_syntax_error
405             ("Cannot define a $p{block_type} block inside a method or subcomponent")
406 119 50       327 unless $c->{in_main};
407              
408             # Error for invalid character in name
409             $self->lexer->throw_syntax_error("Invalid $p{block_type} name: $p{name}")
410 119 100       472 if $p{name} =~ /[^.\w-]/;
411              
412             # Error if two defs or two methods defined with same name
413             $self->lexer->throw_syntax_error
414             (sprintf("Duplicate definition of %s '%s'",
415             $p{block_type} eq 'def' ? 'subcomponent' : 'method', $p{name}))
416 117 100       412 if exists $c->{$p{block_type}}{ $p{name} };
    100          
417            
418             # Error if def and method defined with same name
419 115 100       392 my $other_type = $p{block_type} eq 'def' ? 'method' : 'def';
420             $self->lexer->throw_syntax_error
421             ("Cannot define a method and subcomponent with the same name ($p{name})")
422 115 100       390 if exists $c->{$other_type}{ $p{name} };
423              
424 114         204 $c->{in_main}--;
425              
426 114         455 $c->{ $p{block_type} }{ $p{name} } = {};
427 114         501 $self->_init_comp_data( $c->{ $p{block_type} }{ $p{name} } );
428 114         213 push @{$self->{paused_compiles}}, $c;
  114         338  
429 114         311 $self->{current_compile} = $c->{ $p{block_type} }{ $p{name} };
430 114         670 $self->{current_compile}->{in_named_block} = {block_type => $p{block_type}, name => $p{name}};
431             }
432              
433             sub end_named_block
434             {
435 113     113 1 204 my $self = shift;
436              
437 113         327 delete $self->{current_compile}->{in_named_block};
438 113         179 $self->{current_compile} = pop @{$self->{paused_compiles}};
  113         314  
439 113         281 $self->{current_compile}{in_main}++;
440             }
441              
442             sub substitution
443             {
444 387     387 1 671 my $self = shift;
445 387         1550 my %p = @_;
446              
447 387         838 my $text = $p{substitution};
448              
449             # This is a comment tag if all lines of text contain only whitespace
450             # or start with whitespace and a comment marker, e.g.
451             #
452             # <%
453             # #
454             # # foo
455             # %>
456             #
457 387         1234 my @lines = split(/\n/, $text);
458 387 100       789 unless (grep { /^\s*[^\s\#]/ } @lines) {
  394         2349  
459 4         30 $self->{current_compile}{last_body_code_type} = 'substitution';
460 4         21 return;
461             }
462              
463 383 100 66     1863 if ( ( exists $p{escape} && defined $p{escape} ) ||
      100        
464 361         1167 @{ $self->{default_escape_flags} }
465             )
466             {
467 29         48 my @flags;
468 29 100       73 if ( defined $p{escape} )
469             {
470 22         59 $p{escape} =~ s/\s+$//;
471              
472 22 100       149 if ( $p{escape} =~ /$old_escape_re/ )
473             {
474 14         42 @flags = split //, $p{escape};
475             }
476             else
477             {
478 8         39 @flags = split /\s*,\s*/, $p{escape};
479             }
480             }
481              
482             # is there any way to check the flags for validity and still
483             # allow them to be dynamically set from components?
484              
485 22         54 unshift @flags, @{ $self->default_escape_flags }
486 29 100       67 unless grep { $_ eq 'n' } @flags;
  28         92  
487              
488 29         70 my %seen;
489             my $flags =
490             ( join ', ',
491 32 100       143 map { $seen{$_}++ ? () : "'$_'" }
492 29         48 grep { $_ ne 'n' } @flags
  39         92  
493             );
494              
495 29 100       135 $text = "(map {; \$m->interp->apply_escapes(\$_, $flags) } ($text))"
496             if $flags;
497             }
498              
499 383         677 my $code;
500              
501             # Make sure to allow lists within <% %> tags.
502             #
503 383 100       1056 if ($self->enable_autoflush) {
504 375         928 $code = "\$m->print( $text );\n";
505             } else {
506             # more efficient output form when autoflush is disabled. only
507             # output defined bits, which is what $m->print does internally
508             # as well. use 'if defined' for maximum efficiency; grep
509             # creates a list.
510 8         25 $code = "for ( $text ) { \$\$_outbuf .= \$_ if defined }\n";
511             }
512              
513 383 100       951 eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  3         11  
514 383 50       930 compiler_error $@ if $@;
515              
516 383         1018 $self->_add_body_code($code);
517              
518 383         1298 $self->{current_compile}{last_body_code_type} = 'substitution';
519             }
520              
521             sub component_call
522             {
523 216     216 1 441 my $self = shift;
524 216         665 my %p = @_;
525              
526 216         1278 my ($prespace, $call, $postspace) = ($p{call} =~ /(\s*)(.*)(\s*)/s);
527 216 100       903 if ( $call =~ m,^[\w/.],)
528             {
529 203         517 my $comma = index($call, ',');
530 203 100       498 $comma = length $call if $comma == -1;
531 203         1026 (my $comp = substr($call, 0, $comma)) =~ s/\s+$//;
532 203         705 $call = "'$comp'" . substr($call, $comma);
533             }
534 216         582 my $code = "\$m->comp( $prespace $call $postspace \n); ";
535 216 50       640 eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  0         0  
536 216 50       505 compiler_error $@ if $@;
537              
538 216         631 $self->_add_body_code($code);
539              
540 216         669 $self->{current_compile}{last_body_code_type} = 'component_call';
541             }
542              
543             sub component_content_call
544             {
545 39     39 1 72 my $self = shift;
546 39         73 my $c = $self->{current_compile};
547 39         107 my %p = @_;
548              
549 39         74 my $call = $p{call};
550 39         86 for ($call) { s/^\s+//; s/\s+$//; }
  39         151  
  39         199  
551 39         70 push @{ $c->{comp_with_content_stack} }, $call;
  39         119  
552              
553 39         116 my $code = "\$m->comp( { content => sub {\n";
554 39         134 $code .= $self->_set_buffer();
555              
556 39 50       113 eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  0         0  
557 39 50       83 compiler_error $@ if $@;
558              
559 39         122 $self->_add_body_code($code);
560              
561 39         121 $c->{last_body_code_type} = 'component_content_call';
562             }
563              
564             sub component_content_call_end
565             {
566 39     39 1 65 my $self = shift;
567 39         89 my $c = $self->{current_compile};
568 39         116 my %p = @_;
569              
570             $self->lexer->throw_syntax_error("Found component with content ending tag but no beginning tag")
571 39 100       56 unless @{ $c->{comp_with_content_stack} };
  39         118  
572              
573 37         57 my $call = pop @{ $c->{comp_with_content_stack} };
  37         91  
574 37         70 my $call_end = $p{call_end};
575 37         67 for ($call_end) { s/^\s+//; s/\s+$//; }
  37         72  
  37         72  
576              
577 37         83 my $comp = undef;
578 37 100       124 if ( $call =~ m,^[\w/.],)
579             {
580 33         91 my $comma = index($call, ',');
581 33 100       84 $comma = length $call if $comma == -1;
582 33         108 ($comp = substr($call, 0, $comma)) =~ s/\s+$//;
583 33         106 $call = "'$comp'" . substr($call, $comma);
584             }
585 37 100       82 if ($call_end) {
586 7 100       30 if ($call_end !~ m,^[\w/.],) {
587 2         11 $self->lexer->throw_syntax_error("Cannot use an expression inside component with content ending tag; use a bare component name or instead");
588             }
589 5 100       21 if (!defined($comp)) {
590 1         4 $self->lexer->throw_syntax_error("Cannot match an expression as a component name; use instead");
591             }
592 4 100       11 if ($call_end ne $comp) {
593 1         4 $self->lexer->throw_syntax_error("Component name in ending tag ($call_end) does not match component name in beginning tag ($comp)");
594             }
595             }
596              
597 33         106 my $code = "} }, $call\n );\n";
598              
599 33 50       92 eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  0         0  
600 33 50       69 compiler_error $@ if $@;
601              
602 33         88 $self->_add_body_code($code);
603              
604 33         122 $c->{last_body_code_type} = 'component_content_call_end';
605             }
606              
607             sub perl_line
608             {
609 395     395 1 635 my $self = shift;
610 395         1361 my %p = @_;
611              
612 395         992 my $code = "$p{line}\n";
613              
614 395 100       1014 eval { $self->postprocess_perl->(\$code) } if $self->postprocess_perl;
  1         4  
615 395 50       913 compiler_error $@ if $@;
616              
617 395         991 $self->_add_body_code($code);
618              
619 395         1175 $self->{current_compile}{last_body_code_type} = 'perl_line';
620             }
621              
622             sub _add_body_code
623             {
624 2233     2233   3317 my $self = shift;
625              
626             # We know a perl-line is always _one_ line, so we know that the
627             # line numbers are going to match up as long as the first line in
628             # a series has a line number comment before it. Adding a comment
629             # can break certain constructs like qw() list that spans multiple
630             # perl-lines.
631 2233 100 66     4696 if ( $self->lexer->line_number &&
      100        
632             $self->{current_compile}{last_body_code_type} ne 'perl_line' &&
633             $self->use_source_line_numbers )
634             {
635 1926         3891 my $line = $self->lexer->line_number;
636 1926         4099 my $file = $self->_escape_filename( $self->lexer->name );
637 1926         6649 $self->{current_compile}{body} .= qq{#line $line "$file"\n};
638             }
639              
640 2233         8177 $self->{current_compile}{body} .= $_ foreach @_;
641             }
642              
643             sub _escape_filename
644             {
645 2133     2133   3134 my $self = shift;
646 2133         2949 my $file = shift;
647              
648 2133         4247 $file =~ s/\"//g;
649              
650 2133         3641 return $file;
651             }
652              
653             sub dump
654             {
655 0     0 0 0 my $self = shift;
656 0         0 my $c = $self->{current_compile};
657              
658 0         0 warn "Main component\n";
659              
660 0         0 $self->_dump_data( $c );
661              
662 0         0 foreach ( keys %{ $c->{def} } )
  0         0  
663             {
664 0         0 warn " Subcomponent $_\n";
665 0         0 $self->_dump_data( $c->{def}{$_}, ' ' );
666             }
667              
668 0         0 foreach ( keys %{ $c->{method} } )
  0         0  
669             {
670 0         0 warn " Methods $_\n";
671 0         0 $self->_dump_data( $c->{method}{$_}, ' ');
672             }
673             }
674              
675             sub _dump_data
676             {
677 0     0   0 my $self = shift;
678 0         0 my $data = shift;
679 0   0     0 my $indent = shift || '';
680              
681 0 0       0 if ( @{ $data->{args} } )
  0         0  
682             {
683 0         0 warn "$indent args\n";
684 0         0 foreach ( @{ $data->{args} } )
  0         0  
685             {
686 0         0 warn "$indent $_->{type}$_->{name}";
687 0 0       0 warn " => $_->{default}" if defined $_->{default};
688 0         0 warn "\n";
689             }
690             }
691              
692 0         0 warn "\n$indent body\n";
693 0         0 warn $data->{body}, "\n";
694             }
695              
696             sub _blocks
697             {
698 5566     5566   7687 my $self = shift;
699              
700 5566         6739 return @{ $self->{current_compile}{blocks}{ shift() } };
  5566         16844  
701             }
702              
703             sub HTML::Mason::Parser::new
704             {
705 0     0     die "The Parser module is no longer a part of HTML::Mason. Please see ".
706             "the Lexer and Compiler modules, its replacements.\n";
707             }
708              
709             1;
710              
711             __END__