#!/usr/bin/env perl #BOOTSTRAP-BEGIN # This is the standalone Jemplate compiler. # # All you need is this program and the program called `perl`. You don't need # to install any Perl modules. # # If you downloaded this program from the internet, don't forget to put it in # your path and make sure it is executable. Like this: # # mv jemplate /usr/local/bin/ # chmod +x /usr/local/bin/jemplate # # Try this command to make sure it works: # # jemplate --help use Config; BEGIN { @INC = ( $Config::Config{archlib}, $Config::Config{privlib}, ); } use strict; use warnings; # # Inline include of Number/Compare.pm # BEGIN { $INC{'Number/Compare.pm'} = 'dummy/Number/Compare.pm'; } BEGIN { #line 0 "Number/Compare.pm" package Number::Compare; use strict; use Carp qw(croak); use vars qw/$VERSION/; $VERSION = '0.01'; sub new { my $referent = shift; my $class = ref $referent || $referent; my $expr = $class->parse_to_perl( shift ); bless eval "sub { \$_[0] $expr }", $class; } sub parse_to_perl { shift; my $test = shift; $test =~ m{^ ([<>]=?)? # comparison (.*?) # value ([kmg]i?)? # magnitude $}ix or croak "don't understand '$test' as a test"; my $comparison = $1 || '=='; my $target = $2; my $magnitude = $3; $target *= 1000 if lc $magnitude eq 'k'; $target *= 1024 if lc $magnitude eq 'ki'; $target *= 1000000 if lc $magnitude eq 'm'; $target *= 1024*1024 if lc $magnitude eq 'mi'; $target *= 1000000000 if lc $magnitude eq 'g'; $target *= 1024*1024*1024 if lc $magnitude eq 'gi'; return "$comparison $target"; } sub test { $_[0]->( $_[1] ) } 1; } # # Inline include of Text/Glob.pm # BEGIN { $INC{'Text/Glob.pm'} = 'dummy/Text/Glob.pm'; } BEGIN { #line 0 "Text/Glob.pm" package Text::Glob; use strict; use Exporter; use vars qw/$VERSION @ISA @EXPORT_OK $strict_leading_dot $strict_wildcard_slash/; $VERSION = '0.08'; @ISA = 'Exporter'; @EXPORT_OK = qw( glob_to_regex glob_to_regex_string match_glob ); $strict_leading_dot = 1; $strict_wildcard_slash = 1; use constant debug => 0; sub glob_to_regex { my $glob = shift; my $regex = glob_to_regex_string($glob); return qr/^$regex$/; } sub glob_to_regex_string { my $glob = shift; my ($regex, $in_curlies, $escaping); local $_; my $first_byte = 1; for ($glob =~ m/(.)/gs) { if ($first_byte) { if ($strict_leading_dot) { $regex .= '(?=[^\.])' unless $_ eq '.'; } $first_byte = 0; } if ($_ eq '/') { $first_byte = 1; } if ($_ eq '.' || $_ eq '(' || $_ eq ')' || $_ eq '|' || $_ eq '+' || $_ eq '^' || $_ eq '$' || $_ eq '@' || $_ eq '%' ) { $regex .= "\\$_"; } elsif ($_ eq '*') { $regex .= $escaping ? "\\*" : $strict_wildcard_slash ? "[^/]*" : ".*"; } elsif ($_ eq '?') { $regex .= $escaping ? "\\?" : $strict_wildcard_slash ? "[^/]" : "."; } elsif ($_ eq '{') { $regex .= $escaping ? "\\{" : "("; ++$in_curlies unless $escaping; } elsif ($_ eq '}' && $in_curlies) { $regex .= $escaping ? "}" : ")"; --$in_curlies unless $escaping; } elsif ($_ eq ',' && $in_curlies) { $regex .= $escaping ? "," : "|"; } elsif ($_ eq "\\") { if ($escaping) { $regex .= "\\\\"; $escaping = 0; } else { $escaping = 1; } next; } else { $regex .= $_; $escaping = 0; } $escaping = 0; } print "# $glob $regex\n" if debug; return $regex; } sub match_glob { print "# ", join(', ', map { "'$_'" } @_), "\n" if debug; my $glob = shift; my $regex = glob_to_regex $glob; local $_; grep { $_ =~ $regex } @_; } 1; } # # Inline include of File/Find/Rule.pm # BEGIN { $INC{'File/Find/Rule.pm'} = 'dummy/File/Find/Rule.pm'; } BEGIN { #line 0 "File/Find/Rule.pm" package File::Find::Rule; use strict; use vars qw/$VERSION $AUTOLOAD/; use File::Spec; use Text::Glob 'glob_to_regex'; use Number::Compare; use Carp qw/croak/; use File::Find (); # we're only wrapping for now use Cwd; # 5.00503s File::Find goes screwy with max_depth == 0 $VERSION = '0.30'; sub import { my $pkg = shift; my $to = caller; for my $sym ( qw( find rule ) ) { no strict 'refs'; *{"$to\::$sym"} = \&{$sym}; } for (grep /^:/, @_) { my ($extension) = /^:(.*)/; eval "require File::Find::Rule::$extension"; croak "couldn't bootstrap File::Find::Rule::$extension: $@" if $@; } } *rule = \&find; sub find { my $object = __PACKAGE__->new(); my $not = 0; while (@_) { my $method = shift; my @args; if ($method =~ s/^\!//) { # jinkies, we're really negating this unshift @_, $method; $not = 1; next; } unless (defined prototype $method) { my $args = shift; @args = ref $args eq 'ARRAY' ? @$args : $args; } if ($not) { $not = 0; @args = $object->new->$method(@args); $method = "not"; } my @return = $object->$method(@args); return @return if $method eq 'in'; } $object; } sub new { my $referent = shift; my $class = ref $referent || $referent; bless { rules => [], # [0] subs => [], # [1] iterator => [], extras => {}, maxdepth => undef, mindepth => undef, }, $class; } sub _force_object { my $object = shift; $object = $object->new() unless ref $object; $object; } sub _flatten { my @flat; while (@_) { my $item = shift; ref $item eq 'ARRAY' ? push @_, @{ $item } : push @flat, $item; } return @flat; } sub name { my $self = _force_object shift; my @names = map { ref $_ eq "Regexp" ? $_ : glob_to_regex $_ } _flatten( @_ ); push @{ $self->{rules} }, { rule => 'name', code => join( ' || ', map { "m($_)" } @names ), args => \@_, }; $self; } use vars qw( %X_tests ); %X_tests = ( -r => readable => -R => r_readable => -w => writeable => -W => r_writeable => -w => writable => -W => r_writable => -x => executable => -X => r_executable => -o => owned => -O => r_owned => -e => exists => -f => file => -z => empty => -d => directory => -s => nonempty => -l => symlink => => -p => fifo => -u => setuid => -S => socket => -g => setgid => -b => block => -k => sticky => -c => character => => -t => tty => -M => modified => -A => accessed => -T => ascii => -C => changed => -B => binary => ); for my $test (keys %X_tests) { my $sub = eval 'sub () { my $self = _force_object shift; push @{ $self->{rules} }, { code => "' . $test . ' \$_", rule => "'.$X_tests{$test}.'", }; $self; } '; no strict 'refs'; *{ $X_tests{$test} } = $sub; } use vars qw( @stat_tests ); @stat_tests = qw( dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks ); { my $i = 0; for my $test (@stat_tests) { my $index = $i++; # to close over my $sub = sub { my $self = _force_object shift; my @tests = map { Number::Compare->parse_to_perl($_) } @_; push @{ $self->{rules} }, { rule => $test, args => \@_, code => 'do { my $val = (stat $_)['.$index.'] || 0;'. join ('||', map { "(\$val $_)" } @tests ).' }', }; $self; }; no strict 'refs'; *$test = $sub; } } sub any { my $self = _force_object shift; my @rulesets = @_; push @{ $self->{rules} }, { rule => 'any', code => '(' . join( ' || ', map { "( " . $_->_compile( $self->{subs} ) . " )" } @_ ) . ")", args => \@_, }; $self; } *or = \&any; sub not { my $self = _force_object shift; my @rulesets = @_; push @{ $self->{rules} }, { rule => 'not', args => \@rulesets, code => '(' . join ( ' && ', map { "!(". $_->_compile( $self->{subs} ) . ")" } @_ ) . ")", }; $self; } *none = \¬ sub prune () { my $self = _force_object shift; push @{ $self->{rules} }, { rule => 'prune', code => '$File::Find::prune = 1' }; $self; } sub discard () { my $self = _force_object shift; push @{ $self->{rules} }, { rule => 'discard', code => '$discarded = 1', }; $self; } sub exec { my $self = _force_object shift; my $code = shift; push @{ $self->{rules} }, { rule => 'exec', code => $code, }; $self; } sub grep { my $self = _force_object shift; my @pattern = map { ref $_ ? ref $_ eq 'ARRAY' ? map { [ ( ref $_ ? $_ : qr/$_/ ) => 0 ] } @$_ : [ $_ => 1 ] : [ qr/$_/ => 1 ] } @_; $self->exec( sub { local *FILE; open FILE, $_ or return; local ($_, $.); while () { for my $p (@pattern) { my ($rule, $ret) = @$p; return $ret if ref $rule eq 'Regexp' ? /$rule/ : $rule->(@_); } } return; } ); } for my $setter (qw( maxdepth mindepth extras )) { my $sub = sub { my $self = _force_object shift; $self->{$setter} = shift; $self; }; no strict 'refs'; *$setter = $sub; } sub relative () { my $self = _force_object shift; $self->{relative} = 1; $self; } sub DESTROY {} sub AUTOLOAD { $AUTOLOAD =~ /::not_([^:]*)$/ or croak "Can't locate method $AUTOLOAD"; my $method = $1; my $sub = sub { my $self = _force_object shift; $self->not( $self->new->$method(@_) ); }; { no strict 'refs'; *$AUTOLOAD = $sub; } &$sub; } sub in { my $self = _force_object shift; my @found; my $fragment = $self->_compile( $self->{subs} ); my @subs = @{ $self->{subs} }; warn "relative mode handed multiple paths - that's a bit silly\n" if $self->{relative} && @_ > 1; my $topdir; my $code = 'sub { (my $path = $File::Find::name) =~ s#^(?:\./+)+##; my @args = ($_, $File::Find::dir, $path); my $maxdepth = $self->{maxdepth}; my $mindepth = $self->{mindepth}; my $relative = $self->{relative}; # figure out the relative path and depth my $relpath = $File::Find::name; $relpath =~ s{^\Q$topdir\E/?}{}; my $depth = scalar File::Spec->splitdir($relpath); #print "name: \'$File::Find::name\' "; #print "relpath: \'$relpath\' depth: $depth relative: $relative\n"; defined $maxdepth && $depth >= $maxdepth and $File::Find::prune = 1; defined $mindepth && $depth < $mindepth and return; #print "Testing \'$_\'\n"; my $discarded; return unless ' . $fragment . '; return if $discarded; if ($relative) { push @found, $relpath if $relpath ne ""; } else { push @found, $path; } }'; #use Data::Dumper; #print Dumper \@subs; #warn "Compiled sub: '$code'\n"; my $sub = eval "$code" or die "compile error '$code' $@"; my $cwd = getcwd; for my $path (@_) { # $topdir is used for relative and maxdepth $topdir = $path; # slice off the trailing slash if there is one (the # maxdepth/mindepth code is fussy) $topdir =~ s{/?$}{} unless $topdir eq '/'; $self->_call_find( { %{ $self->{extras} }, wanted => $sub }, $path ); } chdir $cwd; return @found; } sub _call_find { my $self = shift; File::Find::find( @_ ); } sub _compile { my $self = shift; my $subs = shift; # [1] return '1' unless @{ $self->{rules} }; my $code = join " && ", map { if (ref $_->{code}) { push @$subs, $_->{code}; "\$subs[$#{$subs}]->(\@args) # $_->{rule}\n"; } else { "( $_->{code} ) # $_->{rule}\n"; } } @{ $self->{rules} }; return $code; } sub start { my $self = _force_object shift; $self->{iterator} = [ $self->in( @_ ) ]; $self; } sub match { my $self = _force_object shift; return shift @{ $self->{iterator} }; } 1; } # # Inline include of Template/Constants.pm # BEGIN { $INC{'Template/Constants.pm'} = 'dummy/Template/Constants.pm'; } BEGIN { #line 0 "Template/Constants.pm" package Template::Constants; require Exporter; use strict; use warnings; use base 'Exporter'; use vars qw( @EXPORT_OK %EXPORT_TAGS ); use vars qw( $DEBUG_OPTIONS @STATUS @ERROR @CHOMP @DEBUG); our $VERSION = 2.75; use constant STATUS_OK => 0; # ok use constant STATUS_RETURN => 1; # ok, block ended by RETURN use constant STATUS_STOP => 2; # ok, stoppped by STOP use constant STATUS_DONE => 3; # ok, iterator done use constant STATUS_DECLINED => 4; # ok, declined to service request use constant STATUS_ERROR => 255; # error condition use constant ERROR_RETURN => 'return'; # return a status code use constant ERROR_FILE => 'file'; # file error: I/O, parse, recursion use constant ERROR_VIEW => 'view'; # view error use constant ERROR_UNDEF => 'undef'; # undefined variable value used use constant ERROR_PERL => 'perl'; # error in [% PERL %] block use constant ERROR_FILTER => 'filter'; # filter error use constant ERROR_PLUGIN => 'plugin'; # plugin error use constant CHOMP_NONE => 0; # do not remove whitespace use constant CHOMP_ALL => 1; # remove whitespace up to newline use constant CHOMP_ONE => 1; # new name for CHOMP_ALL use constant CHOMP_COLLAPSE => 2; # collapse whitespace to a single space use constant CHOMP_GREEDY => 3; # remove all whitespace including newlines use constant DEBUG_OFF => 0; # do nothing use constant DEBUG_ON => 1; # basic debugging flag use constant DEBUG_UNDEF => 2; # throw undef on undefined variables use constant DEBUG_VARS => 4; # general variable debugging use constant DEBUG_DIRS => 8; # directive debugging use constant DEBUG_STASH => 16; # general stash debugging use constant DEBUG_CONTEXT => 32; # context debugging use constant DEBUG_PARSER => 64; # parser debugging use constant DEBUG_PROVIDER => 128; # provider debugging use constant DEBUG_PLUGINS => 256; # plugins debugging use constant DEBUG_FILTERS => 512; # filters debugging use constant DEBUG_SERVICE => 1024; # context debugging use constant DEBUG_ALL => 2047; # everything use constant DEBUG_CALLER => 4096; # add caller file/line use constant DEBUG_FLAGS => 4096; # bitmask to extraxt flags $DEBUG_OPTIONS = { &DEBUG_OFF => off => off => &DEBUG_OFF, &DEBUG_ON => on => on => &DEBUG_ON, &DEBUG_UNDEF => undef => undef => &DEBUG_UNDEF, &DEBUG_VARS => vars => vars => &DEBUG_VARS, &DEBUG_DIRS => dirs => dirs => &DEBUG_DIRS, &DEBUG_STASH => stash => stash => &DEBUG_STASH, &DEBUG_CONTEXT => context => context => &DEBUG_CONTEXT, &DEBUG_PARSER => parser => parser => &DEBUG_PARSER, &DEBUG_PROVIDER => provider => provider => &DEBUG_PROVIDER, &DEBUG_PLUGINS => plugins => plugins => &DEBUG_PLUGINS, &DEBUG_FILTERS => filters => filters => &DEBUG_FILTERS, &DEBUG_SERVICE => service => service => &DEBUG_SERVICE, &DEBUG_ALL => all => all => &DEBUG_ALL, &DEBUG_CALLER => caller => caller => &DEBUG_CALLER, }; @STATUS = qw( STATUS_OK STATUS_RETURN STATUS_STOP STATUS_DONE STATUS_DECLINED STATUS_ERROR ); @ERROR = qw( ERROR_FILE ERROR_VIEW ERROR_UNDEF ERROR_PERL ERROR_RETURN ERROR_FILTER ERROR_PLUGIN ); @CHOMP = qw( CHOMP_NONE CHOMP_ALL CHOMP_ONE CHOMP_COLLAPSE CHOMP_GREEDY ); @DEBUG = qw( DEBUG_OFF DEBUG_ON DEBUG_UNDEF DEBUG_VARS DEBUG_DIRS DEBUG_STASH DEBUG_CONTEXT DEBUG_PARSER DEBUG_PROVIDER DEBUG_PLUGINS DEBUG_FILTERS DEBUG_SERVICE DEBUG_ALL DEBUG_CALLER DEBUG_FLAGS ); @EXPORT_OK = ( @STATUS, @ERROR, @CHOMP, @DEBUG ); %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ], 'status' => [ @STATUS ], 'error' => [ @ERROR ], 'chomp' => [ @CHOMP ], 'debug' => [ @DEBUG ], ); sub debug_flags { my ($self, $debug) = @_; my (@flags, $flag, $value); $debug = $self unless defined($debug) || ref($self); if ($debug =~ /^\d+$/) { foreach $flag (@DEBUG) { next if $flag =~ /^DEBUG_(OFF|ALL|FLAGS)$/; # don't trash the original my $copy = $flag; $flag =~ s/^DEBUG_//; $flag = lc $flag; return $self->error("no value for flag: $flag") unless defined($value = $DEBUG_OPTIONS->{ $flag }); $flag = $value; if ($debug & $flag) { $value = $DEBUG_OPTIONS->{ $flag }; return $self->error("no value for flag: $flag") unless defined $value; push(@flags, $value); } } return wantarray ? @flags : join(', ', @flags); } else { @flags = split(/\W+/, $debug); $debug = 0; foreach $flag (@flags) { $value = $DEBUG_OPTIONS->{ $flag }; return $self->error("unknown debug flag: $flag") unless defined $value; $debug |= $value; } return $debug; } } 1; } # # Inline include of Template/Base.pm # BEGIN { $INC{'Template/Base.pm'} = 'dummy/Template/Base.pm'; } BEGIN { #line 0 "Template/Base.pm" package Template::Base; use strict; use warnings; use Template::Constants; our $VERSION = 2.78; sub new { my $class = shift; my ($argnames, @args, $arg, $cfg); { no strict 'refs'; no warnings 'once'; $argnames = \@{"$class\::BASEARGS"} || [ ]; } # shift off all mandatory args, returning error if undefined or null foreach $arg (@$argnames) { return $class->error("no $arg specified") unless ($cfg = shift); push(@args, $cfg); } # fold all remaining args into a hash, or use provided hash ref $cfg = defined $_[0] && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; my $self = bless { (map { ($_ => shift @args) } @$argnames), _ERROR => '', DEBUG => 0, }, $class; return $self->_init($cfg) ? $self : $class->error($self->error); } sub error { my $self = shift; my $errvar; { no strict qw( refs ); $errvar = ref $self ? \$self->{ _ERROR } : \${"$self\::ERROR"}; } if (@_) { $$errvar = ref($_[0]) ? shift : join('', @_); return undef; } else { return $$errvar; } } sub _init { my ($self, $config) = @_; return $self; } sub debug { my $self = shift; my $msg = join('', @_); my ($pkg, $file, $line) = caller(); unless ($msg =~ /\n$/) { $msg .= ($self->{ DEBUG } & Template::Constants::DEBUG_CALLER) ? " at $file line $line\n" : "\n"; } print STDERR "[$pkg] $msg"; } sub module_version { my $self = shift; my $class = ref $self || $self; no strict 'refs'; return ${"${class}::VERSION"}; } 1; } # # Inline include of Template/Config.pm # BEGIN { $INC{'Template/Config.pm'} = 'dummy/Template/Config.pm'; } BEGIN { #line 0 "Template/Config.pm" package Template::Config; use strict; use warnings; use base 'Template::Base'; use vars qw( $VERSION $DEBUG $ERROR $INSTDIR $PARSER $PROVIDER $PLUGINS $FILTERS $ITERATOR $LATEX_PATH $PDFLATEX_PATH $DVIPS_PATH $STASH $SERVICE $CONTEXT $CONSTANTS @PRELOAD ); $VERSION = 2.75; $DEBUG = 0 unless defined $DEBUG; $ERROR = ''; $CONTEXT = 'Template::Context'; $FILTERS = 'Template::Filters'; $ITERATOR = 'Template::Iterator'; $PARSER = 'Template::Parser'; $PLUGINS = 'Template::Plugins'; $PROVIDER = 'Template::Provider'; $SERVICE = 'Template::Service'; $STASH = 'Template::Stash::XS'; $CONSTANTS = 'Template::Namespace::Constants'; @PRELOAD = ( $CONTEXT, $FILTERS, $ITERATOR, $PARSER, $PLUGINS, $PROVIDER, $SERVICE, $STASH ); $INSTDIR = ''; sub preload { my $class = shift; foreach my $module (@PRELOAD, @_) { $class->load($module) || return; }; return 1; } sub load { my ($class, $module) = @_; $module =~ s[::][/]g; $module .= '.pm'; eval { require $module; }; return $@ ? $class->error("failed to load $module: $@") : 1; } sub parser { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($PARSER); return $PARSER->new($params) || $class->error("failed to create parser: ", $PARSER->error); } sub provider { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($PROVIDER); return $PROVIDER->new($params) || $class->error("failed to create template provider: ", $PROVIDER->error); } sub plugins { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($PLUGINS); return $PLUGINS->new($params) || $class->error("failed to create plugin provider: ", $PLUGINS->error); } sub filters { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($FILTERS); return $FILTERS->new($params) || $class->error("failed to create filter provider: ", $FILTERS->error); } sub iterator { my $class = shift; my $list = shift; return undef unless $class->load($ITERATOR); return $ITERATOR->new($list, @_) || $class->error("failed to create iterator: ", $ITERATOR->error); } sub stash { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($STASH); return $STASH->new($params) || $class->error("failed to create stash: ", $STASH->error); } sub context { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($CONTEXT); return $CONTEXT->new($params) || $class->error("failed to create context: ", $CONTEXT->error); } sub service { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($SERVICE); return $SERVICE->new($params) || $class->error("failed to create context: ", $SERVICE->error); } sub constants { my $class = shift; my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ }; return undef unless $class->load($CONSTANTS); return $CONSTANTS->new($params) || $class->error("failed to create constants namespace: ", $CONSTANTS->error); } sub instdir { my ($class, $dir) = @_; my $inst = $INSTDIR || return $class->error("no installation directory"); $inst =~ s[/$][]g; $inst .= "/$dir" if $dir; return $inst; } package Template::TieString; sub TIEHANDLE { my ($class, $textref) = @_; bless $textref, $class; } sub PRINT { my $self = shift; $$self .= join('', @_); } 1; } # # Inline include of Template/Document.pm # BEGIN { $INC{'Template/Document.pm'} = 'dummy/Template/Document.pm'; } BEGIN { #line 0 "Template/Document.pm" package Template::Document; use strict; use warnings; use base 'Template::Base'; use Template::Constants; our $VERSION = 2.79; our $DEBUG = 0 unless defined $DEBUG; our $ERROR = ''; our ($COMPERR, $AUTOLOAD, $UNICODE); BEGIN { # UNICODE is supported in versions of Perl from 5.008 onwards if ($UNICODE = $] > 5.007 ? 1 : 0) { if ($] > 5.008) { # utf8::is_utf8() available from Perl 5.8.1 onwards *is_utf8 = \&utf8::is_utf8; } elsif ($] == 5.008) { # use Encode::is_utf8() for Perl 5.8.0 require Encode; *is_utf8 = \&Encode::is_utf8; } } } sub new { my ($class, $doc) = @_; my ($block, $defblocks, $metadata) = @$doc{ qw( BLOCK DEFBLOCKS METADATA ) }; $defblocks ||= { }; $metadata ||= { }; # evaluate Perl code in $block to create sub-routine reference if necessary unless (ref $block) { local $SIG{__WARN__} = \&catch_warnings; $COMPERR = ''; # DON'T LOOK NOW! - blindly untainting can make you go blind! $block =~ /(.*)/s; $block = $1; $block = eval $block; return $class->error($@) unless defined $block; } # same for any additional BLOCK definitions @$defblocks{ keys %$defblocks } = # MORE BLIND UNTAINTING - turn away if you're squeamish map { ref($_) ? $_ : ( /(.*)/s && eval($1) or return $class->error($@) ) } values %$defblocks; bless { %$metadata, _BLOCK => $block, _DEFBLOCKS => $defblocks, _HOT => 0, }, $class; } sub block { return $_[0]->{ _BLOCK }; } sub blocks { return $_[0]->{ _DEFBLOCKS }; } sub process { my ($self, $context) = @_; my $defblocks = $self->{ _DEFBLOCKS }; my $output; # check we're not already visiting this template return $context->throw(Template::Constants::ERROR_FILE, "recursion into '$self->{ name }'") if $self->{ _HOT } && ! $context->{ RECURSION }; ## RETURN ## $context->visit($self, $defblocks); $self->{ _HOT } = 1; eval { my $block = $self->{ _BLOCK }; $output = &$block($context); }; $self->{ _HOT } = 0; $context->leave(); die $context->catch($@) if $@; return $output; } sub AUTOLOAD { my $self = shift; my $method = $AUTOLOAD; $method =~ s/.*:://; return if $method eq 'DESTROY'; return $self->{ $method }; } sub _dump { my $self = shift; my $dblks; my $output = "$self : $self->{ name }\n"; $output .= "BLOCK: $self->{ _BLOCK }\nDEFBLOCKS:\n"; if ($dblks = $self->{ _DEFBLOCKS }) { foreach my $b (keys %$dblks) { $output .= " $b: $dblks->{ $b }\n"; } } return $output; } sub as_perl { my ($class, $content) = @_; my ($block, $defblocks, $metadata) = @$content{ qw( BLOCK DEFBLOCKS METADATA ) }; $block =~ s/\n/\n /g; $block =~ s/\s+$//; $defblocks = join('', map { my $code = $defblocks->{ $_ }; $code =~ s/\n/\n /g; $code =~ s/\s*$//; " '$_' => $code,\n"; } keys %$defblocks); $defblocks =~ s/\s+$//; $metadata = join('', map { my $x = $metadata->{ $_ }; $x =~ s/(['\\])/\\$1/g; " '$_' => '$x',\n"; } keys %$metadata); $metadata =~ s/\s+$//; return <new({ METADATA => { $metadata }, BLOCK => $block, DEFBLOCKS => { $defblocks }, }); EOF } sub write_perl_file { my ($class, $file, $content) = @_; my ($fh, $tmpfile); return $class->error("invalid filename: $file") unless $file =~ /^(.+)$/s; eval { require File::Temp; require File::Basename; ($fh, $tmpfile) = File::Temp::tempfile( DIR => File::Basename::dirname($file) ); my $perlcode = $class->as_perl($content) || die $!; if ($UNICODE && is_utf8($perlcode)) { $perlcode = "use utf8;\n\n$perlcode"; binmode $fh, ":utf8"; } print $fh $perlcode; close($fh); }; return $class->error($@) if $@; return rename($tmpfile, $file) || $class->error($!); } sub catch_warnings { $COMPERR .= join('', @_); } 1; } # # Inline include of Template/Exception.pm # BEGIN { $INC{'Template/Exception.pm'} = 'dummy/Template/Exception.pm'; } BEGIN { #line 0 "Template/Exception.pm" package Template::Exception; use strict; use warnings; use constant TYPE => 0; use constant INFO => 1; use constant TEXT => 2; use overload q|""| => "as_string", fallback => 1; our $VERSION = 2.70; sub new { my ($class, $type, $info, $textref) = @_; bless [ $type, $info, $textref ], $class; } sub type { $_[0]->[ TYPE ]; } sub info { $_[0]->[ INFO ]; } sub type_info { my $self = shift; @$self[ TYPE, INFO ]; } sub text { my ($self, $newtextref) = @_; my $textref = $self->[ TEXT ]; if ($newtextref) { $$newtextref .= $$textref if $textref && $textref ne $newtextref; $self->[ TEXT ] = $newtextref; return ''; } elsif ($textref) { return $$textref; } else { return ''; } } sub as_string { my $self = shift; return $self->[ TYPE ] . ' error - ' . $self->[ INFO ]; } sub select_handler { my ($self, @options) = @_; my $type = $self->[ TYPE ]; my %hlut; @hlut{ @options } = (1) x @options; while ($type) { return $type if $hlut{ $type }; # strip .element from the end of the exception type to find a # more generic handler $type =~ s/\.?[^\.]*$//; } return undef; } 1; } # # Inline include of Template/Service.pm # BEGIN { $INC{'Template/Service.pm'} = 'dummy/Template/Service.pm'; } BEGIN { #line 0 "Template/Service.pm" package Template::Service; use strict; use warnings; use base 'Template::Base'; use Template::Config; use Template::Exception; use Template::Constants; our $VERSION = 2.80; our $DEBUG = 0 unless defined $DEBUG; our $ERROR = ''; sub process { my ($self, $template, $params) = @_; my $context = $self->{ CONTEXT }; my ($name, $output, $procout, $error); $output = ''; $self->debug("process($template, ", defined $params ? $params : '', ')') if $self->{ DEBUG }; $context->reset() if $self->{ AUTO_RESET }; # pre-request compiled template from context so that we can alias it # in the stash for pre-processed templates to reference eval { $template = $context->template($template) }; return $self->error($@) if $@; # localise the variable stash with any parameters passed # and set the 'template' variable $params ||= { }; # TODO: change this to C<||=> so we can use a template parameter $params->{ template } = $template unless ref $template eq 'CODE'; $context->localise($params); SERVICE: { # PRE_PROCESS eval { foreach $name (@{ $self->{ PRE_PROCESS } }) { $self->debug("PRE_PROCESS: $name") if $self->{ DEBUG }; $output .= $context->process($name); } }; last SERVICE if ($error = $@); # PROCESS eval { foreach $name (@{ $self->{ PROCESS } || [ $template ] }) { $self->debug("PROCESS: $name") if $self->{ DEBUG }; $procout .= $context->process($name); } }; if ($error = $@) { last SERVICE unless defined ($procout = $self->_recover(\$error)); } if (defined $procout) { # WRAPPER eval { foreach $name (reverse @{ $self->{ WRAPPER } }) { $self->debug("WRAPPER: $name") if $self->{ DEBUG }; $procout = $context->process($name, { content => $procout }); } }; last SERVICE if ($error = $@); $output .= $procout; } # POST_PROCESS eval { foreach $name (@{ $self->{ POST_PROCESS } }) { $self->debug("POST_PROCESS: $name") if $self->{ DEBUG }; $output .= $context->process($name); } }; last SERVICE if ($error = $@); } $context->delocalise(); delete $params->{ template }; if ($error) { # $error = $error->as_string if ref $error; return $self->error($error); } return $output; } sub context { return $_[0]->{ CONTEXT }; } sub _init { my ($self, $config) = @_; my ($item, $data, $context, $block, $blocks); my $delim = $config->{ DELIMITER }; $delim = ':' unless defined $delim; # coerce PRE_PROCESS, PROCESS and POST_PROCESS to arrays if necessary, # by splitting on non-word characters foreach $item (qw( PRE_PROCESS PROCESS POST_PROCESS WRAPPER )) { $data = $config->{ $item }; $self->{ $item } = [ ], next unless (defined $data); $data = [ split($delim, $data || '') ] unless ref $data eq 'ARRAY'; $self->{ $item } = $data; } # unset PROCESS option unless explicitly specified in config $self->{ PROCESS } = undef unless defined $config->{ PROCESS }; $self->{ ERROR } = $config->{ ERROR } || $config->{ ERRORS }; $self->{ AUTO_RESET } = defined $config->{ AUTO_RESET } ? $config->{ AUTO_RESET } : 1; $self->{ DEBUG } = ( $config->{ DEBUG } || 0 ) & Template::Constants::DEBUG_SERVICE; $context = $self->{ CONTEXT } = $config->{ CONTEXT } || Template::Config->context($config) || return $self->error(Template::Config->error); return $self; } sub _recover { my ($self, $error) = @_; my $context = $self->{ CONTEXT }; my ($hkey, $handler, $output); # there shouldn't ever be a non-exception object received at this # point... unless a module like CGI::Carp messes around with the # DIE handler. return undef unless UNIVERSAL::isa($$error, 'Template::Exception'); # a 'stop' exception is thrown by [% STOP %] - we return the output # buffer stored in the exception object return $$error->text() if $$error->type() eq 'stop'; my $handlers = $self->{ ERROR } || return undef; ## RETURN if (ref $handlers eq 'HASH') { if ($hkey = $$error->select_handler(keys %$handlers)) { $handler = $handlers->{ $hkey }; $self->debug("using error handler for $hkey") if $self->{ DEBUG }; } elsif ($handler = $handlers->{ default }) { # use default handler $self->debug("using default error handler") if $self->{ DEBUG }; } else { return undef; ## RETURN } } else { $handler = $handlers; $self->debug("using default error handler") if $self->{ DEBUG }; } eval { $handler = $context->template($handler) }; if ($@) { $$error = $@; return undef; ## RETURN }; $context->stash->set('error', $$error); eval { $output .= $context->process($handler); }; if ($@) { $$error = $@; return undef; ## RETURN } return $output; } sub _dump { my $self = shift; my $context = $self->{ CONTEXT }->_dump(); $context =~ s/\n/\n /gm; my $error = $self->{ ERROR }; $error = join('', "{\n", (map { " $_ => $error->{ $_ }\n" } keys %$error), "}\n") if ref $error; local $" = ', '; return < [ @{ $self->{ PRE_PROCESS } } ] POST_PROCESS => [ @{ $self->{ POST_PROCESS } } ] ERROR => $error CONTEXT => $context EOF } 1; } # # Inline include of Template/Provider.pm # BEGIN { $INC{'Template/Provider.pm'} = 'dummy/Template/Provider.pm'; } BEGIN { #line 0 "Template/Provider.pm" package Template::Provider; use strict; use warnings; use base 'Template::Base'; use Template::Config; use Template::Constants; use Template::Document; use File::Basename; use File::Spec; use constant PREV => 0; use constant NAME => 1; # template name -- indexed by this name in LOOKUP use constant DATA => 2; # Compiled template use constant LOAD => 3; # mtime of template use constant NEXT => 4; # link to next item in cache linked list use constant STAT => 5; # Time last stat()ed our $VERSION = 2.94; our $DEBUG = 0 unless defined $DEBUG; our $ERROR = ''; our $DOCUMENT = 'Template::Document' unless defined $DOCUMENT; our $STAT_TTL = 1 unless defined $STAT_TTL; our $MAX_DIRS = 64 unless defined $MAX_DIRS; our $UNICODE = $] > 5.007 ? 1 : 0; my $boms = [ 'UTF-8' => "\x{ef}\x{bb}\x{bf}", 'UTF-32BE' => "\x{0}\x{0}\x{fe}\x{ff}", 'UTF-32LE' => "\x{ff}\x{fe}\x{0}\x{0}", 'UTF-16BE' => "\x{fe}\x{ff}", 'UTF-16LE' => "\x{ff}\x{fe}", ]; our $RELATIVE_PATH = qr[(?:^|/)\.+/]; BEGIN { if ($] < 5.006) { package bytes; $INC{'bytes.pm'} = 1; } } sub fetch { my ($self, $name) = @_; my ($data, $error); if (ref $name) { # $name can be a reference to a scalar, GLOB or file handle ($data, $error) = $self->_load($name); ($data, $error) = $self->_compile($data) unless $error; $data = $data->{ data } unless $error; } elsif (File::Spec->file_name_is_absolute($name)) { # absolute paths (starting '/') allowed if ABSOLUTE set ($data, $error) = $self->{ ABSOLUTE } ? $self->_fetch($name) : $self->{ TOLERANT } ? (undef, Template::Constants::STATUS_DECLINED) : ("$name: absolute paths are not allowed (set ABSOLUTE option)", Template::Constants::STATUS_ERROR); } elsif ($name =~ m/$RELATIVE_PATH/o) { # anything starting "./" is relative to cwd, allowed if RELATIVE set ($data, $error) = $self->{ RELATIVE } ? $self->_fetch($name) : $self->{ TOLERANT } ? (undef, Template::Constants::STATUS_DECLINED) : ("$name: relative paths are not allowed (set RELATIVE option)", Template::Constants::STATUS_ERROR); } else { # otherwise, it's a file name relative to INCLUDE_PATH ($data, $error) = $self->{ INCLUDE_PATH } ? $self->_fetch_path($name) : (undef, Template::Constants::STATUS_DECLINED); } return ($data, $error); } sub store { my ($self, $name, $data) = @_; $self->_store($name, { data => $data, load => 0, }); } sub load { my ($self, $name) = @_; my ($data, $error); my $path = $name; if (File::Spec->file_name_is_absolute($name)) { # absolute paths (starting '/') allowed if ABSOLUTE set $error = "$name: absolute paths are not allowed (set ABSOLUTE option)" unless $self->{ ABSOLUTE }; } elsif ($name =~ m[$RELATIVE_PATH]o) { # anything starting "./" is relative to cwd, allowed if RELATIVE set $error = "$name: relative paths are not allowed (set RELATIVE option)" unless $self->{ RELATIVE }; } else { INCPATH: { # otherwise, it's a file name relative to INCLUDE_PATH my $paths = $self->paths() || return ($self->error(), Template::Constants::STATUS_ERROR); foreach my $dir (@$paths) { $path = File::Spec->catfile($dir, $name); last INCPATH if $self->_template_modified($path); } undef $path; # not found } } # Now fetch the content ($data, $error) = $self->_template_content($path) if defined $path && !$error; if ($error) { return $self->{ TOLERANT } ? (undef, Template::Constants::STATUS_DECLINED) : ($error, Template::Constants::STATUS_ERROR); } elsif (! defined $path) { return (undef, Template::Constants::STATUS_DECLINED); } else { return ($data, Template::Constants::STATUS_OK); } } sub include_path { my ($self, $path) = @_; $self->{ INCLUDE_PATH } = $path if $path; return $self->{ INCLUDE_PATH }; } sub paths { my $self = shift; my @ipaths = @{ $self->{ INCLUDE_PATH } }; my (@opaths, $dpaths, $dir); my $count = $MAX_DIRS; while (@ipaths && --$count) { $dir = shift @ipaths || next; # $dir can be a sub or object ref which returns a reference # to a dynamically generated list of search paths. if (ref $dir eq 'CODE') { eval { $dpaths = &$dir() }; if ($@) { chomp $@; return $self->error($@); } unshift(@ipaths, @$dpaths); next; } elsif (ref($dir) && UNIVERSAL::can($dir, 'paths')) { $dpaths = $dir->paths() || return $self->error($dir->error()); unshift(@ipaths, @$dpaths); next; } else { push(@opaths, $dir); } } return $self->error("INCLUDE_PATH exceeds $MAX_DIRS directories") if @ipaths; return \@opaths; } sub DESTROY { my $self = shift; my ($slot, $next); $slot = $self->{ HEAD }; while ($slot) { $next = $slot->[ NEXT ]; undef $slot->[ PREV ]; undef $slot->[ NEXT ]; $slot = $next; } undef $self->{ HEAD }; undef $self->{ TAIL }; } sub _init { my ($self, $params) = @_; my $size = $params->{ CACHE_SIZE }; my $path = $params->{ INCLUDE_PATH } || '.'; my $cdir = $params->{ COMPILE_DIR } || ''; my $dlim = $params->{ DELIMITER }; my $debug; # tweak delim to ignore C:/ unless (defined $dlim) { $dlim = ($^O eq 'MSWin32') ? ':(?!\\/)' : ':'; } # coerce INCLUDE_PATH to an array ref, if not already so $path = [ split(/$dlim/, $path) ] unless ref $path eq 'ARRAY'; # don't allow a CACHE_SIZE 1 because it breaks things and the # additional checking isn't worth it $size = 2 if defined $size && ($size == 1 || $size < 0); if (defined ($debug = $params->{ DEBUG })) { $self->{ DEBUG } = $debug & ( Template::Constants::DEBUG_PROVIDER | Template::Constants::DEBUG_FLAGS ); } else { $self->{ DEBUG } = $DEBUG; } if ($self->{ DEBUG }) { local $" = ', '; $self->debug("creating cache of ", defined $size ? $size : 'unlimited', " slots for [ @$path ]"); } # create COMPILE_DIR and sub-directories representing each INCLUDE_PATH # element in which to store compiled files if ($cdir) { require File::Path; foreach my $dir (@$path) { next if ref $dir; my $wdir = $dir; $wdir =~ s[:][]g if $^O eq 'MSWin32'; $wdir =~ /(.*)/; # untaint $wdir = "$1"; # quotes work around bug in Strawberry Perl $wdir = File::Spec->catfile($cdir, $wdir); File::Path::mkpath($wdir) unless -d $wdir; } } $self->{ LOOKUP } = { }; $self->{ NOTFOUND } = { }; # Tracks templates *not* found. $self->{ SLOTS } = 0; $self->{ SIZE } = $size; $self->{ INCLUDE_PATH } = $path; $self->{ DELIMITER } = $dlim; $self->{ COMPILE_DIR } = $cdir; $self->{ COMPILE_EXT } = $params->{ COMPILE_EXT } || ''; $self->{ ABSOLUTE } = $params->{ ABSOLUTE } || 0; $self->{ RELATIVE } = $params->{ RELATIVE } || 0; $self->{ TOLERANT } = $params->{ TOLERANT } || 0; $self->{ DOCUMENT } = $params->{ DOCUMENT } || $DOCUMENT; $self->{ PARSER } = $params->{ PARSER }; $self->{ DEFAULT } = $params->{ DEFAULT }; $self->{ ENCODING } = $params->{ ENCODING }; $self->{ STAT_TTL } = $params->{ STAT_TTL } || $STAT_TTL; $self->{ PARAMS } = $params; # look for user-provided UNICODE parameter or use default from package var $self->{ UNICODE } = defined $params->{ UNICODE } ? $params->{ UNICODE } : $UNICODE; return $self; } sub _fetch { my ($self, $name, $t_name) = @_; my $stat_ttl = $self->{ STAT_TTL }; $self->debug("_fetch($name)") if $self->{ DEBUG }; # First see if the named template is in the memory cache if ((my $slot = $self->{ LOOKUP }->{ $name })) { # Test if cache is fresh, and reload/compile if not. my ($data, $error) = $self->_refresh($slot); return $error ? ( $data, $error ) # $data may contain error text : $slot->[ DATA ]; # returned document object } # Otherwise, see if we already know the template is not found if (my $last_stat_time = $self->{ NOTFOUND }->{ $name }) { my $expires_in = $last_stat_time + $stat_ttl - time; if ($expires_in > 0) { $self->debug(" file [$name] in negative cache. Expires in $expires_in seconds") if $self->{ DEBUG }; return (undef, Template::Constants::STATUS_DECLINED); } else { delete $self->{ NOTFOUND }->{ $name }; } } # Is there an up-to-date compiled version on disk? if ($self->_compiled_is_current($name)) { # require() the compiled template. my $compiled_template = $self->_load_compiled( $self->_compiled_filename($name) ); # Store and return the compiled template return $self->store( $name, $compiled_template ) if $compiled_template; # Problem loading compiled template: # warn and continue to fetch source template warn($self->error(), "\n"); } # load template from source my ($template, $error) = $self->_load($name, $t_name); if ($error) { # Template could not be fetched. Add to the negative/notfound cache. $self->{ NOTFOUND }->{ $name } = time; return ( $template, $error ); } # compile template source ($template, $error) = $self->_compile($template, $self->_compiled_filename($name) ); if ($error) { # return any compile time error return ($template, $error); } else { # Store compiled template and return it return $self->store($name, $template->{data}) ; } } sub _fetch_path { my ($self, $name) = @_; $self->debug("_fetch_path($name)") if $self->{ DEBUG }; # the template may have been stored using a non-filename name # so look for the plain name in the cache first if ((my $slot = $self->{ LOOKUP }->{ $name })) { # cached entry exists, so refresh slot and extract data my ($data, $error) = $self->_refresh($slot); return $error ? ($data, $error) : ($slot->[ DATA ], $error ); } my $paths = $self->paths || return ( $self->error, Template::Constants::STATUS_ERROR ); # search the INCLUDE_PATH for the file, in cache or on disk foreach my $dir (@$paths) { my $path = File::Spec->catfile($dir, $name); $self->debug("searching path: $path\n") if $self->{ DEBUG }; my ($data, $error) = $self->_fetch( $path, $name ); # Return if no error or if a serious error. return ( $data, $error ) if !$error || $error == Template::Constants::STATUS_ERROR; } # not found in INCLUDE_PATH, now try DEFAULT return $self->_fetch_path( $self->{DEFAULT} ) if defined $self->{DEFAULT} && $name ne $self->{DEFAULT}; # We could not handle this template name return (undef, Template::Constants::STATUS_DECLINED); } sub _compiled_filename { my ($self, $file) = @_; my ($compext, $compdir) = @$self{ qw( COMPILE_EXT COMPILE_DIR ) }; my ($path, $compiled); return undef unless $compext || $compdir; $path = $file; $path =~ /^(.+)$/s or die "invalid filename: $path"; $path =~ s[:][]g if $^O eq 'MSWin32'; $compiled = "$path$compext"; $compiled = File::Spec->catfile($compdir, $compiled) if length $compdir; return $compiled; } sub _load_compiled { my ($self, $file) = @_; my $compiled; # load compiled template via require(); we zap any # %INC entry to ensure it is reloaded (we don't # want 1 returned by require() to say it's in memory) delete $INC{ $file }; eval { $compiled = require $file; }; return $@ ? $self->error("compiled template $compiled: $@") : $compiled; } sub _load { my ($self, $name, $alias) = @_; my ($data, $error); my $tolerant = $self->{ TOLERANT }; my $now = time; $alias = $name unless defined $alias or ref $name; $self->debug("_load($name, ", defined $alias ? $alias : '', ')') if $self->{ DEBUG }; # SCALAR ref is the template text if (ref $name eq 'SCALAR') { # $name can be a SCALAR reference to the input text... return { name => defined $alias ? $alias : 'input text', path => defined $alias ? $alias : 'input text', text => $$name, time => $now, load => 0, }; } # Otherwise, assume GLOB as a file handle if (ref $name) { local $/; my $text = <$name>; $text = $self->_decode_unicode($text) if $self->{ UNICODE }; return { name => defined $alias ? $alias : 'input file handle', path => defined $alias ? $alias : 'input file handle', text => $text, time => $now, load => 0, }; } # Otherwise, it's the name of the template if ( $self->_template_modified( $name ) ) { # does template exist? my ($text, $error, $mtime ) = $self->_template_content( $name ); unless ( $error ) { $text = $self->_decode_unicode($text) if $self->{ UNICODE }; return { name => $alias, path => $name, text => $text, time => $mtime, load => $now, }; } return ( "$alias: $!", Template::Constants::STATUS_ERROR ) unless $tolerant; } # Unable to process template, pass onto the next Provider. return (undef, Template::Constants::STATUS_DECLINED); } sub _refresh { my ($self, $slot) = @_; my $stat_ttl = $self->{ STAT_TTL }; my ($head, $file, $data, $error); $self->debug("_refresh([ ", join(', ', map { defined $_ ? $_ : '' } @$slot), '])') if $self->{ DEBUG }; # if it's more than $STAT_TTL seconds since we last performed a # stat() on the file then we need to do it again and see if the file # time has changed my $now = time; my $expires_in_sec = $slot->[ STAT ] + $stat_ttl - $now; if ( $expires_in_sec <= 0 ) { # Time to check! $slot->[ STAT ] = $now; # Grab mtime of template. # Seems like this should be abstracted to compare to # just ask for a newer compiled template (if it's newer) # and let that check for a newer template source. my $template_mtime = $self->_template_modified( $slot->[ NAME ] ); if ( ! defined $template_mtime || ( $template_mtime != $slot->[ LOAD ] )) { $self->debug("refreshing cache file ", $slot->[ NAME ]) if $self->{ DEBUG }; ($data, $error) = $self->_load($slot->[ NAME ], $slot->[ DATA ]->{ name }); ($data, $error) = $self->_compile($data) unless $error; if ($error) { # if the template failed to load/compile then we wipe out the # STAT entry. This forces the provider to try and reload it # each time instead of using the previously cached version # until $STAT_TTL is next up $slot->[ STAT ] = 0; } else { $slot->[ DATA ] = $data->{ data }; $slot->[ LOAD ] = $data->{ time }; } } } elsif ( $self->{ DEBUG } ) { $self->debug( sprintf('STAT_TTL not met for file [%s]. Expires in %d seconds', $slot->[ NAME ], $expires_in_sec ) ); } # Move this slot to the head of the list unless( $self->{ HEAD } == $slot ) { # remove existing slot from usage chain... if ($slot->[ PREV ]) { $slot->[ PREV ]->[ NEXT ] = $slot->[ NEXT ]; } else { $self->{ HEAD } = $slot->[ NEXT ]; } if ($slot->[ NEXT ]) { $slot->[ NEXT ]->[ PREV ] = $slot->[ PREV ]; } else { $self->{ TAIL } = $slot->[ PREV ]; } # ..and add to start of list $head = $self->{ HEAD }; $head->[ PREV ] = $slot if $head; $slot->[ PREV ] = undef; $slot->[ NEXT ] = $head; $self->{ HEAD } = $slot; } return ($data, $error); } sub _store { my ($self, $name, $data, $compfile) = @_; my $size = $self->{ SIZE }; my ($slot, $head); # Return if memory cache disabled. (overridding code should also check) # $$$ What's the expected behaviour of store()? Can't tell from the # docs if you can call store() when SIZE = 0. return $data->{data} if defined $size and !$size; # extract the compiled template from the data hash $data = $data->{ data }; $self->debug("_store($name, $data)") if $self->{ DEBUG }; # check the modification time -- extra stat here my $load = $self->_modified($name); if (defined $size && $self->{ SLOTS } >= $size) { # cache has reached size limit, so reuse oldest entry $self->debug("reusing oldest cache entry (size limit reached: $size)\nslots: $self->{ SLOTS }") if $self->{ DEBUG }; # remove entry from tail of list $slot = $self->{ TAIL }; $slot->[ PREV ]->[ NEXT ] = undef; $self->{ TAIL } = $slot->[ PREV ]; # remove name lookup for old node delete $self->{ LOOKUP }->{ $slot->[ NAME ] }; # add modified node to head of list $head = $self->{ HEAD }; $head->[ PREV ] = $slot if $head; @$slot = ( undef, $name, $data, $load, $head, time ); $self->{ HEAD } = $slot; # add name lookup for new node $self->{ LOOKUP }->{ $name } = $slot; } else { # cache is under size limit, or none is defined $self->debug("adding new cache entry") if $self->{ DEBUG }; # add new node to head of list $head = $self->{ HEAD }; $slot = [ undef, $name, $data, $load, $head, time ]; $head->[ PREV ] = $slot if $head; $self->{ HEAD } = $slot; $self->{ TAIL } = $slot unless $self->{ TAIL }; # add lookup from name to slot and increment nslots $self->{ LOOKUP }->{ $name } = $slot; $self->{ SLOTS }++; } return $data; } sub _compile { my ($self, $data, $compfile) = @_; my $text = $data->{ text }; my ($parsedoc, $error); $self->debug("_compile($data, ", defined $compfile ? $compfile : '', ')') if $self->{ DEBUG }; my $parser = $self->{ PARSER } ||= Template::Config->parser($self->{ PARAMS }) || return (Template::Config->error(), Template::Constants::STATUS_ERROR); # discard the template text - we don't need it any more delete $data->{ text }; # call parser to compile template into Perl code if ($parsedoc = $parser->parse($text, $data)) { $parsedoc->{ METADATA } = { 'name' => $data->{ name }, 'modtime' => $data->{ time }, %{ $parsedoc->{ METADATA } }, }; # write the Perl code to the file $compfile, if defined if ($compfile) { my $basedir = &File::Basename::dirname($compfile); $basedir =~ /(.*)/; $basedir = $1; unless (-d $basedir) { eval { File::Path::mkpath($basedir) }; $error = "failed to create compiled templates directory: $basedir ($@)" if ($@); } unless ($error) { my $docclass = $self->{ DOCUMENT }; $error = 'cache failed to write ' . &File::Basename::basename($compfile) . ': ' . $docclass->error() unless $docclass->write_perl_file($compfile, $parsedoc); } # set atime and mtime of newly compiled file, don't bother # if time is undef if (!defined($error) && defined $data->{ time }) { my ($cfile) = $compfile =~ /^(.+)$/s or do { return("invalid filename: $compfile", Template::Constants::STATUS_ERROR); }; my ($ctime) = $data->{ time } =~ /^(\d+)$/; unless ($ctime || $ctime eq 0) { return("invalid time: $ctime", Template::Constants::STATUS_ERROR); } utime($ctime, $ctime, $cfile); $self->debug(" cached compiled template to file [$compfile]") if $self->{ DEBUG }; } } unless ($error) { return $data ## RETURN ## if $data->{ data } = $DOCUMENT->new($parsedoc); $error = $Template::Document::ERROR; } } else { $error = Template::Exception->new( 'parse', "$data->{ name } " . $parser->error() ); } # return STATUS_ERROR, or STATUS_DECLINED if we're being tolerant return $self->{ TOLERANT } ? (undef, Template::Constants::STATUS_DECLINED) : ($error, Template::Constants::STATUS_ERROR) } sub _compiled_is_current { my ( $self, $template_name ) = @_; my $compiled_name = $self->_compiled_filename($template_name) || return; my $compiled_mtime = (stat($compiled_name))[9] || return; my $template_mtime = $self->_template_modified( $template_name ) || return; # This was >= in the 2.15, but meant that downgrading # a source template would not get picked up. return $compiled_mtime == $template_mtime; } sub _template_modified { my $self = shift; my $template = shift || return; return (stat( $template ))[9]; } sub _template_content { my ($self, $path) = @_; return (undef, "No path specified to fetch content from ") unless $path; my $data; my $mod_date; my $error; local *FH; if (open(FH, "< $path")) { local $/; binmode(FH); $data = ; $mod_date = (stat($path))[9]; close(FH); } else { $error = "$path: $!"; } return wantarray ? ( $data, $error, $mod_date ) : $data; } sub _modified { my ($self, $name, $time) = @_; my $load = $self->_template_modified($name) || return $time ? 1 : 0; return $time ? $load > $time : $load; } sub _dump { my $self = shift; my $size = $self->{ SIZE }; my $parser = $self->{ PARSER }; $parser = $parser ? $parser->_dump() : ''; $parser =~ s/\n/\n /gm; $size = 'unlimited' unless defined $size; my $output = "[Template::Provider] {\n"; my $format = " %-16s => %s\n"; my $key; $output .= sprintf($format, 'INCLUDE_PATH', '[ ' . join(', ', @{ $self->{ INCLUDE_PATH } }) . ' ]'); $output .= sprintf($format, 'CACHE_SIZE', $size); foreach $key (qw( ABSOLUTE RELATIVE TOLERANT DELIMITER COMPILE_EXT COMPILE_DIR )) { $output .= sprintf($format, $key, $self->{ $key }); } $output .= sprintf($format, 'PARSER', $parser); local $" = ', '; my $lookup = $self->{ LOOKUP }; $lookup = join('', map { sprintf(" $format", $_, defined $lookup->{ $_ } ? ('[ ' . join(', ', map { defined $_ ? $_ : '' } @{ $lookup->{ $_ } }) . ' ]') : ''); } sort keys %$lookup); $lookup = "{\n$lookup }"; $output .= sprintf($format, LOOKUP => $lookup); $output .= '}'; return $output; } sub _dump_cache { my $self = shift; my ($node, $lut, $count); $count = 0; if ($node = $self->{ HEAD }) { while ($node) { $lut->{ $node } = $count++; $node = $node->[ NEXT ]; } $node = $self->{ HEAD }; print STDERR "CACHE STATE:\n"; print STDERR " HEAD: ", $self->{ HEAD }->[ NAME ], "\n"; print STDERR " TAIL: ", $self->{ TAIL }->[ NAME ], "\n"; while ($node) { my ($prev, $name, $data, $load, $next) = @$node; $prev = $prev ? "#$lut->{ $prev }<-": ''; $next = $next ? "->#$lut->{ $next }": ''; print STDERR " #$lut->{ $node } : [ $prev, $name, $data, $load, $next ]\n"; $node = $node->[ NEXT ]; } } } sub _decode_unicode { my $self = shift; my $string = shift; return undef unless defined $string; use bytes; require Encode; return $string if Encode::is_utf8( $string ); # try all the BOMs in order looking for one (order is important # 32bit BOMs look like 16bit BOMs) my $count = 0; while ($count < @{ $boms }) { my $enc = $boms->[$count++]; my $bom = $boms->[$count++]; # does the string start with the bom? if ($bom eq substr($string, 0, length($bom))) { # decode it and hand it back return Encode::decode($enc, substr($string, length($bom)), 1); } } return $self->{ ENCODING } ? Encode::decode( $self->{ ENCODING }, $string ) : $string; } 1; } # # Inline include of Template.pm # BEGIN { $INC{'Template.pm'} = 'dummy/Template.pm'; } BEGIN { #line 0 "Template.pm" package Template; use strict; use warnings; use base 'Template::Base'; use Template::Config; use Template::Constants; use Template::Provider; use Template::Service; use File::Basename; use File::Path; our $VERSION = '2.20'; our $ERROR = ''; our $DEBUG = 0; our $BINMODE = 0 unless defined $BINMODE; our $AUTOLOAD; Template::Config->preload() if $ENV{ MOD_PERL }; sub process { my ($self, $template, $vars, $outstream, @opts) = @_; my ($output, $error); my $options = (@opts == 1) && UNIVERSAL::isa($opts[0], 'HASH') ? shift(@opts) : { @opts }; $options->{ binmode } = $BINMODE unless defined $options->{ binmode }; # we're using this for testing in t/output.t and t/filter.t so # don't remove it if you don't want tests to fail... $self->DEBUG("set binmode\n") if $DEBUG && $options->{ binmode }; $output = $self->{ SERVICE }->process($template, $vars); if (defined $output) { $outstream ||= $self->{ OUTPUT }; unless (ref $outstream) { my $outpath = $self->{ OUTPUT_PATH }; $outstream = "$outpath/$outstream" if $outpath; } # send processed template to output stream, checking for error return ($self->error($error)) if ($error = &_output($outstream, \$output, $options)); return 1; } else { return $self->error($self->{ SERVICE }->error); } } sub service { my $self = shift; return $self->{ SERVICE }; } sub context { my $self = shift; return $self->{ SERVICE }->{ CONTEXT }; } sub _init { my ($self, $config) = @_; # convert any textual DEBUG args to numerical form my $debug = $config->{ DEBUG }; $config->{ DEBUG } = Template::Constants::debug_flags($self, $debug) || return if defined $debug && $debug !~ /^\d+$/; # prepare a namespace handler for any CONSTANTS definition if (my $constants = $config->{ CONSTANTS }) { my $ns = $config->{ NAMESPACE } ||= { }; my $cns = $config->{ CONSTANTS_NAMESPACE } || 'constants'; $constants = Template::Config->constants($constants) || return $self->error(Template::Config->error); $ns->{ $cns } = $constants; } $self->{ SERVICE } = $config->{ SERVICE } || Template::Config->service($config) || return $self->error(Template::Config->error); $self->{ OUTPUT } = $config->{ OUTPUT } || \*STDOUT; $self->{ OUTPUT_PATH } = $config->{ OUTPUT_PATH }; return $self; } sub _output { my ($where, $textref, $options) = @_; my $reftype; my $error = 0; # call a CODE reference if (($reftype = ref($where)) eq 'CODE') { &$where($$textref); } # print to a glob (such as \*STDOUT) elsif ($reftype eq 'GLOB') { print $where $$textref; } # append output to a SCALAR ref elsif ($reftype eq 'SCALAR') { $$where .= $$textref; } # push onto ARRAY ref elsif ($reftype eq 'ARRAY') { push @$where, $$textref; } # call the print() method on an object that implements the method # (e.g. IO::Handle, Apache::Request, etc) elsif (UNIVERSAL::can($where, 'print')) { $where->print($$textref); } # a simple string is taken as a filename elsif (! $reftype) { local *FP; # make destination directory if it doesn't exist my $dir = dirname($where); eval { mkpath($dir) unless -d $dir; }; if ($@) { # strip file name and line number from error raised by die() ($error = $@) =~ s/ at \S+ line \d+\n?$//; } elsif (open(FP, ">$where")) { # binmode option can be 1 or a specific layer, e.g. :utf8 my $bm = $options->{ binmode }; if ($bm && $bm eq 1) { binmode FP; } elsif ($bm){ binmode FP, $bm; } print FP $$textref; close FP; } else { $error = "$where: $!"; } } # give up, we've done our best else { $error = "output_handler() cannot determine target type ($where)\n"; } return $error; } 1; } # # Inline include of Template/Grammar.pm # BEGIN { $INC{'Template/Grammar.pm'} = 'dummy/Template/Grammar.pm'; } BEGIN { #line 0 "Template/Grammar.pm" package Template::Grammar; use strict; use warnings; our $VERSION = 2.25; my (@RESERVED, %CMPOP, $LEXTABLE, $RULES, $STATES); my ($factory, $rawstart); @RESERVED = qw( GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER BLOCK END USE PLUGIN FILTER MACRO PERL RAWPERL TO STEP AND OR NOT DIV MOD IF UNLESS ELSE ELSIF FOR NEXT WHILE SWITCH CASE META IN TRY THROW CATCH FINAL LAST RETURN STOP CLEAR VIEW DEBUG ); %CMPOP = qw( != ne == eq < < > > >= >= <= <= ); $LEXTABLE = { 'FOREACH' => 'FOR', 'BREAK' => 'LAST', '&&' => 'AND', '||' => 'OR', '!' => 'NOT', '|' => 'FILTER', '.' => 'DOT', '_' => 'CAT', '..' => 'TO', '=' => 'ASSIGN', '=>' => 'ASSIGN', ',' => 'COMMA', '\\' => 'REF', 'and' => 'AND', # explicitly specified so that qw( and or 'or' => 'OR', # not ) can always be used in lower case, 'not' => 'NOT', # regardless of ANYCASE flag 'mod' => 'MOD', 'div' => 'DIV', }; { my @tokens = qw< ( ) [ ] { } ${ $ + / ; : ? >; my @cmpop = keys %CMPOP; my @binop = qw( - * % ); # '+' and '/' above, in @tokens # fill lexer table, slice by slice, with reserved words and operators @$LEXTABLE{ @RESERVED, @cmpop, @binop, @tokens } = ( @RESERVED, ('CMPOP') x @cmpop, ('BINOP') x @binop, @tokens ); } sub new { my $class = shift; bless { LEXTABLE => $LEXTABLE, STATES => $STATES, RULES => $RULES, }, $class; } sub install_factory { my ($self, $new_factory) = @_; $factory = $new_factory; } $STATES = [ {#State 0 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'loop' => 4, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'atomdir' => 12, 'anonblock' => 50, 'template' => 52, 'defblockname' => 14, 'ident' => 16, 'assign' => 19, 'macro' => 20, 'lterm' => 56, 'node' => 23, 'term' => 58, 'rawperl' => 59, 'expr' => 62, 'use' => 63, 'defblock' => 66, 'filter' => 29, 'sterm' => 68, 'perl' => 31, 'chunks' => 33, 'setlist' => 70, 'try' => 35, 'switch' => 34, 'directive' => 71, 'block' => 72, 'condition' => 73 } }, {#State 1 ACTIONS => { "\$" => 43, 'LITERAL' => 75, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'setlist' => 76, 'item' => 39, 'assign' => 19, 'node' => 23, 'ident' => 74 } }, {#State 2 DEFAULT => -130 }, {#State 3 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 79, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 4 DEFAULT => -23 }, {#State 5 ACTIONS => { ";" => 80 } }, {#State 6 DEFAULT => -37 }, {#State 7 DEFAULT => -14 }, {#State 8 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 90, 'filename' => 85, 'name' => 82 } }, {#State 9 ACTIONS => { "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "]" => 94, "\${" => 37 }, GOTOS => { 'sterm' => 96, 'item' => 39, 'range' => 93, 'node' => 23, 'ident' => 77, 'term' => 95, 'lterm' => 56, 'list' => 92 } }, {#State 10 ACTIONS => { ";" => 97 } }, {#State 11 DEFAULT => -5 }, {#State 12 ACTIONS => { ";" => -20 }, DEFAULT => -27 }, {#State 13 DEFAULT => -78, GOTOS => { '@5-1' => 98 } }, {#State 14 ACTIONS => { 'IDENT' => 99 }, DEFAULT => -87, GOTOS => { 'blockargs' => 102, 'metadata' => 101, 'meta' => 100 } }, {#State 15 ACTIONS => { 'IDENT' => 99 }, GOTOS => { 'metadata' => 103, 'meta' => 100 } }, {#State 16 ACTIONS => { 'DOT' => 104, 'ASSIGN' => 105 }, DEFAULT => -109 }, {#State 17 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 106, 'filename' => 85, 'name' => 82 } }, {#State 18 ACTIONS => { 'IDENT' => 107 } }, {#State 19 DEFAULT => -149 }, {#State 20 DEFAULT => -12 }, {#State 21 ACTIONS => { "{" => 30, 'LITERAL' => 78, 'IDENT' => 108, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'sterm' => 68, 'item' => 39, 'loopvar' => 110, 'node' => 23, 'ident' => 77, 'term' => 109, 'lterm' => 56 } }, {#State 22 DEFAULT => -40 }, {#State 23 DEFAULT => -127 }, {#State 24 DEFAULT => -6 }, {#State 25 ACTIONS => { "\"" => 117, "\$" => 114, 'LITERAL' => 116, 'FILENAME' => 83, 'IDENT' => 111, 'NUMBER' => 84, "\${" => 37 }, GOTOS => { 'names' => 91, 'lvalue' => 112, 'item' => 113, 'name' => 82, 'filepart' => 87, 'filename' => 85, 'nameargs' => 118, 'lnameargs' => 115 } }, {#State 26 DEFAULT => -113 }, {#State 27 ACTIONS => { "\$" => 43, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'ident' => 119 } }, {#State 28 ACTIONS => { 'LITERAL' => 124, 'FILENAME' => 83, 'IDENT' => 120, 'NUMBER' => 84 }, DEFAULT => -87, GOTOS => { 'blockargs' => 123, 'filepart' => 87, 'filename' => 122, 'blockname' => 121, 'metadata' => 101, 'meta' => 100 } }, {#State 29 DEFAULT => -43 }, {#State 30 ACTIONS => { "\$" => 43, 'LITERAL' => 129, 'IDENT' => 2, "\${" => 37 }, DEFAULT => -119, GOTOS => { 'params' => 128, 'hash' => 125, 'item' => 126, 'param' => 127 } }, {#State 31 DEFAULT => -25 }, {#State 32 ACTIONS => { "\"" => 117, "\$" => 114, 'LITERAL' => 116, 'FILENAME' => 83, 'IDENT' => 111, 'NUMBER' => 84, "\${" => 37 }, GOTOS => { 'names' => 91, 'lvalue' => 112, 'item' => 113, 'name' => 82, 'filepart' => 87, 'filename' => 85, 'nameargs' => 118, 'lnameargs' => 130 } }, {#State 33 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -2, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 131, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'try' => 35, 'switch' => 34, 'assign' => 19, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 34 DEFAULT => -22 }, {#State 35 DEFAULT => -24 }, {#State 36 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 132, 'filename' => 85, 'name' => 82 } }, {#State 37 ACTIONS => { "\"" => 60, "\$" => 43, 'LITERAL' => 78, 'IDENT' => 2, 'REF' => 27, 'NUMBER' => 26, "\${" => 37 }, GOTOS => { 'sterm' => 133, 'item' => 39, 'node' => 23, 'ident' => 77 } }, {#State 38 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 134, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 39 ACTIONS => { "(" => 135 }, DEFAULT => -128 }, {#State 40 ACTIONS => { ";" => 136 } }, {#State 41 DEFAULT => -38 }, {#State 42 DEFAULT => -11 }, {#State 43 ACTIONS => { 'IDENT' => 137 } }, {#State 44 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 138, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 45 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 139, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 46 DEFAULT => -42 }, {#State 47 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 140, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 48 ACTIONS => { 'IF' => 144, 'FILTER' => 143, 'FOR' => 142, 'WHILE' => 146, 'WRAPPER' => 145, 'UNLESS' => 141 } }, {#State 49 DEFAULT => -39 }, {#State 50 DEFAULT => -10 }, {#State 51 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 147, 'filename' => 85, 'name' => 82 } }, {#State 52 ACTIONS => { '' => 148 } }, {#State 53 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 57, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 151, 'sterm' => 68, 'item' => 39, 'assign' => 150, 'node' => 23, 'ident' => 149, 'term' => 58, 'lterm' => 56 } }, {#State 54 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 152, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 55 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 153, 'filename' => 85, 'name' => 82 } }, {#State 56 DEFAULT => -103 }, {#State 57 ACTIONS => { 'ASSIGN' => 154 }, DEFAULT => -112 }, {#State 58 DEFAULT => -146 }, {#State 59 DEFAULT => -15 }, {#State 60 DEFAULT => -176, GOTOS => { 'quoted' => 155 } }, {#State 61 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 156, 'filename' => 85, 'name' => 82 } }, {#State 62 ACTIONS => { ";" => -16, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -26 }, {#State 63 DEFAULT => -13 }, {#State 64 DEFAULT => -36 }, {#State 65 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 167, 'filename' => 85, 'name' => 82 } }, {#State 66 DEFAULT => -9 }, {#State 67 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 168, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 68 DEFAULT => -104 }, {#State 69 ACTIONS => { "\$" => 43, 'LITERAL' => 75, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'setlist' => 169, 'item' => 39, 'assign' => 19, 'node' => 23, 'ident' => 74 } }, {#State 70 ACTIONS => { "\$" => 43, 'COMMA' => 171, 'LITERAL' => 75, 'IDENT' => 2, "\${" => 37 }, DEFAULT => -19, GOTOS => { 'item' => 39, 'assign' => 170, 'node' => 23, 'ident' => 74 } }, {#State 71 DEFAULT => -8 }, {#State 72 DEFAULT => -1 }, {#State 73 DEFAULT => -21 }, {#State 74 ACTIONS => { 'ASSIGN' => 172, 'DOT' => 104 } }, {#State 75 ACTIONS => { 'ASSIGN' => 154 } }, {#State 76 ACTIONS => { 'COMMA' => 171, 'LITERAL' => 75, 'IDENT' => 2, "\$" => 43, "\${" => 37 }, DEFAULT => -30, GOTOS => { 'item' => 39, 'assign' => 170, 'node' => 23, 'ident' => 74 } }, {#State 77 ACTIONS => { 'DOT' => 104 }, DEFAULT => -109 }, {#State 78 DEFAULT => -112 }, {#State 79 ACTIONS => { 'CMPOP' => 164, "?" => 158, ";" => 173, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 } }, {#State 80 DEFAULT => -7 }, {#State 81 DEFAULT => -173 }, {#State 82 DEFAULT => -166 }, {#State 83 DEFAULT => -172 }, {#State 84 DEFAULT => -174 }, {#State 85 ACTIONS => { 'DOT' => 174 }, DEFAULT => -168 }, {#State 86 ACTIONS => { "\$" => 43, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'ident' => 175 } }, {#State 87 DEFAULT => -171 }, {#State 88 DEFAULT => -169 }, {#State 89 DEFAULT => -176, GOTOS => { 'quoted' => 176 } }, {#State 90 DEFAULT => -35 }, {#State 91 ACTIONS => { "+" => 177, "(" => 178 }, DEFAULT => -156, GOTOS => { 'args' => 179 } }, {#State 92 ACTIONS => { "{" => 30, 'COMMA' => 182, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "]" => 180, "\${" => 37 }, GOTOS => { 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 181, 'lterm' => 56 } }, {#State 93 ACTIONS => { "]" => 183 } }, {#State 94 DEFAULT => -107 }, {#State 95 DEFAULT => -116 }, {#State 96 ACTIONS => { 'TO' => 184 }, DEFAULT => -104 }, {#State 97 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 185, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 98 ACTIONS => { ";" => 186 } }, {#State 99 ACTIONS => { 'ASSIGN' => 187 } }, {#State 100 DEFAULT => -99 }, {#State 101 ACTIONS => { 'COMMA' => 189, 'IDENT' => 99 }, DEFAULT => -86, GOTOS => { 'meta' => 188 } }, {#State 102 ACTIONS => { ";" => 190 } }, {#State 103 ACTIONS => { 'COMMA' => 189, 'IDENT' => 99 }, DEFAULT => -17, GOTOS => { 'meta' => 188 } }, {#State 104 ACTIONS => { "\$" => 43, 'IDENT' => 2, 'NUMBER' => 192, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 191 } }, {#State 105 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'WRAPPER' => 55, 'FOR' => 21, 'NEXT' => 22, 'LITERAL' => 57, "\"" => 60, 'PROCESS' => 61, 'FILTER' => 25, 'RETURN' => 64, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 193, 'DEFAULT' => 69, "{" => 30, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'term' => 58, 'loop' => 4, 'expr' => 195, 'wrapper' => 46, 'atomexpr' => 48, 'atomdir' => 12, 'mdir' => 194, 'filter' => 29, 'sterm' => 68, 'ident' => 149, 'perl' => 31, 'setlist' => 70, 'try' => 35, 'switch' => 34, 'assign' => 19, 'directive' => 196, 'condition' => 73, 'lterm' => 56 } }, {#State 106 DEFAULT => -33 }, {#State 107 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'INCLUDE' => 17, "(" => 198, 'SWITCH' => 54, 'WRAPPER' => 55, 'FOR' => 21, 'NEXT' => 22, 'LITERAL' => 57, "\"" => 60, 'PROCESS' => 61, 'FILTER' => 25, 'RETURN' => 64, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 193, 'DEFAULT' => 69, "{" => 30, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'term' => 58, 'loop' => 4, 'expr' => 199, 'wrapper' => 46, 'atomexpr' => 48, 'atomdir' => 12, 'mdir' => 197, 'filter' => 29, 'sterm' => 68, 'ident' => 149, 'perl' => 31, 'setlist' => 70, 'try' => 35, 'switch' => 34, 'assign' => 19, 'directive' => 196, 'condition' => 73, 'lterm' => 56 } }, {#State 108 ACTIONS => { 'IN' => 201, 'ASSIGN' => 200 }, DEFAULT => -130 }, {#State 109 DEFAULT => -156, GOTOS => { 'args' => 202 } }, {#State 110 ACTIONS => { ";" => 203 } }, {#State 111 ACTIONS => { 'ASSIGN' => -130 }, DEFAULT => -173 }, {#State 112 ACTIONS => { 'ASSIGN' => 204 } }, {#State 113 DEFAULT => -159 }, {#State 114 ACTIONS => { "\$" => 43, 'IDENT' => 205, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'ident' => 175 } }, {#State 115 ACTIONS => { ";" => 206 } }, {#State 116 ACTIONS => { 'ASSIGN' => -161 }, DEFAULT => -169 }, {#State 117 DEFAULT => -176, GOTOS => { 'quoted' => 207 } }, {#State 118 DEFAULT => -158 }, {#State 119 ACTIONS => { 'DOT' => 104 }, DEFAULT => -110 }, {#State 120 ACTIONS => { 'ASSIGN' => 187 }, DEFAULT => -173 }, {#State 121 DEFAULT => -83 }, {#State 122 ACTIONS => { 'DOT' => 174 }, DEFAULT => -84 }, {#State 123 ACTIONS => { ";" => 208 } }, {#State 124 DEFAULT => -85 }, {#State 125 ACTIONS => { "}" => 209 } }, {#State 126 ACTIONS => { 'ASSIGN' => 210 } }, {#State 127 DEFAULT => -122 }, {#State 128 ACTIONS => { "\$" => 43, 'COMMA' => 212, 'LITERAL' => 129, 'IDENT' => 2, "\${" => 37 }, DEFAULT => -118, GOTOS => { 'item' => 126, 'param' => 211 } }, {#State 129 ACTIONS => { 'ASSIGN' => 213 } }, {#State 130 DEFAULT => -73 }, {#State 131 DEFAULT => -4 }, {#State 132 ACTIONS => { ";" => 214 } }, {#State 133 ACTIONS => { "}" => 215 } }, {#State 134 ACTIONS => { 'DIV' => 159, 'BINOP' => 161, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, 'MOD' => 165, "/" => 166 }, DEFAULT => -142 }, {#State 135 DEFAULT => -156, GOTOS => { 'args' => 216 } }, {#State 136 DEFAULT => -76, GOTOS => { '@4-2' => 217 } }, {#State 137 DEFAULT => -132 }, {#State 138 ACTIONS => { 'CMPOP' => 164, "?" => 158, ";" => 218, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 } }, {#State 139 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -29 }, {#State 140 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -28 }, {#State 141 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 219, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 142 ACTIONS => { "{" => 30, 'LITERAL' => 78, 'IDENT' => 108, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'sterm' => 68, 'item' => 39, 'loopvar' => 220, 'node' => 23, 'ident' => 77, 'term' => 109, 'lterm' => 56 } }, {#State 143 ACTIONS => { "\"" => 117, "\$" => 114, 'LITERAL' => 116, 'FILENAME' => 83, 'IDENT' => 111, 'NUMBER' => 84, "\${" => 37 }, GOTOS => { 'names' => 91, 'lvalue' => 112, 'item' => 113, 'name' => 82, 'filepart' => 87, 'filename' => 85, 'nameargs' => 118, 'lnameargs' => 221 } }, {#State 144 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 222, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 145 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 223, 'filename' => 85, 'name' => 82 } }, {#State 146 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 224, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 147 DEFAULT => -41 }, {#State 148 DEFAULT => 0 }, {#State 149 ACTIONS => { 'DOT' => 104, 'ASSIGN' => 172 }, DEFAULT => -109 }, {#State 150 ACTIONS => { ")" => 225 } }, {#State 151 ACTIONS => { 'CMPOP' => 164, "?" => 158, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, ")" => 226, 'OR' => 162 } }, {#State 152 ACTIONS => { 'CMPOP' => 164, "?" => 158, ";" => 227, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 } }, {#State 153 ACTIONS => { ";" => 228 } }, {#State 154 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 229, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 155 ACTIONS => { "\"" => 234, 'TEXT' => 231, ";" => 233, "\$" => 43, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'ident' => 230, 'quotable' => 232 } }, {#State 156 DEFAULT => -34 }, {#State 157 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 235, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 158 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 236, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 159 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 237, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 160 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 238, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 161 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 239, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 162 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 240, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 163 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 241, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 164 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 242, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 165 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 243, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 166 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 244, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 167 DEFAULT => -32 }, {#State 168 ACTIONS => { 'CMPOP' => 164, "?" => 158, ";" => 245, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 } }, {#State 169 ACTIONS => { 'COMMA' => 171, 'LITERAL' => 75, 'IDENT' => 2, "\$" => 43, "\${" => 37 }, DEFAULT => -31, GOTOS => { 'item' => 39, 'assign' => 170, 'node' => 23, 'ident' => 74 } }, {#State 170 DEFAULT => -147 }, {#State 171 DEFAULT => -148 }, {#State 172 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 246, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 173 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 247, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 174 ACTIONS => { 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 248 } }, {#State 175 ACTIONS => { 'DOT' => 104 }, DEFAULT => -156, GOTOS => { 'args' => 249 } }, {#State 176 ACTIONS => { "\"" => 250, 'TEXT' => 231, ";" => 233, "\$" => 43, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'ident' => 230, 'quotable' => 232 } }, {#State 177 ACTIONS => { "\"" => 89, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'filename' => 85, 'name' => 251 } }, {#State 178 DEFAULT => -156, GOTOS => { 'args' => 252 } }, {#State 179 ACTIONS => { 'NOT' => 38, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "{" => 30, 'COMMA' => 258, "(" => 53, "\${" => 37 }, DEFAULT => -163, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 180 DEFAULT => -105 }, {#State 181 DEFAULT => -114 }, {#State 182 DEFAULT => -115 }, {#State 183 DEFAULT => -106 }, {#State 184 ACTIONS => { "\"" => 60, "\$" => 43, 'LITERAL' => 78, 'IDENT' => 2, 'REF' => 27, 'NUMBER' => 26, "\${" => 37 }, GOTOS => { 'sterm' => 259, 'item' => 39, 'node' => 23, 'ident' => 77 } }, {#State 185 ACTIONS => { 'FINAL' => 260, 'CATCH' => 262 }, DEFAULT => -72, GOTOS => { 'final' => 261 } }, {#State 186 ACTIONS => { 'TEXT' => 263 } }, {#State 187 ACTIONS => { "\"" => 266, 'LITERAL' => 265, 'NUMBER' => 264 } }, {#State 188 DEFAULT => -97 }, {#State 189 DEFAULT => -98 }, {#State 190 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'loop' => 4, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'atomdir' => 12, 'anonblock' => 50, 'template' => 267, 'defblockname' => 14, 'ident' => 16, 'assign' => 19, 'macro' => 20, 'lterm' => 56, 'node' => 23, 'term' => 58, 'rawperl' => 59, 'expr' => 62, 'use' => 63, 'defblock' => 66, 'filter' => 29, 'sterm' => 68, 'perl' => 31, 'chunks' => 33, 'setlist' => 70, 'switch' => 34, 'try' => 35, 'directive' => 71, 'block' => 72, 'condition' => 73 } }, {#State 191 DEFAULT => -125 }, {#State 192 DEFAULT => -126 }, {#State 193 ACTIONS => { ";" => 268 } }, {#State 194 DEFAULT => -89 }, {#State 195 ACTIONS => { ";" => -150, "+" => 157, 'LITERAL' => -150, 'IDENT' => -150, 'CAT' => 163, "\$" => -150, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, 'COMMA' => -150, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162, "\${" => -150 }, DEFAULT => -26 }, {#State 196 DEFAULT => -92 }, {#State 197 DEFAULT => -91 }, {#State 198 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 57, 'IDENT' => 269, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 151, 'sterm' => 68, 'item' => 39, 'assign' => 150, 'margs' => 270, 'node' => 23, 'ident' => 149, 'term' => 58, 'lterm' => 56 } }, {#State 199 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -26 }, {#State 200 ACTIONS => { "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 271, 'lterm' => 56 } }, {#State 201 ACTIONS => { "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 272, 'lterm' => 56 } }, {#State 202 ACTIONS => { 'NOT' => 38, "{" => 30, 'COMMA' => 258, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, DEFAULT => -64, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 203 DEFAULT => -56, GOTOS => { '@1-3' => 273 } }, {#State 204 ACTIONS => { "\"" => 89, "\$" => 86, 'LITERAL' => 88, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'names' => 91, 'nameargs' => 274, 'filename' => 85, 'name' => 82 } }, {#State 205 ACTIONS => { 'ASSIGN' => -132 }, DEFAULT => -130 }, {#State 206 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 275, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 207 ACTIONS => { "\"" => 276, 'TEXT' => 231, ";" => 233, "\$" => 43, 'IDENT' => 2, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'ident' => 230, 'quotable' => 232 } }, {#State 208 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 277, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 209 DEFAULT => -108 }, {#State 210 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 278, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 211 DEFAULT => -120 }, {#State 212 DEFAULT => -121 }, {#State 213 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 279, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 214 DEFAULT => -74, GOTOS => { '@3-3' => 280 } }, {#State 215 DEFAULT => -131 }, {#State 216 ACTIONS => { 'NOT' => 38, "{" => 30, 'COMMA' => 258, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, ")" => 281, "\${" => 37 }, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 217 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 282, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 218 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 283, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 219 ACTIONS => { 'CMPOP' => 164, "?" => 158, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -47 }, {#State 220 DEFAULT => -58 }, {#State 221 DEFAULT => -81 }, {#State 222 ACTIONS => { 'CMPOP' => 164, "?" => 158, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -45 }, {#State 223 DEFAULT => -66 }, {#State 224 ACTIONS => { 'CMPOP' => 164, "?" => 158, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -61 }, {#State 225 DEFAULT => -144 }, {#State 226 DEFAULT => -145 }, {#State 227 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 284, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 228 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 285, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 229 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -151 }, {#State 230 ACTIONS => { 'DOT' => 104 }, DEFAULT => -177 }, {#State 231 DEFAULT => -178 }, {#State 232 DEFAULT => -175 }, {#State 233 DEFAULT => -179 }, {#State 234 DEFAULT => -111 }, {#State 235 ACTIONS => { 'DIV' => 159, 'MOD' => 165, "/" => 166 }, DEFAULT => -135 }, {#State 236 ACTIONS => { ":" => 286, 'CMPOP' => 164, "?" => 158, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 } }, {#State 237 ACTIONS => { 'MOD' => 165 }, DEFAULT => -136 }, {#State 238 ACTIONS => { 'DIV' => 159, 'BINOP' => 161, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, 'MOD' => 165, "/" => 166 }, DEFAULT => -140 }, {#State 239 ACTIONS => { 'DIV' => 159, "+" => 157, 'MOD' => 165, "/" => 166 }, DEFAULT => -133 }, {#State 240 ACTIONS => { 'DIV' => 159, 'BINOP' => 161, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, 'MOD' => 165, "/" => 166 }, DEFAULT => -141 }, {#State 241 ACTIONS => { 'DIV' => 159, 'BINOP' => 161, "+" => 157, 'CMPOP' => 164, 'MOD' => 165, "/" => 166 }, DEFAULT => -139 }, {#State 242 ACTIONS => { 'DIV' => 159, 'BINOP' => 161, "+" => 157, 'MOD' => 165, "/" => 166 }, DEFAULT => -138 }, {#State 243 DEFAULT => -137 }, {#State 244 ACTIONS => { 'DIV' => 159, 'MOD' => 165 }, DEFAULT => -134 }, {#State 245 DEFAULT => -59, GOTOS => { '@2-3' => 287 } }, {#State 246 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -150 }, {#State 247 ACTIONS => { 'ELSIF' => 290, 'ELSE' => 288 }, DEFAULT => -50, GOTOS => { 'else' => 289 } }, {#State 248 DEFAULT => -170 }, {#State 249 ACTIONS => { 'NOT' => 38, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "{" => 30, 'COMMA' => 258, "(" => 53, "\${" => 37 }, DEFAULT => -162, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 250 DEFAULT => -167 }, {#State 251 DEFAULT => -165 }, {#State 252 ACTIONS => { 'NOT' => 38, "{" => 30, 'COMMA' => 258, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, ")" => 291, "\${" => 37 }, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 253 ACTIONS => { 'DOT' => 104, 'ASSIGN' => 292 }, DEFAULT => -109 }, {#State 254 ACTIONS => { "(" => 135, 'ASSIGN' => 210 }, DEFAULT => -128 }, {#State 255 DEFAULT => -153 }, {#State 256 ACTIONS => { 'ASSIGN' => 213 }, DEFAULT => -112 }, {#State 257 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -152 }, {#State 258 DEFAULT => -155 }, {#State 259 DEFAULT => -117 }, {#State 260 ACTIONS => { ";" => 293 } }, {#State 261 ACTIONS => { 'END' => 294 } }, {#State 262 ACTIONS => { ";" => 296, 'DEFAULT' => 297, 'FILENAME' => 83, 'IDENT' => 81, 'NUMBER' => 84 }, GOTOS => { 'filepart' => 87, 'filename' => 295 } }, {#State 263 ACTIONS => { 'END' => 298 } }, {#State 264 DEFAULT => -102 }, {#State 265 DEFAULT => -100 }, {#State 266 ACTIONS => { 'TEXT' => 299 } }, {#State 267 ACTIONS => { 'END' => 300 } }, {#State 268 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 301, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 269 ACTIONS => { 'IDENT' => -96, ")" => -96, 'COMMA' => -96 }, DEFAULT => -130 }, {#State 270 ACTIONS => { 'COMMA' => 304, 'IDENT' => 302, ")" => 303 } }, {#State 271 DEFAULT => -156, GOTOS => { 'args' => 305 } }, {#State 272 DEFAULT => -156, GOTOS => { 'args' => 306 } }, {#State 273 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 307, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 274 DEFAULT => -157 }, {#State 275 ACTIONS => { 'END' => 308 } }, {#State 276 ACTIONS => { 'ASSIGN' => -160 }, DEFAULT => -167 }, {#State 277 ACTIONS => { 'END' => 309 } }, {#State 278 ACTIONS => { 'DIV' => 159, 'AND' => 160, 'BINOP' => 161, 'OR' => 162, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'MOD' => 165, "/" => 166 }, DEFAULT => -124 }, {#State 279 ACTIONS => { 'DIV' => 159, 'AND' => 160, 'BINOP' => 161, 'OR' => 162, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'MOD' => 165, "/" => 166 }, DEFAULT => -123 }, {#State 280 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 310, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 281 DEFAULT => -129 }, {#State 282 ACTIONS => { 'END' => 311 } }, {#State 283 ACTIONS => { 'ELSIF' => 290, 'ELSE' => 288 }, DEFAULT => -50, GOTOS => { 'else' => 312 } }, {#State 284 ACTIONS => { 'CASE' => 313 }, DEFAULT => -55, GOTOS => { 'case' => 314 } }, {#State 285 ACTIONS => { 'END' => 315 } }, {#State 286 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 316, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 287 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 317, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 288 ACTIONS => { ";" => 318 } }, {#State 289 ACTIONS => { 'END' => 319 } }, {#State 290 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 320, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 291 DEFAULT => -164 }, {#State 292 ACTIONS => { 'NOT' => 38, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'expr' => 321, 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 58, 'lterm' => 56 } }, {#State 293 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 322, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 294 DEFAULT => -67 }, {#State 295 ACTIONS => { 'DOT' => 174, ";" => 323 } }, {#State 296 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 324, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 297 ACTIONS => { ";" => 325 } }, {#State 298 DEFAULT => -79 }, {#State 299 ACTIONS => { "\"" => 326 } }, {#State 300 DEFAULT => -82 }, {#State 301 ACTIONS => { 'END' => 327 } }, {#State 302 DEFAULT => -94 }, {#State 303 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'WRAPPER' => 55, 'FOR' => 21, 'NEXT' => 22, 'LITERAL' => 57, "\"" => 60, 'PROCESS' => 61, 'FILTER' => 25, 'RETURN' => 64, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 193, 'DEFAULT' => 69, "{" => 30, "\${" => 37 }, GOTOS => { 'item' => 39, 'node' => 23, 'term' => 58, 'loop' => 4, 'expr' => 199, 'wrapper' => 46, 'atomexpr' => 48, 'atomdir' => 12, 'mdir' => 328, 'filter' => 29, 'sterm' => 68, 'ident' => 149, 'perl' => 31, 'setlist' => 70, 'try' => 35, 'switch' => 34, 'assign' => 19, 'directive' => 196, 'condition' => 73, 'lterm' => 56 } }, {#State 304 DEFAULT => -95 }, {#State 305 ACTIONS => { 'NOT' => 38, "{" => 30, 'COMMA' => 258, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, DEFAULT => -62, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 306 ACTIONS => { 'NOT' => 38, "{" => 30, 'COMMA' => 258, 'LITERAL' => 256, 'IDENT' => 2, "\"" => 60, "(" => 53, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, DEFAULT => -63, GOTOS => { 'expr' => 257, 'sterm' => 68, 'item' => 254, 'param' => 255, 'node' => 23, 'ident' => 253, 'term' => 58, 'lterm' => 56 } }, {#State 307 ACTIONS => { 'END' => 329 } }, {#State 308 DEFAULT => -80 }, {#State 309 DEFAULT => -88 }, {#State 310 ACTIONS => { 'END' => 330 } }, {#State 311 DEFAULT => -77 }, {#State 312 ACTIONS => { 'END' => 331 } }, {#State 313 ACTIONS => { ";" => 332, 'DEFAULT' => 334, "{" => 30, 'LITERAL' => 78, 'IDENT' => 2, "\"" => 60, "\$" => 43, "[" => 9, 'NUMBER' => 26, 'REF' => 27, "\${" => 37 }, GOTOS => { 'sterm' => 68, 'item' => 39, 'node' => 23, 'ident' => 77, 'term' => 333, 'lterm' => 56 } }, {#State 314 ACTIONS => { 'END' => 335 } }, {#State 315 DEFAULT => -65 }, {#State 316 ACTIONS => { 'DIV' => 159, 'AND' => 160, 'BINOP' => 161, 'OR' => 162, "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'MOD' => 165, "/" => 166 }, DEFAULT => -143 }, {#State 317 ACTIONS => { 'END' => 336 } }, {#State 318 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 337, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 319 DEFAULT => -46 }, {#State 320 ACTIONS => { 'CMPOP' => 164, "?" => 158, ";" => 338, "+" => 157, 'MOD' => 165, 'DIV' => 159, "/" => 166, 'AND' => 160, 'CAT' => 163, 'BINOP' => 161, 'OR' => 162 } }, {#State 321 ACTIONS => { "+" => 157, 'CAT' => 163, 'CMPOP' => 164, "?" => 158, 'DIV' => 159, 'MOD' => 165, "/" => 166, 'AND' => 160, 'BINOP' => 161, 'OR' => 162 }, DEFAULT => -154 }, {#State 322 DEFAULT => -71 }, {#State 323 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 339, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 324 ACTIONS => { 'FINAL' => 260, 'CATCH' => 262 }, DEFAULT => -72, GOTOS => { 'final' => 340 } }, {#State 325 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 341, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 326 DEFAULT => -101 }, {#State 327 DEFAULT => -93 }, {#State 328 DEFAULT => -90 }, {#State 329 DEFAULT => -57 }, {#State 330 DEFAULT => -75 }, {#State 331 DEFAULT => -44 }, {#State 332 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 342, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 333 ACTIONS => { ";" => 343 } }, {#State 334 ACTIONS => { ";" => 344 } }, {#State 335 DEFAULT => -51 }, {#State 336 DEFAULT => -60 }, {#State 337 DEFAULT => -49 }, {#State 338 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 345, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 339 ACTIONS => { 'FINAL' => 260, 'CATCH' => 262 }, DEFAULT => -72, GOTOS => { 'final' => 346 } }, {#State 340 DEFAULT => -70 }, {#State 341 ACTIONS => { 'FINAL' => 260, 'CATCH' => 262 }, DEFAULT => -72, GOTOS => { 'final' => 347 } }, {#State 342 DEFAULT => -54 }, {#State 343 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 348, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 344 ACTIONS => { 'SET' => 1, 'PERL' => 40, 'NOT' => 38, 'IDENT' => 2, 'CLEAR' => 41, 'UNLESS' => 3, 'IF' => 44, "\$" => 43, 'STOP' => 6, 'CALL' => 45, 'THROW' => 8, 'GET' => 47, "[" => 9, 'TRY' => 10, 'LAST' => 49, 'DEBUG' => 51, 'RAWPERL' => 13, 'META' => 15, 'INCLUDE' => 17, "(" => 53, 'SWITCH' => 54, 'MACRO' => 18, 'WRAPPER' => 55, ";" => -18, 'FOR' => 21, 'LITERAL' => 57, 'NEXT' => 22, "\"" => 60, 'TEXT' => 24, 'PROCESS' => 61, 'RETURN' => 64, 'FILTER' => 25, 'INSERT' => 65, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 67, 'BLOCK' => 28, 'DEFAULT' => 69, "{" => 30, 'USE' => 32, 'VIEW' => 36, "\${" => 37 }, DEFAULT => -3, GOTOS => { 'item' => 39, 'node' => 23, 'rawperl' => 59, 'term' => 58, 'loop' => 4, 'use' => 63, 'expr' => 62, 'capture' => 42, 'statement' => 5, 'view' => 7, 'wrapper' => 46, 'atomexpr' => 48, 'chunk' => 11, 'defblock' => 66, 'atomdir' => 12, 'anonblock' => 50, 'sterm' => 68, 'defblockname' => 14, 'filter' => 29, 'ident' => 16, 'perl' => 31, 'setlist' => 70, 'chunks' => 33, 'try' => 35, 'switch' => 34, 'assign' => 19, 'block' => 349, 'directive' => 71, 'macro' => 20, 'condition' => 73, 'lterm' => 56 } }, {#State 345 ACTIONS => { 'ELSIF' => 290, 'ELSE' => 288 }, DEFAULT => -50, GOTOS => { 'else' => 350 } }, {#State 346 DEFAULT => -68 }, {#State 347 DEFAULT => -69 }, {#State 348 ACTIONS => { 'CASE' => 313 }, DEFAULT => -55, GOTOS => { 'case' => 351 } }, {#State 349 DEFAULT => -53 }, {#State 350 DEFAULT => -48 }, {#State 351 DEFAULT => -52 } ]; $RULES = [ [#Rule 0 '$start', 2, undef ], [#Rule 1 'template', 1, sub { $factory->template($_[1]) } ], [#Rule 2 'block', 1, sub { $factory->block($_[1]) } ], [#Rule 3 'block', 0, sub { $factory->block() } ], [#Rule 4 'chunks', 2, sub { push(@{$_[1]}, $_[2]) if defined $_[2]; $_[1] } ], [#Rule 5 'chunks', 1, sub { defined $_[1] ? [ $_[1] ] : [ ] } ], [#Rule 6 'chunk', 1, sub { $factory->textblock($_[1]) } ], [#Rule 7 'chunk', 2, sub { return '' unless $_[1]; $_[0]->location() . $_[1]; } ], [#Rule 8 'statement', 1, undef ], [#Rule 9 'statement', 1, undef ], [#Rule 10 'statement', 1, undef ], [#Rule 11 'statement', 1, undef ], [#Rule 12 'statement', 1, undef ], [#Rule 13 'statement', 1, undef ], [#Rule 14 'statement', 1, undef ], [#Rule 15 'statement', 1, undef ], [#Rule 16 'statement', 1, sub { $factory->get($_[1]) } ], [#Rule 17 'statement', 2, sub { $_[0]->add_metadata($_[2]); } ], [#Rule 18 'statement', 0, undef ], [#Rule 19 'directive', 1, sub { $factory->set($_[1]) } ], [#Rule 20 'directive', 1, undef ], [#Rule 21 'directive', 1, undef ], [#Rule 22 'directive', 1, undef ], [#Rule 23 'directive', 1, undef ], [#Rule 24 'directive', 1, undef ], [#Rule 25 'directive', 1, undef ], [#Rule 26 'atomexpr', 1, sub { $factory->get($_[1]) } ], [#Rule 27 'atomexpr', 1, undef ], [#Rule 28 'atomdir', 2, sub { $factory->get($_[2]) } ], [#Rule 29 'atomdir', 2, sub { $factory->call($_[2]) } ], [#Rule 30 'atomdir', 2, sub { $factory->set($_[2]) } ], [#Rule 31 'atomdir', 2, sub { $factory->default($_[2]) } ], [#Rule 32 'atomdir', 2, sub { $factory->insert($_[2]) } ], [#Rule 33 'atomdir', 2, sub { $factory->include($_[2]) } ], [#Rule 34 'atomdir', 2, sub { $factory->process($_[2]) } ], [#Rule 35 'atomdir', 2, sub { $factory->throw($_[2]) } ], [#Rule 36 'atomdir', 1, sub { $factory->return() } ], [#Rule 37 'atomdir', 1, sub { $factory->stop() } ], [#Rule 38 'atomdir', 1, sub { "\$output = '';"; } ], [#Rule 39 'atomdir', 1, sub { $_[0]->{ INFOR } || $_[0]->{ INWHILE } ? 'last LOOP;' : 'last;' } ], [#Rule 40 'atomdir', 1, sub { $_[0]->{ INFOR } ? $factory->next() : ($_[0]->{ INWHILE } ? 'next LOOP;' : 'next;') } ], [#Rule 41 'atomdir', 2, sub { if ($_[2]->[0]->[0] =~ /^'(on|off)'$/) { $_[0]->{ DEBUG_DIRS } = ($1 eq 'on'); $factory->debug($_[2]); } else { $_[0]->{ DEBUG_DIRS } ? $factory->debug($_[2]) : ''; } } ], [#Rule 42 'atomdir', 1, undef ], [#Rule 43 'atomdir', 1, undef ], [#Rule 44 'condition', 6, sub { $factory->if(@_[2, 4, 5]) } ], [#Rule 45 'condition', 3, sub { $factory->if(@_[3, 1]) } ], [#Rule 46 'condition', 6, sub { $factory->if("!($_[2])", @_[4, 5]) } ], [#Rule 47 'condition', 3, sub { $factory->if("!($_[3])", $_[1]) } ], [#Rule 48 'else', 5, sub { unshift(@{$_[5]}, [ @_[2, 4] ]); $_[5]; } ], [#Rule 49 'else', 3, sub { [ $_[3] ] } ], [#Rule 50 'else', 0, sub { [ undef ] } ], [#Rule 51 'switch', 6, sub { $factory->switch(@_[2, 5]) } ], [#Rule 52 'case', 5, sub { unshift(@{$_[5]}, [ @_[2, 4] ]); $_[5]; } ], [#Rule 53 'case', 4, sub { [ $_[4] ] } ], [#Rule 54 'case', 3, sub { [ $_[3] ] } ], [#Rule 55 'case', 0, sub { [ undef ] } ], [#Rule 56 '@1-3', 0, sub { $_[0]->{ INFOR }++ } ], [#Rule 57 'loop', 6, sub { $_[0]->{ INFOR }--; $factory->foreach(@{$_[2]}, $_[5]) } ], [#Rule 58 'loop', 3, sub { $factory->foreach(@{$_[3]}, $_[1]) } ], [#Rule 59 '@2-3', 0, sub { $_[0]->{ INWHILE }++ } ], [#Rule 60 'loop', 6, sub { $_[0]->{ INWHILE }--; $factory->while(@_[2, 5]) } ], [#Rule 61 'loop', 3, sub { $factory->while(@_[3, 1]) } ], [#Rule 62 'loopvar', 4, sub { [ @_[1, 3, 4] ] } ], [#Rule 63 'loopvar', 4, sub { [ @_[1, 3, 4] ] } ], [#Rule 64 'loopvar', 2, sub { [ 0, @_[1, 2] ] } ], [#Rule 65 'wrapper', 5, sub { $factory->wrapper(@_[2, 4]) } ], [#Rule 66 'wrapper', 3, sub { $factory->wrapper(@_[3, 1]) } ], [#Rule 67 'try', 5, sub { $factory->try(@_[3, 4]) } ], [#Rule 68 'final', 5, sub { unshift(@{$_[5]}, [ @_[2,4] ]); $_[5]; } ], [#Rule 69 'final', 5, sub { unshift(@{$_[5]}, [ undef, $_[4] ]); $_[5]; } ], [#Rule 70 'final', 4, sub { unshift(@{$_[4]}, [ undef, $_[3] ]); $_[4]; } ], [#Rule 71 'final', 3, sub { [ $_[3] ] } ], [#Rule 72 'final', 0, sub { [ 0 ] } ], [#Rule 73 'use', 2, sub { $factory->use($_[2]) } ], [#Rule 74 '@3-3', 0, sub { $_[0]->push_defblock(); } ], [#Rule 75 'view', 6, sub { $factory->view(@_[2,5], $_[0]->pop_defblock) } ], [#Rule 76 '@4-2', 0, sub { ${$_[0]->{ INPERL }}++; } ], [#Rule 77 'perl', 5, sub { ${$_[0]->{ INPERL }}--; $_[0]->{ EVAL_PERL } ? $factory->perl($_[4]) : $factory->no_perl(); } ], [#Rule 78 '@5-1', 0, sub { ${$_[0]->{ INPERL }}++; $rawstart = ${$_[0]->{'LINE'}}; } ], [#Rule 79 'rawperl', 5, sub { ${$_[0]->{ INPERL }}--; $_[0]->{ EVAL_PERL } ? $factory->rawperl($_[4], $rawstart) : $factory->no_perl(); } ], [#Rule 80 'filter', 5, sub { $factory->filter(@_[2,4]) } ], [#Rule 81 'filter', 3, sub { $factory->filter(@_[3,1]) } ], [#Rule 82 'defblock', 5, sub { my $name = join('/', @{ $_[0]->{ DEFBLOCKS } }); pop(@{ $_[0]->{ DEFBLOCKS } }); $_[0]->define_block($name, $_[4]); undef } ], [#Rule 83 'defblockname', 2, sub { push(@{ $_[0]->{ DEFBLOCKS } }, $_[2]); $_[2]; } ], [#Rule 84 'blockname', 1, undef ], [#Rule 85 'blockname', 1, sub { $_[1] =~ s/^'(.*)'$/$1/; $_[1] } ], [#Rule 86 'blockargs', 1, undef ], [#Rule 87 'blockargs', 0, undef ], [#Rule 88 'anonblock', 5, sub { local $" = ', '; print STDERR "experimental block args: [@{ $_[2] }]\n" if $_[2]; $factory->anon_block($_[4]) } ], [#Rule 89 'capture', 3, sub { $factory->capture(@_[1, 3]) } ], [#Rule 90 'macro', 6, sub { $factory->macro(@_[2, 6, 4]) } ], [#Rule 91 'macro', 3, sub { $factory->macro(@_[2, 3]) } ], [#Rule 92 'mdir', 1, undef ], [#Rule 93 'mdir', 4, sub { $_[3] } ], [#Rule 94 'margs', 2, sub { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 95 'margs', 2, sub { $_[1] } ], [#Rule 96 'margs', 1, sub { [ $_[1] ] } ], [#Rule 97 'metadata', 2, sub { push(@{$_[1]}, @{$_[2]}); $_[1] } ], [#Rule 98 'metadata', 2, undef ], [#Rule 99 'metadata', 1, undef ], [#Rule 100 'meta', 3, sub { for ($_[3]) { s/^'//; s/'$//; s/\\'/'/g }; [ @_[1,3] ] } ], [#Rule 101 'meta', 5, sub { [ @_[1,4] ] } ], [#Rule 102 'meta', 3, sub { [ @_[1,3] ] } ], [#Rule 103 'term', 1, undef ], [#Rule 104 'term', 1, undef ], [#Rule 105 'lterm', 3, sub { "[ $_[2] ]" } ], [#Rule 106 'lterm', 3, sub { "[ $_[2] ]" } ], [#Rule 107 'lterm', 2, sub { "[ ]" } ], [#Rule 108 'lterm', 3, sub { "{ $_[2] }" } ], [#Rule 109 'sterm', 1, sub { $factory->ident($_[1]) } ], [#Rule 110 'sterm', 2, sub { $factory->identref($_[2]) } ], [#Rule 111 'sterm', 3, sub { $factory->quoted($_[2]) } ], [#Rule 112 'sterm', 1, undef ], [#Rule 113 'sterm', 1, undef ], [#Rule 114 'list', 2, sub { "$_[1], $_[2]" } ], [#Rule 115 'list', 2, undef ], [#Rule 116 'list', 1, undef ], [#Rule 117 'range', 3, sub { $_[1] . '..' . $_[3] } ], [#Rule 118 'hash', 1, undef ], [#Rule 119 'hash', 0, sub { "" } ], [#Rule 120 'params', 2, sub { "$_[1], $_[2]" } ], [#Rule 121 'params', 2, undef ], [#Rule 122 'params', 1, undef ], [#Rule 123 'param', 3, sub { "$_[1] => $_[3]" } ], [#Rule 124 'param', 3, sub { "$_[1] => $_[3]" } ], [#Rule 125 'ident', 3, sub { push(@{$_[1]}, @{$_[3]}); $_[1] } ], [#Rule 126 'ident', 3, sub { push(@{$_[1]}, map {($_, 0)} split(/\./, $_[3])); $_[1]; } ], [#Rule 127 'ident', 1, undef ], [#Rule 128 'node', 1, sub { [ $_[1], 0 ] } ], [#Rule 129 'node', 4, sub { [ $_[1], $factory->args($_[3]) ] } ], [#Rule 130 'item', 1, sub { "'$_[1]'" } ], [#Rule 131 'item', 3, sub { $_[2] } ], [#Rule 132 'item', 2, sub { $_[0]->{ V1DOLLAR } ? "'$_[2]'" : $factory->ident(["'$_[2]'", 0]) } ], [#Rule 133 'expr', 3, sub { "$_[1] $_[2] $_[3]" } ], [#Rule 134 'expr', 3, sub { "$_[1] $_[2] $_[3]" } ], [#Rule 135 'expr', 3, sub { "$_[1] $_[2] $_[3]" } ], [#Rule 136 'expr', 3, sub { "int($_[1] / $_[3])" } ], [#Rule 137 'expr', 3, sub { "$_[1] % $_[3]" } ], [#Rule 138 'expr', 3, sub { "$_[1] $CMPOP{ $_[2] } $_[3]" } ], [#Rule 139 'expr', 3, sub { "$_[1] . $_[3]" } ], [#Rule 140 'expr', 3, sub { "$_[1] && $_[3]" } ], [#Rule 141 'expr', 3, sub { "$_[1] || $_[3]" } ], [#Rule 142 'expr', 2, sub { "! $_[2]" } ], [#Rule 143 'expr', 5, sub { "$_[1] ? $_[3] : $_[5]" } ], [#Rule 144 'expr', 3, sub { $factory->assign(@{$_[2]}) } ], [#Rule 145 'expr', 3, sub { "($_[2])" } ], [#Rule 146 'expr', 1, undef ], [#Rule 147 'setlist', 2, sub { push(@{$_[1]}, @{$_[2]}); $_[1] } ], [#Rule 148 'setlist', 2, undef ], [#Rule 149 'setlist', 1, undef ], [#Rule 150 'assign', 3, sub { [ $_[1], $_[3] ] } ], [#Rule 151 'assign', 3, sub { [ @_[1,3] ] } ], [#Rule 152 'args', 2, sub { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 153 'args', 2, sub { push(@{$_[1]->[0]}, $_[2]); $_[1] } ], [#Rule 154 'args', 4, sub { push(@{$_[1]->[0]}, "'', " . $factory->assign(@_[2,4])); $_[1] } ], [#Rule 155 'args', 2, sub { $_[1] } ], [#Rule 156 'args', 0, sub { [ [ ] ] } ], [#Rule 157 'lnameargs', 3, sub { push(@{$_[3]}, $_[1]); $_[3] } ], [#Rule 158 'lnameargs', 1, undef ], [#Rule 159 'lvalue', 1, undef ], [#Rule 160 'lvalue', 3, sub { $factory->quoted($_[2]) } ], [#Rule 161 'lvalue', 1, undef ], [#Rule 162 'nameargs', 3, sub { [ [$factory->ident($_[2])], $_[3] ] } ], [#Rule 163 'nameargs', 2, sub { [ @_[1,2] ] } ], [#Rule 164 'nameargs', 4, sub { [ @_[1,3] ] } ], [#Rule 165 'names', 3, sub { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 166 'names', 1, sub { [ $_[1] ] } ], [#Rule 167 'name', 3, sub { $factory->quoted($_[2]) } ], [#Rule 168 'name', 1, sub { "'$_[1]'" } ], [#Rule 169 'name', 1, undef ], [#Rule 170 'filename', 3, sub { "$_[1].$_[3]" } ], [#Rule 171 'filename', 1, undef ], [#Rule 172 'filepart', 1, undef ], [#Rule 173 'filepart', 1, undef ], [#Rule 174 'filepart', 1, undef ], [#Rule 175 'quoted', 2, sub { push(@{$_[1]}, $_[2]) if defined $_[2]; $_[1] } ], [#Rule 176 'quoted', 0, sub { [ ] } ], [#Rule 177 'quotable', 1, sub { $factory->ident($_[1]) } ], [#Rule 178 'quotable', 1, sub { $factory->text($_[1]) } ], [#Rule 179 'quotable', 1, sub { undef } ] ]; 1; } # # Inline include of Template/Directive.pm # BEGIN { $INC{'Template/Directive.pm'} = 'dummy/Template/Directive.pm'; } BEGIN { #line 0 "Template/Directive.pm" package Template::Directive; use strict; use warnings; use base 'Template::Base'; use Template::Constants; use Template::Exception; our $VERSION = 2.20; our $DEBUG = 0 unless defined $DEBUG; our $WHILE_MAX = 1000 unless defined $WHILE_MAX; our $PRETTY = 0 unless defined $PRETTY; our $OUTPUT = '$output .= '; sub _init { my ($self, $config) = @_; $self->{ NAMESPACE } = $config->{ NAMESPACE }; return $self; } sub pad { my ($text, $pad) = @_; $pad = ' ' x ($pad * 4); $text =~ s/^(?!#line)/$pad/gm; $text; } sub template { my ($class, $block) = @_; $block = pad($block, 2) if $PRETTY; return "sub { return '' }" unless $block =~ /\S/; return <stash; my \$output = ''; my \$_tt_error; eval { BLOCK: { $block } }; if (\$@) { \$_tt_error = \$context->catch(\$@, \\\$output); die \$_tt_error unless \$_tt_error->type eq 'return'; } return \$output; } EOF } sub anon_block { my ($class, $block) = @_; $block = pad($block, 2) if $PRETTY; return <catch(\$@, \\\$output); die \$_tt_error unless \$_tt_error->type eq 'return'; } \$output; }; EOF } sub block { my ($class, $block) = @_; return join("\n", @{ $block || [] }); } sub textblock { my ($class, $text) = @_; return "$OUTPUT " . &text($class, $text) . ';'; } sub text { my ($class, $text) = @_; for ($text) { s/(["\$\@\\])/\\$1/g; s/\n/\\n/g; } return '"' . $text . '"'; } sub quoted { my ($class, $items) = @_; return '' unless @$items; return ("('' . " . $items->[0] . ')') if scalar @$items == 1; return '(' . join(' . ', @$items) . ')'; } sub ident { my ($class, $ident) = @_; return "''" unless @$ident; my $ns; # does the first element of the identifier have a NAMESPACE # handler defined? if (ref $class && @$ident > 2 && ($ns = $class->{ NAMESPACE })) { my $key = $ident->[0]; $key =~ s/^'(.+)'$/$1/s; if ($ns = $ns->{ $key }) { return $ns->ident($ident); } } if (scalar @$ident <= 2 && ! $ident->[1]) { $ident = $ident->[0]; } else { $ident = '[' . join(', ', @$ident) . ']'; } return "\$stash->get($ident)"; } sub identref { my ($class, $ident) = @_; return "''" unless @$ident; if (scalar @$ident <= 2 && ! $ident->[1]) { $ident = $ident->[0]; } else { $ident = '[' . join(', ', @$ident) . ']'; } return "\$stash->getref($ident)"; } sub assign { my ($class, $var, $val, $default) = @_; if (ref $var) { if (scalar @$var == 2 && ! $var->[1]) { $var = $var->[0]; } else { $var = '[' . join(', ', @$var) . ']'; } } $val .= ', 1' if $default; return "\$stash->set($var, $val)"; } sub args { my ($class, $args) = @_; my $hash = shift @$args; push(@$args, '{ ' . join(', ', @$hash) . ' }') if @$hash; return '0' unless @$args; return '[ ' . join(', ', @$args) . ' ]'; } sub filenames { my ($class, $names) = @_; if (@$names > 1) { $names = '[ ' . join(', ', @$names) . ' ]'; } else { $names = shift @$names; } return $names; } sub get { my ($class, $expr) = @_; return "$OUTPUT $expr;"; } sub call { my ($class, $expr) = @_; $expr .= ';'; return $expr; } sub set { my ($class, $setlist) = @_; my $output; while (my ($var, $val) = splice(@$setlist, 0, 2)) { $output .= &assign($class, $var, $val) . ";\n"; } chomp $output; return $output; } sub default { my ($class, $setlist) = @_; my $output; while (my ($var, $val) = splice(@$setlist, 0, 2)) { $output .= &assign($class, $var, $val, 1) . ";\n"; } chomp $output; return $output; } sub insert { my ($class, $nameargs) = @_; my ($file, $args) = @$nameargs; $file = $class->filenames($file); return "$OUTPUT \$context->insert($file);"; } sub include { my ($class, $nameargs) = @_; my ($file, $args) = @$nameargs; my $hash = shift @$args; $file = $class->filenames($file); $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return "$OUTPUT \$context->include($file);"; } sub process { my ($class, $nameargs) = @_; my ($file, $args) = @$nameargs; my $hash = shift @$args; $file = $class->filenames($file); $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return "$OUTPUT \$context->process($file);"; } sub if { my ($class, $expr, $block, $else) = @_; my @else = $else ? @$else : (); $else = pop @else; $block = pad($block, 1) if $PRETTY; my $output = "if ($expr) {\n$block\n}\n"; foreach my $elsif (@else) { ($expr, $block) = @$elsif; $block = pad($block, 1) if $PRETTY; $output .= "elsif ($expr) {\n$block\n}\n"; } if (defined $else) { $else = pad($else, 1) if $PRETTY; $output .= "else {\n$else\n}\n"; } return $output; } sub foreach { my ($class, $target, $list, $args, $block) = @_; $args = shift @$args; $args = @$args ? ', { ' . join(', ', @$args) . ' }' : ''; my ($loop_save, $loop_set, $loop_restore, $setiter); if ($target) { $loop_save = 'eval { $_tt_oldloop = ' . &ident($class, ["'loop'"]) . ' }'; $loop_set = "\$stash->{'$target'} = \$_tt_value"; $loop_restore = "\$stash->set('loop', \$_tt_oldloop)"; } else { $loop_save = '$stash = $context->localise()'; $loop_set = "\$stash->get(['import', [\$_tt_value]]) " . "if ref \$_tt_value eq 'HASH'"; $loop_restore = '$stash = $context->delocalise()'; } $block = pad($block, 3) if $PRETTY; return <iterator(\$_tt_list) || die \$Template::Config::ERROR, "\\n"; } (\$_tt_value, \$_tt_error) = \$_tt_list->get_first(); $loop_save; \$stash->set('loop', \$_tt_list); eval { LOOP: while (! \$_tt_error) { $loop_set; $block; (\$_tt_value, \$_tt_error) = \$_tt_list->get_next(); } }; $loop_restore; die \$@ if \$@; \$_tt_error = 0 if \$_tt_error && \$_tt_error eq Template::Constants::STATUS_DONE; die \$_tt_error if \$_tt_error; }; EOF } sub next { return <get_next(); next LOOP; EOF } sub wrapper { my ($class, $nameargs, $block) = @_; my ($file, $args) = @$nameargs; my $hash = shift @$args; local $" = ', '; return $class->multi_wrapper($file, $hash, $block) if @$file > 1; $file = shift @$file; $block = pad($block, 1) if $PRETTY; push(@$hash, "'content'", '$output'); $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return <include($file); }; EOF } sub multi_wrapper { my ($class, $file, $hash, $block) = @_; $block = pad($block, 1) if $PRETTY; push(@$hash, "'content'", '$output'); $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; $file = join(', ', reverse @$file); return <include(\$_$hash); } \$output; }; EOF } sub while { my ($class, $expr, $block) = @_; $block = pad($block, 2) if $PRETTY; return < $WHILE_MAX iterations)\\n" unless \$_tt_failsafe; }; EOF } sub switch { my ($class, $expr, $case) = @_; my @case = @$case; my ($match, $block, $default); my $caseblock = ''; $default = pop @case; foreach $case (@case) { $match = $case->[0]; $block = $case->[1]; $block = pad($block, 1) if $PRETTY; $caseblock .= <[0] || do { $default ||= $catch->[1]; next; }; $mblock = $catch->[1]; $mblock = pad($mblock, 1) if $PRETTY; push(@$handlers, "'$match'"); $catchblock .= $n++ ? "elsif (\$_tt_handler eq '$match') {\n$mblock\n}\n" : "if (\$_tt_handler eq '$match') {\n$mblock\n}\n"; } $catchblock .= "\$_tt_error = 0;"; $catchblock = pad($catchblock, 3) if $PRETTY; if ($default) { $default = pad($default, 1) if $PRETTY; $default = "else {\n # DEFAULT\n$default\n \$_tt_error = '';\n}"; } else { $default = '# NO DEFAULT'; } $default = pad($default, 2) if $PRETTY; $handlers = join(', ', @$handlers); return <catch(\$@, \\\$output); die \$_tt_error if \$_tt_error->type =~ /^return|stop\$/; \$stash->set('error', \$_tt_error); \$stash->set('e', \$_tt_error); if (defined (\$_tt_handler = \$_tt_error->select_handler($handlers))) { $catchblock } $default } $final }; EOF } sub throw { my ($class, $nameargs) = @_; my ($type, $args) = @$nameargs; my $hash = shift(@$args); my $info = shift(@$args); $type = shift @$type; # uses same parser production as INCLUDE # etc., which allow multiple names # e.g. INCLUDE foo+bar+baz if (! $info) { $args = "$type, undef"; } elsif (@$hash || @$args) { local $" = ', '; my $i = 0; $args = "$type, { args => [ " . join(', ', $info, @$args) . ' ], ' . join(', ', (map { "'" . $i++ . "' => $_" } ($info, @$args)), @$hash) . ' }'; } else { $args = "$type, $info"; } return "\$context->throw($args, \\\$output);"; } sub clear { return "\$output = '';"; } sub break { return 'last LOOP;'; } sub return { return "\$context->throw('return', '', \\\$output);"; } sub stop { return "\$context->throw('stop', '', \\\$output);"; } sub use { my ($class, $lnameargs) = @_; my ($file, $args, $alias) = @$lnameargs; $file = shift @$file; # same production rule as INCLUDE $alias ||= $file; $args = &args($class, $args); $file .= ", $args" if $args; return "# USE\n" . "\$stash->set($alias,\n" . " \$context->plugin($file));"; } sub view { my ($class, $nameargs, $block, $defblocks) = @_; my ($name, $args) = @$nameargs; my $hash = shift @$args; $name = shift @$name; # same production rule as INCLUDE $block = pad($block, 1) if $PRETTY; if (%$defblocks) { $defblocks = join(",\n", map { "'$_' => $defblocks->{ $_ }" } keys %$defblocks); $defblocks = pad($defblocks, 1) if $PRETTY; $defblocks = "{\n$defblocks\n}"; push(@$hash, "'blocks'", $defblocks); } $hash = @$hash ? '{ ' . join(', ', @$hash) . ' }' : ''; return <get('view'); my \$_tt_view = \$context->view($hash); \$stash->set($name, \$_tt_view); \$stash->set('view', \$_tt_view); $block \$stash->set('view', \$_tt_oldv); \$_tt_view->seal(); }; EOF } sub perl { my ($class, $block) = @_; $block = pad($block, 1) if $PRETTY; return <throw('perl', 'EVAL_PERL not set') unless \$context->eval_perl(); $OUTPUT do { my \$output = "package Template::Perl;\\n"; $block local(\$Template::Perl::context) = \$context; local(\$Template::Perl::stash) = \$stash; my \$_tt_result = ''; tie *Template::Perl::PERLOUT, 'Template::TieString', \\\$_tt_result; my \$_tt_save_stdout = select *Template::Perl::PERLOUT; eval \$output; select \$_tt_save_stdout; \$context->throw(\$@) if \$@; \$_tt_result; }; EOF } sub no_perl { my $class = shift; return "\$context->throw('perl', 'EVAL_PERL not set');"; } sub rawperl { my ($class, $block, $line) = @_; for ($block) { s/^\n+//; s/\n+$//; } $block = pad($block, 1) if $PRETTY; $line = $line ? " (starting line $line)" : ''; return <filter($name) || \$context->throw(\$context->error); $block &\$_tt_filter(\$output); }; EOF } sub capture { my ($class, $name, $block) = @_; if (ref $name) { if (scalar @$name == 2 && ! $name->[1]) { $name = $name->[0]; } else { $name = '[' . join(', ', @$name) . ']'; } } $block = pad($block, 1) if $PRETTY; return <set($name, do { my \$output = ''; $block \$output; }); EOF } sub macro { my ($class, $ident, $block, $args) = @_; $block = pad($block, 2) if $PRETTY; if ($args) { my $nargs = scalar @$args; $args = join(', ', map { "'$_'" } @$args); $args = $nargs > 1 ? "\@_tt_args{ $args } = splice(\@_, 0, $nargs)" : "\$_tt_args{ $args } = shift"; return <set('$ident', sub { my \$output = ''; my (%_tt_args, \$_tt_params); $args; \$_tt_params = shift; \$_tt_params = { } unless ref(\$_tt_params) eq 'HASH'; \$_tt_params = { \%_tt_args, %\$_tt_params }; my \$stash = \$context->localise(\$_tt_params); eval { $block }; \$stash = \$context->delocalise(); die \$@ if \$@; return \$output; }); EOF } else { return <set('$ident', sub { my \$_tt_params = \$_[0] if ref(\$_[0]) eq 'HASH'; my \$output = ''; my \$stash = \$context->localise(\$_tt_params); eval { $block }; \$stash = \$context->delocalise(); die \$@ if \$@; return \$output; }); EOF } } sub debug { my ($class, $nameargs) = @_; my ($file, $args) = @$nameargs; my $hash = shift @$args; $args = join(', ', @$file, @$args); $args .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return "$OUTPUT \$context->debugging($args); ## DEBUG ##"; } 1; } # # Inline include of Template/Parser.pm # BEGIN { $INC{'Template/Parser.pm'} = 'dummy/Template/Parser.pm'; } BEGIN { #line 0 "Template/Parser.pm" package Template::Parser; use strict; use warnings; use base 'Template::Base'; use Template::Constants qw( :status :chomp ); use Template::Directive; use Template::Grammar; use constant CONTINUE => 0; use constant ACCEPT => 1; use constant ERROR => 2; use constant ABORT => 3; our $VERSION = 2.89; our $DEBUG = 0 unless defined $DEBUG; our $ERROR = ''; our $TAG_STYLE = { 'default' => [ '\[%', '%\]' ], 'template1' => [ '[\[%]%', '%[\]%]' ], 'metatext' => [ '%%', '%%' ], 'html' => [ '' ], 'mason' => [ '<%', '>' ], 'asp' => [ '<%', '%>' ], 'php' => [ '<\?', '\?>' ], 'star' => [ '\[\*', '\*\]' ], }; $TAG_STYLE->{ template } = $TAG_STYLE->{ tt2 } = $TAG_STYLE->{ default }; our $DEFAULT_STYLE = { START_TAG => $TAG_STYLE->{ default }->[0], END_TAG => $TAG_STYLE->{ default }->[1], ANYCASE => 0, INTERPOLATE => 0, PRE_CHOMP => 0, POST_CHOMP => 0, V1DOLLAR => 0, EVAL_PERL => 0, }; our $QUOTED_ESCAPES = { n => "\n", r => "\r", t => "\t", }; our $CHOMP_FLAGS = qr/[-=~+]/; sub new { my $class = shift; my $config = $_[0] && UNIVERSAL::isa($_[0], 'HASH') ? shift(@_) : { @_ }; my ($tagstyle, $debug, $start, $end, $defaults, $grammar, $hash, $key, $udef); my $self = bless { START_TAG => undef, END_TAG => undef, TAG_STYLE => 'default', ANYCASE => 0, INTERPOLATE => 0, PRE_CHOMP => 0, POST_CHOMP => 0, V1DOLLAR => 0, EVAL_PERL => 0, FILE_INFO => 1, GRAMMAR => undef, _ERROR => '', FACTORY => $config->{ FACTORY } || 'Template::Directive', }, $class; # update self with any relevant keys in config foreach $key (keys %$self) { $self->{ $key } = $config->{ $key } if defined $config->{ $key }; } $self->{ FILEINFO } = [ ]; # DEBUG config item can be a bitmask if (defined ($debug = $config->{ DEBUG })) { $self->{ DEBUG } = $debug & ( Template::Constants::DEBUG_PARSER | Template::Constants::DEBUG_FLAGS ); $self->{ DEBUG_DIRS } = $debug & Template::Constants::DEBUG_DIRS; } # package variable can be set to 1 to support previous behaviour elsif ($DEBUG == 1) { $self->{ DEBUG } = Template::Constants::DEBUG_PARSER; $self->{ DEBUG_DIRS } = 0; } # otherwise let $DEBUG be a bitmask else { $self->{ DEBUG } = $DEBUG & ( Template::Constants::DEBUG_PARSER | Template::Constants::DEBUG_FLAGS ); $self->{ DEBUG_DIRS } = $DEBUG & Template::Constants::DEBUG_DIRS; } $grammar = $self->{ GRAMMAR } ||= do { require Template::Grammar; Template::Grammar->new(); }; # build a FACTORY object to include any NAMESPACE definitions, # but only if FACTORY isn't already an object if ($config->{ NAMESPACE } && ! ref $self->{ FACTORY }) { my $fclass = $self->{ FACTORY }; $self->{ FACTORY } = $fclass->new( NAMESPACE => $config->{ NAMESPACE } ) || return $class->error($fclass->error()); } # load grammar rules, states and lex table @$self{ qw( LEXTABLE STATES RULES ) } = @$grammar{ qw( LEXTABLE STATES RULES ) }; $self->new_style($config) || return $class->error($self->error()); return $self; } sub new_style { my ($self, $config) = @_; my $styles = $self->{ STYLE } ||= [ ]; my ($tagstyle, $tags, $start, $end, $key); # clone new style from previous or default style my $style = { %{ $styles->[-1] || $DEFAULT_STYLE } }; # expand START_TAG and END_TAG from specified TAG_STYLE if ($tagstyle = $config->{ TAG_STYLE }) { return $self->error("Invalid tag style: $tagstyle") unless defined ($tags = $TAG_STYLE->{ $tagstyle }); ($start, $end) = @$tags; $config->{ START_TAG } ||= $start; $config->{ END_TAG } ||= $end; } foreach $key (keys %$DEFAULT_STYLE) { $style->{ $key } = $config->{ $key } if defined $config->{ $key }; } push(@$styles, $style); return $style; } sub old_style { my $self = shift; my $styles = $self->{ STYLE }; return $self->error('only 1 parser style remaining') unless (@$styles > 1); pop @$styles; return $styles->[-1]; } sub parse { my ($self, $text, $info) = @_; my ($tokens, $block); $info->{ DEBUG } = $self->{ DEBUG_DIRS } unless defined $info->{ DEBUG }; # store for blocks defined in the template (see define_block()) my $defblock = $self->{ DEFBLOCK } = { }; my $metadata = $self->{ METADATA } = [ ]; $self->{ DEFBLOCKS } = [ ]; $self->{ _ERROR } = ''; # split file into TEXT/DIRECTIVE chunks $tokens = $self->split_text($text) || return undef; ## RETURN ## push(@{ $self->{ FILEINFO } }, $info); # parse chunks $block = $self->_parse($tokens, $info); pop(@{ $self->{ FILEINFO } }); return undef unless $block; ## RETURN ## $self->debug("compiled main template document block:\n$block") if $self->{ DEBUG } & Template::Constants::DEBUG_PARSER; return { BLOCK => $block, DEFBLOCKS => $defblock, METADATA => { @$metadata }, }; } sub split_text { my ($self, $text) = @_; my ($pre, $dir, $prelines, $dirlines, $postlines, $chomp, $tags, @tags); my $style = $self->{ STYLE }->[-1]; my ($start, $end, $prechomp, $postchomp, $interp ) = @$style{ qw( START_TAG END_TAG PRE_CHOMP POST_CHOMP INTERPOLATE ) }; my $tags_dir = $self->{ANYCASE} ? qri : qr; my @tokens = (); my $line = 1; return \@tokens ## RETURN ## unless defined $text && length $text; # extract all directives from the text while ($text =~ s/ ^(.*?) # $1 - start of line up to directive (?: $start # start of tag (.*?) # $2 - tag contents $end # end of tag ) //sx) { ($pre, $dir) = ($1, $2); $pre = '' unless defined $pre; $dir = '' unless defined $dir; $prelines = ($pre =~ tr/\n//); # newlines in preceeding text $dirlines = ($dir =~ tr/\n//); # newlines in directive tag $postlines = 0; # newlines chomped after tag for ($dir) { if (/^\#/) { # comment out entire directive except for any end chomp flag $dir = ($dir =~ /($CHOMP_FLAGS)$/o) ? $1 : ''; } else { s/^($CHOMP_FLAGS)?\s*//so; # PRE_CHOMP: process whitespace before tag $chomp = $1 ? $1 : $prechomp; $chomp =~ tr/-=~+/1230/; if ($chomp && $pre) { # chomp off whitespace and newline preceding directive if ($chomp == CHOMP_ALL) { $pre =~ s{ (\n|^) [^\S\n]* \z }{}mx; } elsif ($chomp == CHOMP_COLLAPSE) { $pre =~ s{ (\s+) \z }{ }x; } elsif ($chomp == CHOMP_GREEDY) { $pre =~ s{ (\s+) \z }{}x; } } } # POST_CHOMP: process whitespace after tag s/\s*($CHOMP_FLAGS)?\s*$//so; $chomp = $1 ? $1 : $postchomp; $chomp =~ tr/-=~+/1230/; if ($chomp) { if ($chomp == CHOMP_ALL) { $text =~ s{ ^ ([^\S\n]* \n) }{}x && $postlines++; } elsif ($chomp == CHOMP_COLLAPSE) { $text =~ s{ ^ (\s+) }{ }x && ($postlines += $1=~y/\n//); } # any trailing whitespace elsif ($chomp == CHOMP_GREEDY) { $text =~ s{ ^ (\s+) }{}x && ($postlines += $1=~y/\n//); } } } # any text preceding the directive can now be added if (length $pre) { push(@tokens, $interp ? [ $pre, $line, 'ITEXT' ] : ('TEXT', $pre) ); } $line += $prelines; # and now the directive, along with line number information if (length $dir) { # the TAGS directive is a compile-time switch if ($dir =~ /^$tags_dir\s+(.*)/) { my @tags = split(/\s+/, $1); if (scalar @tags > 1) { ($start, $end) = map { quotemeta($_) } @tags; } elsif ($tags = $TAG_STYLE->{ $tags[0] }) { ($start, $end) = @$tags; } else { warn "invalid TAGS style: $tags[0]\n"; } } else { # DIRECTIVE is pushed as: # [ $dirtext, $line_no(s), \@tokens ] push(@tokens, [ $dir, ($dirlines ? sprintf("%d-%d", $line, $line + $dirlines) : $line), $self->tokenise_directive($dir) ]); } } # update line counter to include directive lines and any extra # newline chomped off the start of the following text $line += $dirlines + $postlines; } # anything remaining in the string is plain text push(@tokens, $interp ? [ $text, $line, 'ITEXT' ] : ( 'TEXT', $text) ) if length $text; return \@tokens; ## RETURN ## } sub interpolate_text { my ($self, $text, $line) = @_; my @tokens = (); my ($pre, $var, $dir); while ($text =~ / ( (?: \\. | [^\$] ){1,3000} ) # escaped or non-'$' character [$1] | ( \$ (?: # embedded variable [$2] (?: \{ ([^\}]*) \} ) # ${ ... } [$3] | ([\w\.]+) # $word [$4] ) ) /gx) { ($pre, $var, $dir) = ($1, $3 || $4, $2); # preceding text if (defined($pre) && length($pre)) { $line += $pre =~ tr/\n//; $pre =~ s/\\\$/\$/g; push(@tokens, 'TEXT', $pre); } # $variable reference if ($var) { $line += $dir =~ tr/\n/ /; push(@tokens, [ $dir, $line, $self->tokenise_directive($var) ]); } # other '$' reference - treated as text elsif ($dir) { $line += $dir =~ tr/\n//; push(@tokens, 'TEXT', $dir); } } return \@tokens; } sub tokenise_directive { my ($self, $text, $line) = @_; my ($token, $uctoken, $type, $lookup); my $lextable = $self->{ LEXTABLE }; my $style = $self->{ STYLE }->[-1]; my ($anycase, $start, $end) = @$style{ qw( ANYCASE START_TAG END_TAG ) }; my @tokens = ( ); while ($text =~ / # strip out any comments (\#[^\n]*) | # a quoted phrase matches in $3 (["']) # $2 - opening quote, ' or " ( # $3 - quoted text buffer (?: # repeat group (no backreference) \\\\ # an escaped backslash \\ | # ...or... \\\2 # an escaped quote \" or \' (match $1) | # ...or... . # any other character | \n )*? # non-greedy repeat ) # end of $3 \2 # match opening quote | # an unquoted number matches in $4 (-?\d+(?:\.\d+)?) # numbers | # filename matches in $5 ( \/?\w+(?:(?:\/|::?)\w*)+ | \/\w+) | # an identifier matches in $6 (\w+) # variable identifier | # an unquoted word or symbol matches in $7 ( [(){}\[\]:;,\/\\] # misc parenthesis and symbols | [+\-*] # math operations | \$\{? # dollar with option left brace | => # like '=' | [=!<>]?= | [!<>] # eqality tests | &&? | \|\|? # boolean ops | \.\.? # n..n sequence | \S+ # something unquoted ) # end of $7 /gmxo) { # ignore comments to EOL next if $1; # quoted string if (defined ($token = $3)) { # double-quoted string may include $variable references if ($2 eq '"') { if ($token =~ /[\$\\]/) { $type = 'QUOTED'; # unescape " and \ but leave \$ escaped so that # interpolate_text() doesn't incorrectly treat it # as a variable reference for ($token) { s/\\([^\$nrt])/$1/g; s/\\([nrt])/$QUOTED_ESCAPES->{ $1 }/ge; } push(@tokens, ('"') x 2, @{ $self->interpolate_text($token) }, ('"') x 2); next; } else { $type = 'LITERAL'; $token =~ s['][\\']g; $token = "'$token'"; } } else { $type = 'LITERAL'; $token = "'$token'"; } } # number elsif (defined ($token = $4)) { $type = 'NUMBER'; } elsif (defined($token = $5)) { $type = 'FILENAME'; } elsif (defined($token = $6)) { # reserved words may be in lower case unless case sensitive $uctoken = $anycase ? uc $token : $token; if (defined ($type = $lextable->{ $uctoken })) { $token = $uctoken; } else { $type = 'IDENT'; } } elsif (defined ($token = $7)) { # reserved words may be in lower case unless case sensitive $uctoken = $anycase ? uc $token : $token; unless (defined ($type = $lextable->{ $uctoken })) { $type = 'UNQUOTED'; } } push(@tokens, $type, $token); } return \@tokens; ## RETURN ## } sub define_block { my ($self, $name, $block) = @_; my $defblock = $self->{ DEFBLOCK } || return undef; $self->debug("compiled block '$name':\n$block") if $self->{ DEBUG } & Template::Constants::DEBUG_PARSER; $defblock->{ $name } = $block; return undef; } sub push_defblock { my $self = shift; my $stack = $self->{ DEFBLOCK_STACK } ||= []; push(@$stack, $self->{ DEFBLOCK } ); $self->{ DEFBLOCK } = { }; } sub pop_defblock { my $self = shift; my $defs = $self->{ DEFBLOCK }; my $stack = $self->{ DEFBLOCK_STACK } || return $defs; return $defs unless @$stack; $self->{ DEFBLOCK } = pop @$stack; return $defs; } sub add_metadata { my ($self, $setlist) = @_; my $metadata = $self->{ METADATA } || return undef; push(@$metadata, @$setlist); return undef; } sub location { my $self = shift; return "\n" unless $self->{ FILE_INFO }; my $line = ${ $self->{ LINE } }; my $info = $self->{ FILEINFO }->[-1]; my $file = $info->{ path } || $info->{ name } || '(unknown template)'; $line =~ s/\-.*$//; # might be 'n-n' return "#line $line \"$file\"\n"; } sub _parse { my ($self, $tokens, $info) = @_; my ($token, $value, $text, $line, $inperl); my ($state, $stateno, $status, $action, $lookup, $coderet, @codevars); my ($lhs, $len, $code); # rule contents my $stack = [ [ 0, undef ] ]; # DFA stack # retrieve internal rule and state tables my ($states, $rules) = @$self{ qw( STATES RULES ) }; # call the grammar set_factory method to install emitter factory $self->{ GRAMMAR }->install_factory($self->{ FACTORY }); $line = $inperl = 0; $self->{ LINE } = \$line; $self->{ FILE } = $info->{ name }; $self->{ INPERL } = \$inperl; $status = CONTINUE; my $in_string = 0; while(1) { # get state number and state $stateno = $stack->[-1]->[0]; $state = $states->[$stateno]; # see if any lookaheads exist for the current state if (exists $state->{'ACTIONS'}) { # get next token and expand any directives (i.e. token is an # array ref) onto the front of the token list while (! defined $token && @$tokens) { $token = shift(@$tokens); if (ref $token) { ($text, $line, $token) = @$token; if (ref $token) { if ($info->{ DEBUG } && ! $in_string) { # - - - - - - - - - - - - - - - - - - - - - - - - - # This is gnarly. Look away now if you're easily # frightened. We're pushing parse tokens onto the # pending list to simulate a DEBUG directive like so: # [% DEBUG msg line='20' text='INCLUDE foo' %] # - - - - - - - - - - - - - - - - - - - - - - - - - my $dtext = $text; $dtext =~ s[(['\\])][\\$1]g; unshift(@$tokens, DEBUG => 'DEBUG', IDENT => 'msg', IDENT => 'line', ASSIGN => '=', LITERAL => "'$line'", IDENT => 'text', ASSIGN => '=', LITERAL => "'$dtext'", IDENT => 'file', ASSIGN => '=', LITERAL => "'$info->{ name }'", (';') x 2, @$token, (';') x 2); } else { unshift(@$tokens, @$token, (';') x 2); } $token = undef; # force redo } elsif ($token eq 'ITEXT') { if ($inperl) { # don't perform interpolation in PERL blocks $token = 'TEXT'; $value = $text; } else { unshift(@$tokens, @{ $self->interpolate_text($text, $line) }); $token = undef; # force redo } } } else { # toggle string flag to indicate if we're crossing # a string boundary $in_string = ! $in_string if $token eq '"'; $value = shift(@$tokens); } }; # clear undefined token to avoid 'undefined variable blah blah' # warnings and let the parser logic pick it up in a minute $token = '' unless defined $token; # get the next state for the current lookahead token $action = defined ($lookup = $state->{'ACTIONS'}->{ $token }) ? $lookup : defined ($lookup = $state->{'DEFAULT'}) ? $lookup : undef; } else { # no lookahead actions $action = $state->{'DEFAULT'}; } # ERROR: no ACTION last unless defined $action; # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # shift (+ive ACTION) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ($action > 0) { push(@$stack, [ $action, $value ]); $token = $value = undef; redo; }; # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # reduce (-ive ACTION) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - ($lhs, $len, $code) = @{ $rules->[ -$action ] }; # no action imples ACCEPTance $action or $status = ACCEPT; # use dummy sub if code ref doesn't exist $code = sub { $_[1] } unless $code; @codevars = $len ? map { $_->[1] } @$stack[ -$len .. -1 ] : (); eval { $coderet = &$code( $self, @codevars ); }; if ($@) { my $err = $@; chomp $err; return $self->_parse_error($err); } # reduce stack by $len splice(@$stack, -$len, $len); # ACCEPT return $coderet ## RETURN ## if $status == ACCEPT; # ABORT return undef ## RETURN ## if $status == ABORT; # ERROR last if $status == ERROR; } continue { push(@$stack, [ $states->[ $stack->[-1][0] ]->{'GOTOS'}->{ $lhs }, $coderet ]), } # ERROR ## RETURN ## return $self->_parse_error('unexpected end of input') unless defined $value; # munge text of last directive to make it readable return $self->_parse_error("unexpected end of directive", $text) if $value eq ';'; # end of directive SEPARATOR return $self->_parse_error("unexpected token ($value)", $text); } sub _parse_error { my ($self, $msg, $text) = @_; my $line = $self->{ LINE }; $line = ref($line) ? $$line : $line; $line = 'unknown' unless $line; $msg .= "\n [% $text %]" if defined $text; return $self->error("line $line: $msg"); } sub _dump { my $self = shift; my $output = "[Template::Parser] {\n"; my $format = " %-16s => %s\n"; my $key; foreach $key (qw( START_TAG END_TAG TAG_STYLE ANYCASE INTERPOLATE PRE_CHOMP POST_CHOMP V1DOLLAR )) { my $val = $self->{ $key }; $val = '' unless defined $val; $output .= sprintf($format, $key, $val); } $output .= '}'; return $output; } 1; } # # Inline include of Jemplate/Directive.pm # BEGIN { $INC{'Jemplate/Directive.pm'} = 'dummy/Jemplate/Directive.pm'; } BEGIN { #line 0 "Jemplate/Directive.pm" package Jemplate::Directive; use strict; use warnings; our $OUTPUT = 'output +='; our $WHILE_MAX = 1000; our $INJAVASCRIPT = 0; sub template { my ($class, $block) = @_; return "function() { return ''; }" unless $block =~ /\S/; return <<"..."; function(context) { if (! context) throw('Jemplate function called without context\\n'); var stash = context.stash; var output = ''; try { $block } catch(e) { var error = context.set_error(e, output); throw(error); } return output; } ... } sub textblock { my ($class, $text) = @_; return $text if $INJAVASCRIPT; return "$OUTPUT " . $class->text($text) . ';'; } sub text { my ($class, $text) = @_; for ($text) { s/([\'\\])/\\$1/g; s/\n/\\n/g; s/\r/\\r/g; } return "'" . $text . "'"; } sub ident { my ($class, $ident) = @_; return "''" unless @$ident; my $ns; # does the first element of the identifier have a NAMESPACE # handler defined? if (ref $class && @$ident > 2 && ($ns = $class->{ NAMESPACE })) { my $key = $ident->[0]; $key =~ s/^'(.+)'$/$1/s; if ($ns = $ns->{ $key }) { return $ns->ident($ident); } } if (scalar @$ident <= 2 && ! $ident->[1]) { $ident = $ident->[0]; } else { $ident = '[' . join(', ', @$ident) . ']'; } return "stash.get($ident)"; } sub assign { my ($class, $var, $val, $default) = @_; if (ref $var) { if (scalar @$var == 2 && ! $var->[1]) { $var = $var->[0]; } else { $var = '[' . join(', ', @$var) . ']'; } } $val .= ', 1' if $default; return "stash.set($var, $val)"; } sub args { my ($class, $args) = @_; my $hash = shift @$args; push(@$args, '{ ' . join(', ', @$hash) . ' }') if @$hash; return '[]' unless @$args; return '[ ' . join(', ', @$args) . ' ]'; } sub filenames { my ($class, $names) = @_; if (@$names > 1) { $names = '[ ' . join(', ', @$names) . ' ]'; } else { $names = shift @$names; } return $names; } sub get { my ($class, $expr) = @_; return "$OUTPUT $expr;"; } sub block { my ($class, $block) = @_; return join "\n", map { s/^#(?=line \d+)/\/\//gm; $_; } @{ $block || [] }; } sub call { my ($class, $expr) = @_; $expr .= ';'; return $expr; } sub set { my ($class, $setlist) = @_; my $output; while (my ($var, $val) = splice(@$setlist, 0, 2)) { $output .= $class->assign($var, $val) . ";\n"; } chomp $output; return $output; } sub default { my ($class, $setlist) = @_; my $output; while (my ($var, $val) = splice(@$setlist, 0, 2)) { $output .= &assign($class, $var, $val, 1) . ";\n"; } chomp $output; return $output; } sub include { my ($class, $nameargs) = @_; my ($file, $args) = @$nameargs; my $hash = shift @$args; $file = $class->filenames($file); $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return "$OUTPUT context.include($file);"; } sub process { my ($class, $nameargs) = @_; my ($file, $args) = @$nameargs; my $hash = shift @$args; $file = $class->filenames($file); $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return "$OUTPUT context.process($file);"; } sub if { my ($class, $expr, $block, $else) = @_; my @else = $else ? @$else : (); $else = pop @else; my $output = "if ($expr) {\n$block\n}\n"; foreach my $elsif (@else) { ($expr, $block) = @$elsif; $output .= "else if ($expr) {\n$block\n}\n"; } if (defined $else) { $output .= "else {\n$else\n}\n"; } return $output; } sub foreach { my ($class, $target, $list, $args, $block) = @_; $args = shift @$args; $args = @$args ? ', { ' . join(', ', @$args) . ' }' : ''; my ($loop_save, $loop_set, $loop_restore, $setiter); if ($target) { $loop_save = 'try { oldloop = ' . $class->ident(["'loop'"]) . ' } finally {}'; $loop_set = "stash.data['$target'] = value"; $loop_restore = "stash.set('loop', oldloop)"; } else { die "XXX - Not supported yet"; $loop_save = 'stash = context.localise()'; $loop_set = "stash.get(['import', [value]]) if typeof(value) == 'object'"; $loop_restore = 'stash = context.delocalise()'; } return < /: / for @$hash; return $class->multi_wrapper($file, $hash, $block) if @$file > 1; $file = shift @$file; push(@$hash, "'content': output"); $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; return < $WHILE_MAX iterations)\\n") EOF } sub javascript { my ( $class, $javascript ) = @_; return $javascript; } sub no_javascript { my ( $class ) = @_; die "EVAL_JAVASCRIPT has not been enabled, cannot process [% JAVASCRIPT %] blocks"; } sub switch { my ($class, $expr, $case) = @_; my @case = @$case; my ($match, $block, $default); my $caseblock = ''; $default = pop @case; foreach $case (@case) { $match = $case->[0]; $block = $case->[1]; $caseblock .= <{$name}; if (*$glob{CODE}) { my $code = *$glob{CODE}; no warnings 'redefine'; $stash->{$name} = sub { warn "Calling $name(@_)\n"; &$code(@_); }; } } } 1; } # # Inline include of Jemplate/Grammar.pm # BEGIN { $INC{'Jemplate/Grammar.pm'} = 'dummy/Jemplate/Grammar.pm'; } BEGIN { #line 0 "Jemplate/Grammar.pm" package Jemplate::Grammar; require 5.004; use strict; use vars qw( $VERSION ); $VERSION = sprintf("%d.%02d", q$Revision: 2.10 $ =~ /(\d+)\.(\d+)/); my (@RESERVED, %CMPOP, $LEXTABLE, $RULES, $STATES); my ($factory, $rawstart); @RESERVED = qw( GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER BLOCK END USE RAW PLUGIN FILTER MACRO JAVASCRIPT TO STEP AND OR NOT DIV MOD IF UNLESS ELSE ELSIF FOR NEXT WHILE SWITCH CASE META IN TRY THROW CATCH FINAL LAST RETURN STOP CLEAR VIEW DEBUG ); %CMPOP = qw( != != == == < < > > >= >= <= <= ); $LEXTABLE = { 'FOREACH' => 'FOR', 'BREAK' => 'LAST', '&&' => 'AND', '||' => 'OR', '!' => 'NOT', '|' => 'FILTER', '.' => 'DOT', '_' => 'CAT', '..' => 'TO', '=' => 'ASSIGN', '=>' => 'ASSIGN', ',' => 'COMMA', '\\' => 'REF', 'and' => 'AND', # explicitly specified so that qw( and or 'or' => 'OR', # not ) can always be used in lower case, 'not' => 'NOT', # regardless of ANYCASE flag 'mod' => 'MOD', 'div' => 'DIV', }; { my @tokens = qw< ( ) [ ] { } ${ $ + / ; : ? >; my @cmpop = keys %CMPOP; my @binop = qw( - * % ); # '+' and '/' above, in @tokens # fill lexer table, slice by slice, with reserved words and operators @$LEXTABLE{ @RESERVED, @cmpop, @binop, @tokens } = ( @RESERVED, ('CMPOP') x @cmpop, ('BINOP') x @binop, @tokens ); } sub new { my $class = shift; bless { LEXTABLE => $LEXTABLE, STATES => $STATES, RULES => $RULES, }, $class; } sub install_factory { my ($self, $new_factory) = @_; $factory = $new_factory; } $STATES = [ {#State 0 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'loop' => 5, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'atomdir' => 13, 'anonblock' => 51, 'template' => 53, 'defblockname' => 14, 'ident' => 16, 'assign' => 19, 'macro' => 20, 'lterm' => 58, 'node' => 23, 'term' => 60, 'expr' => 64, 'use' => 65, 'defblock' => 68, 'filter' => 30, 'sterm' => 70, 'chunks' => 34, 'setlist' => 72, 'try' => 36, 'switch' => 35, 'directive' => 73, 'block' => 74, 'raw' => 39, 'condition' => 75 } }, {#State 1 ACTIONS => { "\$" => 44, 'LITERAL' => 77, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'setlist' => 78, 'item' => 41, 'assign' => 19, 'node' => 23, 'ident' => 76 } }, {#State 2 DEFAULT => -131 }, {#State 3 DEFAULT => -26 }, {#State 4 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 81, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 5 DEFAULT => -24 }, {#State 6 ACTIONS => { ";" => 82 } }, {#State 7 DEFAULT => -39 }, {#State 8 DEFAULT => -15 }, {#State 9 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 92, 'filename' => 87, 'name' => 84 } }, {#State 10 ACTIONS => { "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "]" => 96, "\${" => 38 }, GOTOS => { 'sterm' => 98, 'item' => 41, 'range' => 95, 'node' => 23, 'ident' => 79, 'term' => 97, 'lterm' => 58, 'list' => 94 } }, {#State 11 ACTIONS => { ";" => 99 } }, {#State 12 DEFAULT => -5 }, {#State 13 ACTIONS => { ";" => -21 }, DEFAULT => -29 }, {#State 14 ACTIONS => { 'IDENT' => 100 }, DEFAULT => -88, GOTOS => { 'blockargs' => 103, 'metadata' => 102, 'meta' => 101 } }, {#State 15 ACTIONS => { 'IDENT' => 100 }, GOTOS => { 'metadata' => 104, 'meta' => 101 } }, {#State 16 ACTIONS => { 'DOT' => 105, 'ASSIGN' => 106 }, DEFAULT => -110 }, {#State 17 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 107, 'filename' => 87, 'name' => 84 } }, {#State 18 ACTIONS => { 'IDENT' => 108 } }, {#State 19 DEFAULT => -150 }, {#State 20 DEFAULT => -12 }, {#State 21 ACTIONS => { "{" => 31, 'LITERAL' => 80, 'IDENT' => 109, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'sterm' => 70, 'item' => 41, 'loopvar' => 111, 'node' => 23, 'ident' => 79, 'term' => 110, 'lterm' => 58 } }, {#State 22 DEFAULT => -42 }, {#State 23 DEFAULT => -128 }, {#State 24 DEFAULT => -6 }, {#State 25 ACTIONS => { "\"" => 118, "\$" => 115, 'LITERAL' => 117, 'FILENAME' => 85, 'IDENT' => 112, 'NUMBER' => 86, "\${" => 38 }, GOTOS => { 'names' => 93, 'lvalue' => 113, 'item' => 114, 'name' => 84, 'filepart' => 89, 'filename' => 87, 'nameargs' => 119, 'lnameargs' => 116 } }, {#State 26 DEFAULT => -114 }, {#State 27 ACTIONS => { "\$" => 44, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 23, 'ident' => 120 } }, {#State 28 ACTIONS => { "\"" => 118, "\$" => 115, 'LITERAL' => 117, 'FILENAME' => 85, 'IDENT' => 112, 'NUMBER' => 86, "\${" => 38 }, GOTOS => { 'names' => 93, 'lvalue' => 113, 'item' => 114, 'name' => 84, 'filepart' => 89, 'filename' => 87, 'nameargs' => 119, 'lnameargs' => 121 } }, {#State 29 ACTIONS => { 'LITERAL' => 126, 'FILENAME' => 85, 'IDENT' => 122, 'NUMBER' => 86 }, DEFAULT => -88, GOTOS => { 'blockargs' => 125, 'filepart' => 89, 'filename' => 124, 'blockname' => 123, 'metadata' => 102, 'meta' => 101 } }, {#State 30 DEFAULT => -45 }, {#State 31 ACTIONS => { "\$" => 44, 'LITERAL' => 131, 'IDENT' => 2, "\${" => 38 }, DEFAULT => -120, GOTOS => { 'params' => 130, 'hash' => 127, 'item' => 128, 'param' => 129 } }, {#State 32 DEFAULT => -27 }, {#State 33 ACTIONS => { "\"" => 118, "\$" => 115, 'LITERAL' => 117, 'FILENAME' => 85, 'IDENT' => 112, 'NUMBER' => 86, "\${" => 38 }, GOTOS => { 'names' => 93, 'lvalue' => 113, 'item' => 114, 'name' => 84, 'filepart' => 89, 'filename' => 87, 'nameargs' => 119, 'lnameargs' => 132 } }, {#State 34 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -2, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 133, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'try' => 36, 'switch' => 35, 'assign' => 19, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 35 DEFAULT => -23 }, {#State 36 DEFAULT => -25 }, {#State 37 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 134, 'filename' => 87, 'name' => 84 } }, {#State 38 ACTIONS => { "\"" => 62, "\$" => 44, 'LITERAL' => 80, 'IDENT' => 2, 'REF' => 27, 'NUMBER' => 26, "\${" => 38 }, GOTOS => { 'sterm' => 135, 'item' => 41, 'node' => 23, 'ident' => 79 } }, {#State 39 DEFAULT => -14 }, {#State 40 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 136, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 41 ACTIONS => { "(" => 137 }, DEFAULT => -129 }, {#State 42 DEFAULT => -40 }, {#State 43 DEFAULT => -11 }, {#State 44 ACTIONS => { 'IDENT' => 138 } }, {#State 45 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 139, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 46 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 140, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 47 DEFAULT => -44 }, {#State 48 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 141, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 49 ACTIONS => { 'IF' => 145, 'FILTER' => 144, 'FOR' => 143, 'WHILE' => 147, 'WRAPPER' => 146, 'UNLESS' => 142 } }, {#State 50 DEFAULT => -41 }, {#State 51 DEFAULT => -10 }, {#State 52 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 148, 'filename' => 87, 'name' => 84 } }, {#State 53 ACTIONS => { '' => 149 } }, {#State 54 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 59, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 152, 'sterm' => 70, 'item' => 41, 'assign' => 151, 'node' => 23, 'ident' => 150, 'term' => 60, 'lterm' => 58 } }, {#State 55 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 153, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 56 ACTIONS => { ";" => 154 } }, {#State 57 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 155, 'filename' => 87, 'name' => 84 } }, {#State 58 DEFAULT => -104 }, {#State 59 ACTIONS => { 'ASSIGN' => 156 }, DEFAULT => -113 }, {#State 60 DEFAULT => -147 }, {#State 61 DEFAULT => -16 }, {#State 62 DEFAULT => -177, GOTOS => { 'quoted' => 157 } }, {#State 63 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 158, 'filename' => 87, 'name' => 84 } }, {#State 64 ACTIONS => { ";" => -17, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -28 }, {#State 65 DEFAULT => -13 }, {#State 66 DEFAULT => -38 }, {#State 67 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 169, 'filename' => 87, 'name' => 84 } }, {#State 68 DEFAULT => -9 }, {#State 69 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 170, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 70 DEFAULT => -105 }, {#State 71 ACTIONS => { "\$" => 44, 'LITERAL' => 77, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'setlist' => 171, 'item' => 41, 'assign' => 19, 'node' => 23, 'ident' => 76 } }, {#State 72 ACTIONS => { "\$" => 44, 'COMMA' => 173, 'LITERAL' => 77, 'IDENT' => 2, "\${" => 38 }, DEFAULT => -20, GOTOS => { 'item' => 41, 'assign' => 172, 'node' => 23, 'ident' => 76 } }, {#State 73 DEFAULT => -8 }, {#State 74 DEFAULT => -1 }, {#State 75 DEFAULT => -22 }, {#State 76 ACTIONS => { 'ASSIGN' => 174, 'DOT' => 105 } }, {#State 77 ACTIONS => { 'ASSIGN' => 156 } }, {#State 78 ACTIONS => { 'COMMA' => 173, 'LITERAL' => 77, 'IDENT' => 2, "\$" => 44, "\${" => 38 }, DEFAULT => -32, GOTOS => { 'item' => 41, 'assign' => 172, 'node' => 23, 'ident' => 76 } }, {#State 79 ACTIONS => { 'DOT' => 105 }, DEFAULT => -110 }, {#State 80 DEFAULT => -113 }, {#State 81 ACTIONS => { 'CMPOP' => 166, "?" => 160, ";" => 175, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 } }, {#State 82 DEFAULT => -7 }, {#State 83 DEFAULT => -174 }, {#State 84 DEFAULT => -167 }, {#State 85 DEFAULT => -173 }, {#State 86 DEFAULT => -175 }, {#State 87 ACTIONS => { 'DOT' => 176 }, DEFAULT => -169 }, {#State 88 ACTIONS => { "\$" => 44, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 23, 'ident' => 177 } }, {#State 89 DEFAULT => -172 }, {#State 90 DEFAULT => -170 }, {#State 91 DEFAULT => -177, GOTOS => { 'quoted' => 178 } }, {#State 92 DEFAULT => -37 }, {#State 93 ACTIONS => { "+" => 179, "(" => 180 }, DEFAULT => -157, GOTOS => { 'args' => 181 } }, {#State 94 ACTIONS => { "{" => 31, 'COMMA' => 184, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "]" => 182, "\${" => 38 }, GOTOS => { 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 183, 'lterm' => 58 } }, {#State 95 ACTIONS => { "]" => 185 } }, {#State 96 DEFAULT => -108 }, {#State 97 DEFAULT => -117 }, {#State 98 ACTIONS => { 'TO' => 186 }, DEFAULT => -105 }, {#State 99 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 187, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 100 ACTIONS => { 'ASSIGN' => 188 } }, {#State 101 DEFAULT => -100 }, {#State 102 ACTIONS => { 'COMMA' => 190, 'IDENT' => 100 }, DEFAULT => -87, GOTOS => { 'meta' => 189 } }, {#State 103 ACTIONS => { ";" => 191 } }, {#State 104 ACTIONS => { 'COMMA' => 190, 'IDENT' => 100 }, DEFAULT => -18, GOTOS => { 'meta' => 189 } }, {#State 105 ACTIONS => { "\$" => 44, 'IDENT' => 2, 'NUMBER' => 193, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 192 } }, {#State 106 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, 'FOR' => 21, 'NEXT' => 22, 'LITERAL' => 59, "\"" => 62, 'PROCESS' => 63, 'FILTER' => 25, 'RETURN' => 66, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'BLOCK' => 194, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, "\${" => 38 }, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'expr' => 196, 'wrapper' => 47, 'atomexpr' => 49, 'atomdir' => 13, 'mdir' => 195, 'filter' => 30, 'sterm' => 70, 'ident' => 150, 'setlist' => 72, 'try' => 36, 'switch' => 35, 'assign' => 19, 'directive' => 197, 'condition' => 75, 'lterm' => 58 } }, {#State 107 DEFAULT => -35 }, {#State 108 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'INCLUDE' => 17, "(" => 199, 'SWITCH' => 55, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, 'FOR' => 21, 'NEXT' => 22, 'LITERAL' => 59, "\"" => 62, 'PROCESS' => 63, 'FILTER' => 25, 'RETURN' => 66, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'BLOCK' => 194, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, "\${" => 38 }, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'expr' => 200, 'wrapper' => 47, 'atomexpr' => 49, 'atomdir' => 13, 'mdir' => 198, 'filter' => 30, 'sterm' => 70, 'ident' => 150, 'setlist' => 72, 'try' => 36, 'switch' => 35, 'assign' => 19, 'directive' => 197, 'condition' => 75, 'lterm' => 58 } }, {#State 109 ACTIONS => { 'IN' => 202, 'ASSIGN' => 201 }, DEFAULT => -131 }, {#State 110 DEFAULT => -157, GOTOS => { 'args' => 203 } }, {#State 111 ACTIONS => { ";" => 204 } }, {#State 112 ACTIONS => { 'ASSIGN' => -131 }, DEFAULT => -174 }, {#State 113 ACTIONS => { 'ASSIGN' => 205 } }, {#State 114 DEFAULT => -160 }, {#State 115 ACTIONS => { "\$" => 44, 'IDENT' => 206, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 23, 'ident' => 177 } }, {#State 116 ACTIONS => { ";" => 207 } }, {#State 117 ACTIONS => { 'ASSIGN' => -162 }, DEFAULT => -170 }, {#State 118 DEFAULT => -177, GOTOS => { 'quoted' => 208 } }, {#State 119 DEFAULT => -159 }, {#State 120 ACTIONS => { 'DOT' => 105 }, DEFAULT => -111 }, {#State 121 DEFAULT => -76 }, {#State 122 ACTIONS => { 'ASSIGN' => 188 }, DEFAULT => -174 }, {#State 123 DEFAULT => -84 }, {#State 124 ACTIONS => { 'DOT' => 176 }, DEFAULT => -85 }, {#State 125 ACTIONS => { ";" => 209 } }, {#State 126 DEFAULT => -86 }, {#State 127 ACTIONS => { "}" => 210 } }, {#State 128 ACTIONS => { 'ASSIGN' => 211 } }, {#State 129 DEFAULT => -123 }, {#State 130 ACTIONS => { "\$" => 44, 'COMMA' => 213, 'LITERAL' => 131, 'IDENT' => 2, "\${" => 38 }, DEFAULT => -119, GOTOS => { 'item' => 128, 'param' => 212 } }, {#State 131 ACTIONS => { 'ASSIGN' => 214 } }, {#State 132 DEFAULT => -75 }, {#State 133 DEFAULT => -4 }, {#State 134 ACTIONS => { ";" => 215 } }, {#State 135 ACTIONS => { "}" => 216 } }, {#State 136 ACTIONS => { 'DIV' => 161, 'BINOP' => 163, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, 'MOD' => 167, "/" => 168 }, DEFAULT => -143 }, {#State 137 DEFAULT => -157, GOTOS => { 'args' => 217 } }, {#State 138 DEFAULT => -133 }, {#State 139 ACTIONS => { 'CMPOP' => 166, "?" => 160, ";" => 218, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 } }, {#State 140 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -31 }, {#State 141 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -30 }, {#State 142 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 219, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 143 ACTIONS => { "{" => 31, 'LITERAL' => 80, 'IDENT' => 109, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'sterm' => 70, 'item' => 41, 'loopvar' => 220, 'node' => 23, 'ident' => 79, 'term' => 110, 'lterm' => 58 } }, {#State 144 ACTIONS => { "\"" => 118, "\$" => 115, 'LITERAL' => 117, 'FILENAME' => 85, 'IDENT' => 112, 'NUMBER' => 86, "\${" => 38 }, GOTOS => { 'names' => 93, 'lvalue' => 113, 'item' => 114, 'name' => 84, 'filepart' => 89, 'filename' => 87, 'nameargs' => 119, 'lnameargs' => 221 } }, {#State 145 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 222, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 146 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 223, 'filename' => 87, 'name' => 84 } }, {#State 147 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 224, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 148 DEFAULT => -43 }, {#State 149 DEFAULT => 0 }, {#State 150 ACTIONS => { 'DOT' => 105, 'ASSIGN' => 174 }, DEFAULT => -110 }, {#State 151 ACTIONS => { ")" => 225 } }, {#State 152 ACTIONS => { 'CMPOP' => 166, "?" => 160, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, ")" => 226, 'OR' => 164 } }, {#State 153 ACTIONS => { 'CMPOP' => 166, "?" => 160, ";" => 227, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 } }, {#State 154 DEFAULT => -79, GOTOS => { '@4-2' => 228 } }, {#State 155 ACTIONS => { ";" => 229 } }, {#State 156 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 230, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 157 ACTIONS => { "\"" => 235, 'TEXT' => 232, ";" => 234, "\$" => 44, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 23, 'ident' => 231, 'quotable' => 233 } }, {#State 158 DEFAULT => -36 }, {#State 159 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 236, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 160 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 237, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 161 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 238, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 162 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 239, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 163 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 240, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 164 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 241, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 165 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 242, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 166 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 243, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 167 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 244, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 168 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 245, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 169 DEFAULT => -34 }, {#State 170 ACTIONS => { 'CMPOP' => 166, "?" => 160, ";" => 246, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 } }, {#State 171 ACTIONS => { 'COMMA' => 173, 'LITERAL' => 77, 'IDENT' => 2, "\$" => 44, "\${" => 38 }, DEFAULT => -33, GOTOS => { 'item' => 41, 'assign' => 172, 'node' => 23, 'ident' => 76 } }, {#State 172 DEFAULT => -148 }, {#State 173 DEFAULT => -149 }, {#State 174 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 247, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 175 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 248, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 176 ACTIONS => { 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 249 } }, {#State 177 ACTIONS => { 'DOT' => 105 }, DEFAULT => -157, GOTOS => { 'args' => 250 } }, {#State 178 ACTIONS => { "\"" => 251, 'TEXT' => 232, ";" => 234, "\$" => 44, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 23, 'ident' => 231, 'quotable' => 233 } }, {#State 179 ACTIONS => { "\"" => 91, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'filename' => 87, 'name' => 252 } }, {#State 180 DEFAULT => -157, GOTOS => { 'args' => 253 } }, {#State 181 ACTIONS => { 'NOT' => 40, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "{" => 31, 'COMMA' => 259, "(" => 54, "\${" => 38 }, DEFAULT => -164, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 182 DEFAULT => -106 }, {#State 183 DEFAULT => -115 }, {#State 184 DEFAULT => -116 }, {#State 185 DEFAULT => -107 }, {#State 186 ACTIONS => { "\"" => 62, "\$" => 44, 'LITERAL' => 80, 'IDENT' => 2, 'REF' => 27, 'NUMBER' => 26, "\${" => 38 }, GOTOS => { 'sterm' => 260, 'item' => 41, 'node' => 23, 'ident' => 79 } }, {#State 187 ACTIONS => { 'FINAL' => 261, 'CATCH' => 263 }, DEFAULT => -74, GOTOS => { 'final' => 262 } }, {#State 188 ACTIONS => { "\"" => 266, 'LITERAL' => 265, 'NUMBER' => 264 } }, {#State 189 DEFAULT => -98 }, {#State 190 DEFAULT => -99 }, {#State 191 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'loop' => 5, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'atomdir' => 13, 'anonblock' => 51, 'template' => 267, 'defblockname' => 14, 'ident' => 16, 'assign' => 19, 'macro' => 20, 'lterm' => 58, 'node' => 23, 'term' => 60, 'expr' => 64, 'use' => 65, 'defblock' => 68, 'filter' => 30, 'sterm' => 70, 'chunks' => 34, 'setlist' => 72, 'switch' => 35, 'try' => 36, 'directive' => 73, 'block' => 74, 'raw' => 39, 'condition' => 75 } }, {#State 192 DEFAULT => -126 }, {#State 193 DEFAULT => -127 }, {#State 194 ACTIONS => { ";" => 268 } }, {#State 195 DEFAULT => -90 }, {#State 196 ACTIONS => { ";" => -151, "+" => 159, 'LITERAL' => -151, 'IDENT' => -151, 'CAT' => 165, "\$" => -151, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, 'COMMA' => -151, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164, "\${" => -151 }, DEFAULT => -28 }, {#State 197 DEFAULT => -93 }, {#State 198 DEFAULT => -92 }, {#State 199 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 59, 'IDENT' => 269, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 152, 'sterm' => 70, 'item' => 41, 'assign' => 151, 'margs' => 270, 'node' => 23, 'ident' => 150, 'term' => 60, 'lterm' => 58 } }, {#State 200 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -28 }, {#State 201 ACTIONS => { "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 271, 'lterm' => 58 } }, {#State 202 ACTIONS => { "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 272, 'lterm' => 58 } }, {#State 203 ACTIONS => { 'NOT' => 40, "{" => 31, 'COMMA' => 259, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, DEFAULT => -66, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 204 DEFAULT => -58, GOTOS => { '@1-3' => 273 } }, {#State 205 ACTIONS => { "\"" => 91, "\$" => 88, 'LITERAL' => 90, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'names' => 93, 'nameargs' => 274, 'filename' => 87, 'name' => 84 } }, {#State 206 ACTIONS => { 'ASSIGN' => -133 }, DEFAULT => -131 }, {#State 207 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 275, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 208 ACTIONS => { "\"" => 276, 'TEXT' => 232, ";" => 234, "\$" => 44, 'IDENT' => 2, "\${" => 38 }, GOTOS => { 'item' => 41, 'node' => 23, 'ident' => 231, 'quotable' => 233 } }, {#State 209 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 277, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 210 DEFAULT => -109 }, {#State 211 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 278, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 212 DEFAULT => -121 }, {#State 213 DEFAULT => -122 }, {#State 214 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 279, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 215 DEFAULT => -77, GOTOS => { '@3-3' => 280 } }, {#State 216 DEFAULT => -132 }, {#State 217 ACTIONS => { 'NOT' => 40, "{" => 31, 'COMMA' => 259, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, ")" => 281, "\${" => 38 }, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 218 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 282, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 219 ACTIONS => { 'CMPOP' => 166, "?" => 160, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -49 }, {#State 220 DEFAULT => -60 }, {#State 221 DEFAULT => -82 }, {#State 222 ACTIONS => { 'CMPOP' => 166, "?" => 160, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -47 }, {#State 223 DEFAULT => -68 }, {#State 224 ACTIONS => { 'CMPOP' => 166, "?" => 160, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -63 }, {#State 225 DEFAULT => -145 }, {#State 226 DEFAULT => -146 }, {#State 227 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 283, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 228 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 284, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 229 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 285, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 230 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -152 }, {#State 231 ACTIONS => { 'DOT' => 105 }, DEFAULT => -178 }, {#State 232 DEFAULT => -179 }, {#State 233 DEFAULT => -176 }, {#State 234 DEFAULT => -180 }, {#State 235 DEFAULT => -112 }, {#State 236 ACTIONS => { 'DIV' => 161, 'MOD' => 167, "/" => 168 }, DEFAULT => -136 }, {#State 237 ACTIONS => { ":" => 286, 'CMPOP' => 166, "?" => 160, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 } }, {#State 238 ACTIONS => { 'MOD' => 167 }, DEFAULT => -137 }, {#State 239 ACTIONS => { 'DIV' => 161, 'BINOP' => 163, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, 'MOD' => 167, "/" => 168 }, DEFAULT => -141 }, {#State 240 ACTIONS => { 'DIV' => 161, "+" => 159, 'MOD' => 167, "/" => 168 }, DEFAULT => -134 }, {#State 241 ACTIONS => { 'DIV' => 161, 'BINOP' => 163, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, 'MOD' => 167, "/" => 168 }, DEFAULT => -142 }, {#State 242 ACTIONS => { 'DIV' => 161, 'BINOP' => 163, "+" => 159, 'CMPOP' => 166, 'MOD' => 167, "/" => 168 }, DEFAULT => -140 }, {#State 243 ACTIONS => { 'DIV' => 161, 'BINOP' => 163, "+" => 159, 'MOD' => 167, "/" => 168 }, DEFAULT => -139 }, {#State 244 DEFAULT => -138 }, {#State 245 ACTIONS => { 'DIV' => 161, 'MOD' => 167 }, DEFAULT => -135 }, {#State 246 DEFAULT => -61, GOTOS => { '@2-3' => 287 } }, {#State 247 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -151 }, {#State 248 ACTIONS => { 'ELSIF' => 290, 'ELSE' => 288 }, DEFAULT => -52, GOTOS => { 'else' => 289 } }, {#State 249 DEFAULT => -171 }, {#State 250 ACTIONS => { 'NOT' => 40, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "{" => 31, 'COMMA' => 259, "(" => 54, "\${" => 38 }, DEFAULT => -163, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 251 DEFAULT => -168 }, {#State 252 DEFAULT => -166 }, {#State 253 ACTIONS => { 'NOT' => 40, "{" => 31, 'COMMA' => 259, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, ")" => 291, "\${" => 38 }, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 254 ACTIONS => { 'DOT' => 105, 'ASSIGN' => 292 }, DEFAULT => -110 }, {#State 255 ACTIONS => { "(" => 137, 'ASSIGN' => 211 }, DEFAULT => -129 }, {#State 256 DEFAULT => -154 }, {#State 257 ACTIONS => { 'ASSIGN' => 214 }, DEFAULT => -113 }, {#State 258 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -153 }, {#State 259 DEFAULT => -156 }, {#State 260 DEFAULT => -118 }, {#State 261 ACTIONS => { ";" => 293 } }, {#State 262 ACTIONS => { 'END' => 294 } }, {#State 263 ACTIONS => { ";" => 296, 'DEFAULT' => 297, 'FILENAME' => 85, 'IDENT' => 83, 'NUMBER' => 86 }, GOTOS => { 'filepart' => 89, 'filename' => 295 } }, {#State 264 DEFAULT => -103 }, {#State 265 DEFAULT => -101 }, {#State 266 ACTIONS => { 'TEXT' => 298 } }, {#State 267 ACTIONS => { 'END' => 299 } }, {#State 268 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 300, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 269 ACTIONS => { 'IDENT' => -97, ")" => -97, 'COMMA' => -97 }, DEFAULT => -131 }, {#State 270 ACTIONS => { 'COMMA' => 303, 'IDENT' => 301, ")" => 302 } }, {#State 271 DEFAULT => -157, GOTOS => { 'args' => 304 } }, {#State 272 DEFAULT => -157, GOTOS => { 'args' => 305 } }, {#State 273 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 306, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 274 DEFAULT => -158 }, {#State 275 ACTIONS => { 'END' => 307 } }, {#State 276 ACTIONS => { 'ASSIGN' => -161 }, DEFAULT => -168 }, {#State 277 ACTIONS => { 'END' => 308 } }, {#State 278 ACTIONS => { 'DIV' => 161, 'AND' => 162, 'BINOP' => 163, 'OR' => 164, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'MOD' => 167, "/" => 168 }, DEFAULT => -125 }, {#State 279 ACTIONS => { 'DIV' => 161, 'AND' => 162, 'BINOP' => 163, 'OR' => 164, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'MOD' => 167, "/" => 168 }, DEFAULT => -124 }, {#State 280 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 309, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 281 DEFAULT => -130 }, {#State 282 ACTIONS => { 'ELSIF' => 290, 'ELSE' => 288 }, DEFAULT => -52, GOTOS => { 'else' => 310 } }, {#State 283 ACTIONS => { 'CASE' => 311 }, DEFAULT => -57, GOTOS => { 'case' => 312 } }, {#State 284 ACTIONS => { 'END' => 313 } }, {#State 285 ACTIONS => { 'END' => 314 } }, {#State 286 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 315, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 287 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 316, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 288 ACTIONS => { ";" => 317 } }, {#State 289 ACTIONS => { 'END' => 318 } }, {#State 290 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 319, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 291 DEFAULT => -165 }, {#State 292 ACTIONS => { 'NOT' => 40, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'expr' => 320, 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 60, 'lterm' => 58 } }, {#State 293 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 321, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 294 DEFAULT => -69 }, {#State 295 ACTIONS => { 'DOT' => 176, ";" => 322 } }, {#State 296 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 323, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 297 ACTIONS => { ";" => 324 } }, {#State 298 ACTIONS => { "\"" => 325 } }, {#State 299 DEFAULT => -83 }, {#State 300 ACTIONS => { 'END' => 326 } }, {#State 301 DEFAULT => -95 }, {#State 302 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, 'FOR' => 21, 'NEXT' => 22, 'LITERAL' => 59, "\"" => 62, 'PROCESS' => 63, 'FILTER' => 25, 'RETURN' => 66, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'BLOCK' => 194, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, "\${" => 38 }, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'expr' => 200, 'wrapper' => 47, 'atomexpr' => 49, 'atomdir' => 13, 'mdir' => 327, 'filter' => 30, 'sterm' => 70, 'ident' => 150, 'setlist' => 72, 'try' => 36, 'switch' => 35, 'assign' => 19, 'directive' => 197, 'condition' => 75, 'lterm' => 58 } }, {#State 303 DEFAULT => -96 }, {#State 304 ACTIONS => { 'NOT' => 40, "{" => 31, 'COMMA' => 259, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, DEFAULT => -64, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 305 ACTIONS => { 'NOT' => 40, "{" => 31, 'COMMA' => 259, 'LITERAL' => 257, 'IDENT' => 2, "\"" => 62, "(" => 54, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, DEFAULT => -65, GOTOS => { 'expr' => 258, 'sterm' => 70, 'item' => 255, 'param' => 256, 'node' => 23, 'ident' => 254, 'term' => 60, 'lterm' => 58 } }, {#State 306 ACTIONS => { 'END' => 328 } }, {#State 307 DEFAULT => -81 }, {#State 308 DEFAULT => -89 }, {#State 309 ACTIONS => { 'END' => 329 } }, {#State 310 ACTIONS => { 'END' => 330 } }, {#State 311 ACTIONS => { ";" => 331, 'DEFAULT' => 333, "{" => 31, 'LITERAL' => 80, 'IDENT' => 2, "\"" => 62, "\$" => 44, "[" => 10, 'NUMBER' => 26, 'REF' => 27, "\${" => 38 }, GOTOS => { 'sterm' => 70, 'item' => 41, 'node' => 23, 'ident' => 79, 'term' => 332, 'lterm' => 58 } }, {#State 312 ACTIONS => { 'END' => 334 } }, {#State 313 DEFAULT => -80 }, {#State 314 DEFAULT => -67 }, {#State 315 ACTIONS => { 'DIV' => 161, 'AND' => 162, 'BINOP' => 163, 'OR' => 164, "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'MOD' => 167, "/" => 168 }, DEFAULT => -144 }, {#State 316 ACTIONS => { 'END' => 335 } }, {#State 317 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 336, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 318 DEFAULT => -48 }, {#State 319 ACTIONS => { 'CMPOP' => 166, "?" => 160, ";" => 337, "+" => 159, 'MOD' => 167, 'DIV' => 161, "/" => 168, 'AND' => 162, 'CAT' => 165, 'BINOP' => 163, 'OR' => 164 } }, {#State 320 ACTIONS => { "+" => 159, 'CAT' => 165, 'CMPOP' => 166, "?" => 160, 'DIV' => 161, 'MOD' => 167, "/" => 168, 'AND' => 162, 'BINOP' => 163, 'OR' => 164 }, DEFAULT => -155 }, {#State 321 DEFAULT => -73 }, {#State 322 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 338, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 323 ACTIONS => { 'FINAL' => 261, 'CATCH' => 263 }, DEFAULT => -74, GOTOS => { 'final' => 339 } }, {#State 324 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 340, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 325 DEFAULT => -102 }, {#State 326 DEFAULT => -94 }, {#State 327 DEFAULT => -91 }, {#State 328 DEFAULT => -59 }, {#State 329 DEFAULT => -78 }, {#State 330 DEFAULT => -46 }, {#State 331 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 341, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 332 ACTIONS => { ";" => 342 } }, {#State 333 ACTIONS => { ";" => 343 } }, {#State 334 DEFAULT => -53 }, {#State 335 DEFAULT => -62 }, {#State 336 DEFAULT => -51 }, {#State 337 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 344, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 338 ACTIONS => { 'FINAL' => 261, 'CATCH' => 263 }, DEFAULT => -74, GOTOS => { 'final' => 345 } }, {#State 339 DEFAULT => -72 }, {#State 340 ACTIONS => { 'FINAL' => 261, 'CATCH' => 263 }, DEFAULT => -74, GOTOS => { 'final' => 346 } }, {#State 341 DEFAULT => -56 }, {#State 342 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 347, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 343 ACTIONS => { 'SET' => 1, 'NOT' => 40, 'IDENT' => 2, 'CLEAR' => 42, 'UNLESS' => 4, 'IF' => 45, "\$" => 44, 'STOP' => 7, 'CALL' => 46, 'THROW' => 9, 'GET' => 48, "[" => 10, 'TRY' => 11, 'LAST' => 50, 'DEBUG' => 52, 'META' => 15, 'INCLUDE' => 17, "(" => 54, 'SWITCH' => 55, 'MACRO' => 18, 'JAVASCRIPT' => 56, 'WRAPPER' => 57, ";" => -19, 'FOR' => 21, 'LITERAL' => 59, 'NEXT' => 22, 'rawperl' => 61, "\"" => 62, 'TEXT' => 24, 'PROCESS' => 63, 'RETURN' => 66, 'FILTER' => 25, 'INSERT' => 67, 'NUMBER' => 26, 'REF' => 27, 'WHILE' => 69, 'RAW' => 28, 'BLOCK' => 29, 'DEFAULT' => 71, "{" => 31, 'perl' => 32, 'USE' => 33, 'VIEW' => 37, "\${" => 38 }, DEFAULT => -3, GOTOS => { 'item' => 41, 'javascript' => 3, 'node' => 23, 'term' => 60, 'loop' => 5, 'use' => 65, 'expr' => 64, 'capture' => 43, 'statement' => 6, 'view' => 8, 'wrapper' => 47, 'atomexpr' => 49, 'chunk' => 12, 'defblock' => 68, 'atomdir' => 13, 'anonblock' => 51, 'sterm' => 70, 'defblockname' => 14, 'filter' => 30, 'ident' => 16, 'setlist' => 72, 'chunks' => 34, 'try' => 36, 'switch' => 35, 'assign' => 19, 'block' => 348, 'directive' => 73, 'macro' => 20, 'condition' => 75, 'lterm' => 58, 'raw' => 39 } }, {#State 344 ACTIONS => { 'ELSIF' => 290, 'ELSE' => 288 }, DEFAULT => -52, GOTOS => { 'else' => 349 } }, {#State 345 DEFAULT => -70 }, {#State 346 DEFAULT => -71 }, {#State 347 ACTIONS => { 'CASE' => 311 }, DEFAULT => -57, GOTOS => { 'case' => 350 } }, {#State 348 DEFAULT => -55 }, {#State 349 DEFAULT => -50 }, {#State 350 DEFAULT => -54 } ]; $RULES = [ [#Rule 0 '$start', 2, undef ], [#Rule 1 'template', 1, sub { $factory->template($_[1]) } ], [#Rule 2 'block', 1, sub { $factory->block($_[1]) } ], [#Rule 3 'block', 0, sub { $factory->block() } ], [#Rule 4 'chunks', 2, sub { push(@{$_[1]}, $_[2]) if defined $_[2]; $_[1] } ], [#Rule 5 'chunks', 1, sub { defined $_[1] ? [ $_[1] ] : [ ] } ], [#Rule 6 'chunk', 1, sub { $factory->textblock($_[1]) } ], [#Rule 7 'chunk', 2, sub { return '' unless $_[1]; $_[0]->location() . $_[1]; } ], [#Rule 8 'statement', 1, undef ], [#Rule 9 'statement', 1, undef ], [#Rule 10 'statement', 1, undef ], [#Rule 11 'statement', 1, undef ], [#Rule 12 'statement', 1, undef ], [#Rule 13 'statement', 1, undef ], [#Rule 14 'statement', 1, undef ], [#Rule 15 'statement', 1, undef ], [#Rule 16 'statement', 1, undef ], [#Rule 17 'statement', 1, sub { $factory->get($_[1]) } ], [#Rule 18 'statement', 2, sub { $_[0]->add_metadata($_[2]); } ], [#Rule 19 'statement', 0, undef ], [#Rule 20 'directive', 1, sub { $factory->set($_[1]) } ], [#Rule 21 'directive', 1, undef ], [#Rule 22 'directive', 1, undef ], [#Rule 23 'directive', 1, undef ], [#Rule 24 'directive', 1, undef ], [#Rule 25 'directive', 1, undef ], [#Rule 26 'directive', 1, undef ], [#Rule 27 'directive', 1, undef ], [#Rule 28 'atomexpr', 1, sub { $factory->get($_[1]) } ], [#Rule 29 'atomexpr', 1, undef ], [#Rule 30 'atomdir', 2, sub { $factory->get($_[2]) } ], [#Rule 31 'atomdir', 2, sub { $factory->call($_[2]) } ], [#Rule 32 'atomdir', 2, sub { $factory->set($_[2]) } ], [#Rule 33 'atomdir', 2, sub { $factory->default($_[2]) } ], [#Rule 34 'atomdir', 2, sub { $factory->insert($_[2]) } ], [#Rule 35 'atomdir', 2, sub { $factory->include($_[2]) } ], [#Rule 36 'atomdir', 2, sub { $factory->process($_[2]) } ], [#Rule 37 'atomdir', 2, sub { $factory->throw($_[2]) } ], [#Rule 38 'atomdir', 1, sub { $factory->return() } ], [#Rule 39 'atomdir', 1, sub { $factory->stop() } ], [#Rule 40 'atomdir', 1, sub { $factory->clear() } ], [#Rule 41 'atomdir', 1, sub { $factory->break() } ], [#Rule 42 'atomdir', 1, sub { $factory->next() } ], [#Rule 43 'atomdir', 2, sub { if ($_[2]->[0]->[0] =~ /^'(on|off)'$/) { $_[0]->{ DEBUG_DIRS } = ($1 eq 'on'); $factory->debug($_[2]); } else { $_[0]->{ DEBUG_DIRS } ? $factory->debug($_[2]) : ''; } } ], [#Rule 44 'atomdir', 1, undef ], [#Rule 45 'atomdir', 1, undef ], [#Rule 46 'condition', 6, sub { $factory->if(@_[2, 4, 5]) } ], [#Rule 47 'condition', 3, sub { $factory->if(@_[3, 1]) } ], [#Rule 48 'condition', 6, sub { $factory->if("!($_[2])", @_[4, 5]) } ], [#Rule 49 'condition', 3, sub { $factory->if("!($_[3])", $_[1]) } ], [#Rule 50 'else', 5, sub { unshift(@{$_[5]}, [ @_[2, 4] ]); $_[5]; } ], [#Rule 51 'else', 3, sub { [ $_[3] ] } ], [#Rule 52 'else', 0, sub { [ undef ] } ], [#Rule 53 'switch', 6, sub { $factory->switch(@_[2, 5]) } ], [#Rule 54 'case', 5, sub { unshift(@{$_[5]}, [ @_[2, 4] ]); $_[5]; } ], [#Rule 55 'case', 4, sub { [ $_[4] ] } ], [#Rule 56 'case', 3, sub { [ $_[3] ] } ], [#Rule 57 'case', 0, sub { [ undef ] } ], [#Rule 58 '@1-3', 0, sub { $_[0]->{ INFOR }++ } ], [#Rule 59 'loop', 6, sub { $_[0]->{ INFOR }--; $factory->foreach(@{$_[2]}, $_[5]) } ], [#Rule 60 'loop', 3, sub { $factory->foreach(@{$_[3]}, $_[1]) } ], [#Rule 61 '@2-3', 0, sub { $_[0]->{ INWHILE }++ } ], [#Rule 62 'loop', 6, sub { $_[0]->{ INWHILE }--; $factory->while(@_[2, 5]) } ], [#Rule 63 'loop', 3, sub { $factory->while(@_[3, 1]) } ], [#Rule 64 'loopvar', 4, sub { [ @_[1, 3, 4] ] } ], [#Rule 65 'loopvar', 4, sub { [ @_[1, 3, 4] ] } ], [#Rule 66 'loopvar', 2, sub { [ 0, @_[1, 2] ] } ], [#Rule 67 'wrapper', 5, sub { $factory->wrapper(@_[2, 4]) } ], [#Rule 68 'wrapper', 3, sub { $factory->wrapper(@_[3, 1]) } ], [#Rule 69 'try', 5, sub { $factory->try(@_[3, 4]) } ], [#Rule 70 'final', 5, sub { unshift(@{$_[5]}, [ @_[2,4] ]); $_[5]; } ], [#Rule 71 'final', 5, sub { unshift(@{$_[5]}, [ undef, $_[4] ]); $_[5]; } ], [#Rule 72 'final', 4, sub { unshift(@{$_[4]}, [ undef, $_[3] ]); $_[4]; } ], [#Rule 73 'final', 3, sub { [ $_[3] ] } ], [#Rule 74 'final', 0, sub { [ 0 ] } ], [#Rule 75 'use', 2, sub { $factory->use($_[2]) } ], [#Rule 76 'raw', 2, sub { $factory->raw($_[2]) } ], [#Rule 77 '@3-3', 0, sub { $_[0]->push_defblock(); } ], [#Rule 78 'view', 6, sub { $factory->view(@_[2,5], $_[0]->pop_defblock) } ], [#Rule 79 '@4-2', 0, sub { ${$_[0]->{ INJAVASCRIPT }}++; } ], [#Rule 80 'javascript', 5, sub { ${$_[0]->{ INJAVASCRIPT }}--; $_[0]->{ EVAL_JAVASCRIPT } ? $factory->javascript($_[4]) : $factory->no_javascript(); } ], [#Rule 81 'filter', 5, sub { $factory->filter(@_[2,4]) } ], [#Rule 82 'filter', 3, sub { $factory->filter(@_[3,1]) } ], [#Rule 83 'defblock', 5, sub { my $name = join('/', @{ $_[0]->{ DEFBLOCKS } }); pop(@{ $_[0]->{ DEFBLOCKS } }); $_[0]->define_block($name, $_[4]); undef } ], [#Rule 84 'defblockname', 2, sub { push(@{ $_[0]->{ DEFBLOCKS } }, $_[2]); $_[2]; } ], [#Rule 85 'blockname', 1, undef ], [#Rule 86 'blockname', 1, sub { $_[1] =~ s/^'(.*)'$/$1/; $_[1] } ], [#Rule 87 'blockargs', 1, undef ], [#Rule 88 'blockargs', 0, undef ], [#Rule 89 'anonblock', 5, sub { local $" = ', '; print STDERR "experimental block args: [@{ $_[2] }]\n" if $_[2]; $factory->anon_block($_[4]) } ], [#Rule 90 'capture', 3, sub { $factory->capture(@_[1, 3]) } ], [#Rule 91 'macro', 6, sub { $factory->macro(@_[2, 6, 4]) } ], [#Rule 92 'macro', 3, sub { $factory->macro(@_[2, 3]) } ], [#Rule 93 'mdir', 1, undef ], [#Rule 94 'mdir', 4, sub { $_[3] } ], [#Rule 95 'margs', 2, sub { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 96 'margs', 2, sub { $_[1] } ], [#Rule 97 'margs', 1, sub { [ $_[1] ] } ], [#Rule 98 'metadata', 2, sub { push(@{$_[1]}, @{$_[2]}); $_[1] } ], [#Rule 99 'metadata', 2, undef ], [#Rule 100 'metadata', 1, undef ], [#Rule 101 'meta', 3, sub { for ($_[3]) { s/^'//; s/'$//; s/\\'/'/g }; [ @_[1,3] ] } ], [#Rule 102 'meta', 5, sub { [ @_[1,4] ] } ], [#Rule 103 'meta', 3, sub { [ @_[1,3] ] } ], [#Rule 104 'term', 1, undef ], [#Rule 105 'term', 1, undef ], [#Rule 106 'lterm', 3, sub { "[ $_[2] ]" } ], [#Rule 107 'lterm', 3, sub { "[ $_[2] ]" } ], [#Rule 108 'lterm', 2, sub { "[ ]" } ], [#Rule 109 'lterm', 3, sub { "{ $_[2] }" } ], [#Rule 110 'sterm', 1, sub { $factory->ident($_[1]) } ], [#Rule 111 'sterm', 2, sub { $factory->identref($_[2]) } ], [#Rule 112 'sterm', 3, sub { $factory->quoted($_[2]) } ], [#Rule 113 'sterm', 1, undef ], [#Rule 114 'sterm', 1, undef ], [#Rule 115 'list', 2, sub { "$_[1], $_[2]" } ], [#Rule 116 'list', 2, undef ], [#Rule 117 'list', 1, undef ], [#Rule 118 'range', 3, sub { $_[1] . '..' . $_[3] } ], [#Rule 119 'hash', 1, undef ], [#Rule 120 'hash', 0, sub { "" } ], [#Rule 121 'params', 2, sub { "$_[1], $_[2]" } ], [#Rule 122 'params', 2, undef ], [#Rule 123 'params', 1, undef ], [#Rule 124 'param', 3, sub { "$_[1]: $_[3]" } ], [#Rule 125 'param', 3, sub { "$_[1]: $_[3]" } ], [#Rule 126 'ident', 3, sub { push(@{$_[1]}, @{$_[3]}); $_[1] } ], [#Rule 127 'ident', 3, sub { push(@{$_[1]}, map {($_, 0)} split(/\./, $_[3])); $_[1]; } ], [#Rule 128 'ident', 1, undef ], [#Rule 129 'node', 1, sub { [ $_[1], 0 ] } ], [#Rule 130 'node', 4, sub { [ $_[1], $factory->args($_[3]) ] } ], [#Rule 131 'item', 1, sub { "'$_[1]'" } ], [#Rule 132 'item', 3, sub { $_[2] } ], [#Rule 133 'item', 2, sub { $_[0]->{ V1DOLLAR } ? "'$_[2]'" : $factory->ident(["'$_[2]'", 0]) } ], [#Rule 134 'expr', 3, sub { "$_[1] $_[2] $_[3]" } ], [#Rule 135 'expr', 3, sub { "$_[1] $_[2] $_[3]" } ], [#Rule 136 'expr', 3, sub { "$_[1] $_[2] $_[3]" } ], [#Rule 137 'expr', 3, sub { "int($_[1] / $_[3])" } ], [#Rule 138 'expr', 3, sub { "$_[1] % $_[3]" } ], [#Rule 139 'expr', 3, sub { "$_[1] $CMPOP{ $_[2] } $_[3]" } ], [#Rule 140 'expr', 3, sub { "$_[1] + $_[3]" } ], [#Rule 141 'expr', 3, sub { "$_[1] && $_[3]" } ], [#Rule 142 'expr', 3, sub { "$_[1] || $_[3]" } ], [#Rule 143 'expr', 2, sub { "! $_[2]" } ], [#Rule 144 'expr', 5, sub { "$_[1] ? $_[3] : $_[5]" } ], [#Rule 145 'expr', 3, sub { $factory->assign(@{$_[2]}) } ], [#Rule 146 'expr', 3, sub { "($_[2])" } ], [#Rule 147 'expr', 1, undef ], [#Rule 148 'setlist', 2, sub { push(@{$_[1]}, @{$_[2]}); $_[1] } ], [#Rule 149 'setlist', 2, undef ], [#Rule 150 'setlist', 1, undef ], [#Rule 151 'assign', 3, sub { [ $_[1], $_[3] ] } ], [#Rule 152 'assign', 3, sub { [ @_[1,3] ] } ], [#Rule 153 'args', 2, sub { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 154 'args', 2, sub { push(@{$_[1]->[0]}, $_[2]); $_[1] } ], [#Rule 155 'args', 4, sub { push(@{$_[1]->[0]}, "'', " . $factory->assign(@_[2,4])); $_[1] } ], [#Rule 156 'args', 2, sub { $_[1] } ], [#Rule 157 'args', 0, sub { [ [ ] ] } ], [#Rule 158 'lnameargs', 3, sub { push(@{$_[3]}, $_[1]); $_[3] } ], [#Rule 159 'lnameargs', 1, undef ], [#Rule 160 'lvalue', 1, undef ], [#Rule 161 'lvalue', 3, sub { $factory->quoted($_[2]) } ], [#Rule 162 'lvalue', 1, undef ], [#Rule 163 'nameargs', 3, sub { [ [$factory->ident($_[2])], $_[3] ] } ], [#Rule 164 'nameargs', 2, sub { [ @_[1,2] ] } ], [#Rule 165 'nameargs', 4, sub { [ @_[1,3] ] } ], [#Rule 166 'names', 3, sub { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 167 'names', 1, sub { [ $_[1] ] } ], [#Rule 168 'name', 3, sub { $factory->quoted($_[2]) } ], [#Rule 169 'name', 1, sub { "'$_[1]'" } ], [#Rule 170 'name', 1, undef ], [#Rule 171 'filename', 3, sub { "$_[1].$_[3]" } ], [#Rule 172 'filename', 1, undef ], [#Rule 173 'filepart', 1, undef ], [#Rule 174 'filepart', 1, undef ], [#Rule 175 'filepart', 1, undef ], [#Rule 176 'quoted', 2, sub { push(@{$_[1]}, $_[2]) if defined $_[2]; $_[1] } ], [#Rule 177 'quoted', 0, sub { [ ] } ], [#Rule 178 'quotable', 1, sub { $factory->ident($_[1]) } ], [#Rule 179 'quotable', 1, sub { $factory->text($_[1]) } ], [#Rule 180 'quotable', 1, sub { undef } ] ]; 1; } # # Inline include of Jemplate/Parser.pm # BEGIN { $INC{'Jemplate/Parser.pm'} = 'dummy/Jemplate/Parser.pm'; } BEGIN { #line 0 "Jemplate/Parser.pm" package Jemplate::Parser; use strict; use warnings; use base 'Template::Parser'; use Jemplate::Grammar; use Jemplate::Directive; sub new { my $class = shift; my $parser = $class->SUPER::new( GRAMMAR => Jemplate::Grammar->new(), FACTORY => 'Jemplate::Directive', @_, ); # flags passed from Jemplate object my %args = @_; # eval-javascript is default "on" $parser->{EVAL_JAVASCRIPT} = exists $args{EVAL_JAVASCRIPT} ? $args{EVAL_JAVASCRIPT} : 1; # tie the parser state-variable to the global Directive var $parser->{INJAVASCRIPT} = \$Jemplate::Directive::INJAVASCRIPT; return $parser; } 1; } # # Inline include of Jemplate/Runtime.pm # BEGIN { $INC{'Jemplate/Runtime.pm'} = 'dummy/Jemplate/Runtime.pm'; } BEGIN { #line 0 "Jemplate/Runtime.pm" package Jemplate::Runtime; use strict; use warnings; sub main { return &kernel } sub kernel { <<'...'; /*------------------------------------------------------------------------------ Jemplate - Template Toolkit for JavaScript DESCRIPTION - This module provides the runtime JavaScript support for compiled Jemplate templates. AUTHOR - Ingy döt Net Copyright 2006,2008 Ingy döt Net. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ------------------------------------------------------------------------------*/ //------------------------------------------------------------------------------ // Main Jemplate class //------------------------------------------------------------------------------ if (typeof Jemplate == 'undefined') { var Jemplate = function() { this.init.apply(this, arguments); }; } Jemplate.VERSION = '0.22'; Jemplate.process = function() { var jemplate = new Jemplate(Jemplate.prototype.config); return jemplate.process.apply(jemplate, arguments); } ;(function(){ if (! Jemplate.templateMap) Jemplate.templateMap = {}; var proto = Jemplate.prototype = {}; proto.config = { AUTO_RESET: true, BLOCKS: {}, CONTEXT: null, DEBUG_UNDEF: false, DEFAULT: null, ERROR: null, EVAL_JAVASCRIPT: false, GLOBAL : true, SCOPE : this, FILTERS: {}, INCLUDE_PATH: [''], INTERPOLATE: false, OUTPUT: null, PLUGINS: {}, POST_PROCESS: [], PRE_PROCESS: [], PROCESS: null, RECURSION: false, STASH: null, TOLERANT: null, VARIABLES: {}, WRAPPER: [] }; proto.defaults = { AUTO_RESET: true, BLOCKS: {}, CONTEXT: null, DEBUG_UNDEF: false, DEFAULT: null, ERROR: null, EVAL_JAVASCRIPT: false, GLOBAL : true, SCOPE : this, INCLUDE_PATH: [''], INTERPOLATE: false, OUTPUT: null, PLUGINS: {}, POST_PROCESS: [], PRE_PROCESS: [], PROCESS: null, RECURSION: false, STASH: null, TOLERANT: null, VARIABLES: {}, WRAPPER: [] }; Jemplate.init = function(config) { Jemplate.prototype.config = config || {}; for (var i in Jemplate.prototype.defaults) { if(typeof Jemplate.prototype.config[i] == "undefined") { Jemplate.prototype.config[i] = Jemplate.prototype.defaults[i]; } } } proto.init = function(config) { this.config = config || {}; for (var i in Jemplate.prototype.defaults) { if(typeof this.config[i] == "undefined") { this.config[i] = Jemplate.prototype.defaults[i]; } } } proto.process = function(template, data, output) { var context = this.config.CONTEXT || new Jemplate.Context(); context.config = this.config; context.stash = new Jemplate.Stash(this.config.STASH, this.config); context.__filter__ = new Jemplate.Filter(); context.__filter__.config = this.config; context.__plugin__ = new Jemplate.Plugin(); context.__plugin__.config = this.config; var result; var proc = function(input) { try { if (typeof context.config.PRE_PROCESS == 'string') context.config.PRE_PROCESS = [context.config.PRE_PROCESS]; for (var i = 0; i < context.config.PRE_PROCESS.length; i++) { context.process(context.config.PRE_PROCESS[i]); } result = context.process(template, input); if (typeof context.config.POST_PROCESS == 'string') context.config.PRE_PROCESS = [context.config.POST_PROCESS]; for (i = 0; i < context.config.POST_PROCESS.length; i++) { context.process(context.config.POST_PROCESS[i]); } } catch(e) { if (! String(e).match(/Jemplate\.STOP\n/)) throw(e); result = e.toString().replace(/Jemplate\.STOP\n/, ''); } if (typeof output == 'undefined') return result; if (typeof output == 'function') { output(result); return null; } if (typeof(output) == 'string' || output instanceof String) { if (output.match(/^#[\w\-]+$/)) { var id = output.replace(/^#/, ''); var element = document.getElementById(id); if (typeof element == 'undefined') throw('No element found with id="' + id + '"'); element.innerHTML = result; return null; } } else { output.innerHTML = result; return null; } throw("Invalid arguments in call to Jemplate.process"); return 1; } if (typeof data == 'function') data = data(); else if (typeof data == 'string') { // Jemplate.Ajax.get(data, function(r) { proc(Jemplate.JSON.parse(r)) }); var url = data; Jemplate.Ajax.processGet(url, function(data) { proc(data) }); return null; } return proc(data); } //------------------------------------------------------------------------------ // Jemplate.Context class //------------------------------------------------------------------------------ if (typeof Jemplate.Context == 'undefined') Jemplate.Context = function() {}; proto = Jemplate.Context.prototype; proto.include = function(template, args) { return this.process(template, args, true); } proto.process = function(template, args, localise) { if (localise) this.stash.clone(args); else this.stash.update(args); var func = Jemplate.templateMap[template]; if (typeof func == 'undefined') throw('No Jemplate template named "' + template + '" available'); var output = func(this); if (localise) this.stash.declone(); return output; } proto.set_error = function(error, output) { this._error = [error, output]; return error; } proto.plugin = function(name, args) { if (typeof name == 'undefined') throw "Unknown plugin name ':" + name + "'"; // The Context object (this) is passed as the first argument to the plugin. var func = eval(name); return new func(this, args); } proto.filter = function(text, name, args) { if (name == 'null') name = "null_filter"; if (typeof this.__filter__.filters[name] == "function") return this.__filter__.filters[name](text, args, this); else throw "Unknown filter name ':" + name + "'"; } //------------------------------------------------------------------------------ // Jemplate.Plugin class //------------------------------------------------------------------------------ if (typeof Jemplate.Plugin == 'undefined') { Jemplate.Plugin = function() { }; } proto = Jemplate.Plugin.prototype; proto.plugins = {}; //------------------------------------------------------------------------------ // Jemplate.Filter class //------------------------------------------------------------------------------ if (typeof Jemplate.Filter == 'undefined') { Jemplate.Filter = function() { }; } proto = Jemplate.Filter.prototype; proto.filters = {}; proto.filters.null_filter = function(text) { return ''; } proto.filters.upper = function(text) { return text.toUpperCase(); } proto.filters.lower = function(text) { return text.toLowerCase(); } proto.filters.ucfirst = function(text) { var first = text.charAt(0); var rest = text.substr(1); return first.toUpperCase() + rest; } proto.filters.lcfirst = function(text) { var first = text.charAt(0); var rest = text.substr(1); return first.toLowerCase() + rest; } proto.filters.trim = function(text) { return text.replace( /^\s+/g, "" ).replace( /\s+$/g, "" ); } proto.filters.collapse = function(text) { return text.replace( /^\s+/g, "" ).replace( /\s+$/g, "" ).replace(/\s+/, " "); } proto.filters.html = function(text) { text = text.replace(/&/g, '&'); text = text.replace(//g, '>'); text = text.replace(/"/g, '"'); // " end quote for emacs return text; } proto.filters.html_para = function(text) { var lines = text.split(/(?:\r?\n){2,}/); return "

\n" + lines.join("\n

\n\n

\n") + "

\n"; } proto.filters.html_break = function(text) { return text.replace(/(\r?\n){2,}/g, "$1
$1
$1"); } proto.filters.html_line_break = function(text) { return text.replace(/(\r?\n)/g, "$1
$1"); } proto.filters.uri = function(text) { return encodeURIComponent(text); } proto.filters.url = function(text) { return encodeURI(text); } proto.filters.indent = function(text, args) { var pad = args[0]; if (! text) return null; if (typeof pad == 'undefined') pad = 4; var finalpad = ''; if (typeof pad == 'number' || String(pad).match(/^\d$/)) { for (var i = 0; i < pad; i++) { finalpad += ' '; } } else { finalpad = pad; } var output = text.replace(/^/gm, finalpad); return output; } proto.filters.truncate = function(text, args) { var len = args[0]; if (! text) return null; if (! len) len = 32; // This should probably be <=, but TT just uses < if (text.length < len) return text; var newlen = len - 3; return text.substr(0,newlen) + '...'; } proto.filters.repeat = function(text, iter) { if (! text) return null; if (! iter || iter == 0) iter = 1; if (iter == 1) return text var output = text; for (var i = 1; i < iter; i++) { output += text; } return output; } proto.filters.replace = function(text, args) { if (! text) return null; var re_search = args[0]; var text_replace = args[1]; if (! re_search) re_search = ''; if (! text_replace) text_replace = ''; var re = new RegExp(re_search, 'g'); return text.replace(re, text_replace); } //------------------------------------------------------------------------------ // Jemplate.Stash class //------------------------------------------------------------------------------ if (typeof Jemplate.Stash == 'undefined') { Jemplate.Stash = function(stash, config) { this.__config__ = config; this.data = { GLOBAL : this.__config__.SCOPE }; this.LOCAL_ANCHOR = {}; this.data.LOCAL = this.LOCAL_ANCHOR; this.update(stash); }; } proto = Jemplate.Stash.prototype; proto.clone = function(args) { var data = this.data; this.data = { GLOBAL : this.__config__.SCOPE }; this.data.LOCAL = this.LOCAL_ANCHOR; this.update(data); this.update(args); this.data._PARENT = data; } proto.declone = function(args) { this.data = this.data._PARENT || this.data; } proto.update = function(args) { if (typeof args == 'undefined') return; for (var key in args) { if (key != 'GLOBAL' && key != 'LOCAL') { this.set(key, args[key]); } } } proto.get = function(ident, args) { var root = this.data; var value; if ( (ident instanceof Array) || (typeof ident == 'string' && /\./.test(ident) ) ) { if (typeof ident == 'string') { ident = ident.split('.'); var newIdent = []; for (var i = 0; i < ident.length; i++) { newIdent.push(ident.replace(/\(.*$/,'')); newIdent.push(0); } ident = newIdent; } for (var i = 0; i < ident.length; i += 2) { var dotopArgs = ident.slice(i, i+2); dotopArgs.unshift(root); value = this._dotop.apply(this, dotopArgs); if (typeof value == 'undefined') break; root = value; } } else { value = this._dotop(root, ident, args); } if (typeof value == 'undefined' || value == null) { if (this.__config__.DEBUG_UNDEF) throw("undefined value found while using DEBUG_UNDEF"); value = ''; } return value; } proto.set = function(ident, value, set_default) { var root, result, error; root = this.data; while (true) { if ( (ident instanceof Array) || (typeof ident == 'string' && /\./.test(ident) ) ) { if (typeof ident == 'string') { ident = ident.split('.'); var newIdent = []; for (var i = 0; i < ident.length; i++) { newIdent.push(ident.replace(/\(.*$/,'')); newIdent.push(0); } ident = newIdent; } for (var i = 0; i < ident.length - 2; i += 2) { var dotopArgs = ident.slice(i, i+2); dotopArgs.unshift(root); dotopArgs.push(1); result = this._dotop.apply(this, dotopArgs); if (typeof value == 'undefined') break; root = result; } var assignArgs = ident.slice(ident.length-2, ident.length); assignArgs.unshift(root); assignArgs.push(value); assignArgs.push(set_default); result = this._assign.apply(this, assignArgs); } else { result = this._assign(root, ident, 0, value, set_default); } break; } return (typeof result != 'undefined') ? result : ''; } proto._dotop = function(root, item, args, lvalue) { if (root == this.LOCAL_ANCHOR) root = this.data; var atroot = root == this.data; var value,result = undefined; var is_function_call = args instanceof Array; args = args || []; if (typeof root == 'undefined' || typeof item == 'undefined' || typeof item == 'string' && item.match(/^[\._]/)) { return undefined; } if (atroot || root.constructor == Object || root == this.data.GLOBAL) { if (typeof root[item] != 'undefined' && root[item] != null && (!is_function_call || !this.hash_functions[item])) { //consider undefined == null if (typeof root[item] == 'function') { result = root[item].apply(root,args); } else { return root[item]; } } /*else if (atroot && typeof this.data.GLOBAL[item] != 'undefined' && this.__config__.GLOBAL && item != 'LOCAL' ) { if (typeof this.data.GLOBAL[item] == 'function' ) { result = this.data.GLOBAL[item].apply(root,args); } else { return this.data.GLOBAL[item]; } }*/ else if (lvalue) { return root[item] = {}; } else if (this.hash_functions[item] && !atroot || item == 'import') { args.unshift(root); result = this.hash_functions[item].apply(this,args); } else if (item instanceof Array) { result = {}; for (var i = 0; i < item.length; i++) result[item[i]] = root[item[i]]; return result; } } else if (root instanceof Array) { if (this.list_functions[item]) { args.unshift(root); result = this.list_functions[item].apply(this,args); } else if (typeof item == 'string' && /^-?\d+$/.test(item) || typeof item == 'number' ) { if (typeof root[item] != 'function') return root[item]; result = root[item].apply(this, args); } else if (item instanceof Array) { for (var i = 0; i < item.length; i++) result.push(root[item[i]]); return result; } } else if ( (root.constructor != Object) && (root instanceof Object) ) { //this section was proposed for calling method on blessed reference in Perl //not sure how well it is playing with javascript try { result = root[item].apply(root,args); } catch (e) { var my_class = root.constructor.name; if (false) throw "Cant locate method"; if (root instanceof Array) { if (this.list_functions[item]) { args.unshift(root); result = this.list_functions[item].apply(this,args); } else if (typeof item == 'string' && /^-?\d+$/.test(item) || typeof item == 'number' ) { if (typeof root[item] != 'function') return root[item]; result = root[item].apply(this, args); } else if (item instanceof Array) { for (var i = 0; i < item.length; i++) result.push(root[item[i]]); return result; } } else if (typeof root == 'object') { if (typeof root[item] != 'undefined' && root[item] != null) {//consider undefined == null if (typeof root[item] == 'function') { result = root[item].apply(this,args); } else { return root[item]; } } else if (this.hash_functions[item]) { args.unshift(root); result = this.hash_functions[item].apply(this,args); } } else if (this.string_functions[item]) { args.unshift(root); result = this.string_functions[item].apply(this, args); } else if (this.list_functions[item]) { args.unshift([root]); result = this.list_functions[item].apply(this,args); } } } else if (this.string_functions[item] && !lvalue) { args.unshift(root); result = this.string_functions[item].apply(this, args); } else if (this.list_functions[item] && !lvalue) { args.unshift([root]); result = this.list_functions[item].apply(this,args); } else { result = undefined; } if (result instanceof Array) { if (typeof result[0] == 'undefined' && typeof result[1] != 'undefined') { throw result[1]; } } return result; } proto._assign = function(root, item, args, value, set_default) { var atroot = root == this.data; var result; args = args || []; if (typeof root == 'undefined' || typeof item == 'undefined' || typeof item == 'string' && item.match(/^[\._]/)) { return undefined; } if (atroot || root.constructor == Object || root == this.data.GLOBAL) { // if (atroot && this.__config__.GLOBAL && typeof root[item] == 'undefined' && typeof this.data.GLOBAL[item] != 'undefined' && !set_default) { // return this.data.GLOBAL[item] = value; // } if (root == this.LOCAL_ANCHOR) root = this.data; if (!(set_default && typeof root[item] != 'undefined')) { if (atroot && item == 'GLOBAL') throw "Attempt to modify GLOBAL access modifier" if (atroot && item == 'LOCAL') throw "Attempt to modify LOCAL access modifier" return root[item] = value; } } else if ((root instanceof Array) && (typeof item == 'string' && /^-?\d+$/.test(item) || typeof item == 'number' )) { if (!(set_default && typeof root[item] != 'undefined')) { return root[item] = value; } } else if ( (root.constructor != Object) && (root instanceof Object) ) { try { result = root[item].apply(root,args); } catch (e) { } } else { throw 'dont know how to assign to [' + root + '.' + item +']'; } return undefined; } proto.string_functions = {}; // typeof proto.string_functions['typeof'] = function(value) { return typeof value; } // chunk(size) negative size chunks from end proto.string_functions.chunk = function(string, size) { //var size = args; var list = new Array(); if (! size) size = 1; if (size < 0) { size = 0 - size; for (var i = string.length - size; i >= 0; i = i - size) list.unshift(string.substr(i, size)); if (string.length % size) list.unshift(string.substr(0, string.length % size)); } else for (i = 0; i < string.length; i = i + size) list.push(string.substr(i, size)); return list; } // defined is value defined? proto.string_functions.defined = function(string) { return 1; } // hash treat as single-element hash with key value proto.string_functions.hash = function(string) { return { 'value': string }; } // length length of string representation proto.string_functions.length = function(string) { return string.length; } // list treat as single-item list proto.string_functions.list = function(string) { return [ string ]; } // match(re) get list of matches proto.string_functions.match = function(string, re, modifiers) { var regexp = new RegExp(re, modifiers); var list = string.match(regexp); return list; } // repeat(n) repeated n times proto.string_functions.repeat = function(string, args) { var n = args || 1; var output = ''; for (var i = 0; i < n; i++) { output += string; } return output; } // replace(re, sub, global) replace instances of re with sub proto.string_functions.replace = function(string, re, sub, modifiers) { var regexp = new RegExp(re,modifiers); if (! sub) sub = ''; return string.replace(regexp, sub); } // search(re) true if value matches re proto.string_functions.search = function(string, re) { var regexp = new RegExp(re); return (string.search(regexp) >= 0) ? 1 : 0; } // size returns 1, as if a single-item list proto.string_functions.size = function(string) { return 1; } // split(re) split string on re proto.string_functions.split = function(string, re) { var regexp = new RegExp(re); var list = string.split(regexp); return list; } proto.list_functions = {}; // typeof proto.list_functions['typeof'] = function(list) { return 'array'; }; proto.list_functions.list = function(list) { return list; }; proto.list_functions.join = function(list, str) { return list.join(str); }; proto.list_functions.sort = function(list,key) { if( typeof(key) != 'undefined' && key != "" ) { // we probably have a list of hashes // and need to sort based on hash key return list.sort( function(a,b) { if( a[key] == b[key] ) { return 0; } else if( a[key] > b[key] ) { return 1; } else { return -1; } } ); } return list.sort(); } proto.list_functions.nsort = function(list) { return list.sort(function(a, b) { return (a-b) }); } proto.list_functions.grep = function(list, re) { var regexp = new RegExp(re); var result = []; for (var i = 0; i < list.length; i++) { if (list[i].match(regexp)) result.push(list[i]); } return result; } proto.list_functions.unique = function(list) { var result = []; var seen = {}; for (var i = 0; i < list.length; i++) { var elem = list[i]; if (! seen[elem]) result.push(elem); seen[elem] = true; } return result; } proto.list_functions.reverse = function(list) { var result = []; for (var i = list.length - 1; i >= 0; i--) { result.push(list[i]); } return result; } proto.list_functions.merge = function(list /*, ... args */) { var result = []; var push_all = function(elem) { if (elem instanceof Array) { for (var j = 0; j < elem.length; j++) { result.push(elem[j]); } } else { result.push(elem); } } push_all(list); for (var i = 1; i < arguments.length; i++) { push_all(arguments[i]); } return result; } proto.list_functions.slice = function(list, start, end) { return list.slice(start, end); } proto.list_functions.splice = function(list /*, ... args */ ) { var args = Array.prototype.slice.call(arguments); args.shift(); return list.splice.apply(list,args); } proto.list_functions.push = function(list, value) { list.push(value); return list; } proto.list_functions.pop = function(list) { return list.pop(); } proto.list_functions.unshift = function(list, value) { list.unshift(value); return list; } proto.list_functions.shift = function(list) { return list.shift(); } proto.list_functions.first = function(list) { return list[0]; } proto.list_functions.size = function(list) { return list.length; } proto.list_functions.max = function(list) { return list.length - 1; } proto.list_functions.last = function(list) { return list.slice(-1); } proto.hash_functions = {}; // typeof proto.hash_functions['typeof'] = function(hash) { return 'object'; }; // each list of alternating keys/values proto.hash_functions.each = function(hash) { var list = new Array(); for ( var key in hash ) list.push(key, hash[key]); return list; } // exists(key) does key exist? proto.hash_functions.exists = function(hash, key) { return ( typeof( hash[key] ) == "undefined" ) ? 0 : 1; } // import(hash2) import contents of hash2 // import import into current namespace hash proto.hash_functions['import'] = function(hash, hash2) { for ( var key in hash2 ) hash[key] = hash2[key]; return ''; } // keys list of keys proto.hash_functions.keys = function(hash) { var list = new Array(); for ( var key in hash ) list.push(key); return list; } // list returns alternating key, value proto.hash_functions.list = function(hash, what) { //var what = ''; //if ( args ) //what = args[0]; var list = new Array(); var key; if (what == 'keys') for ( key in hash ) list.push(key); else if (what == 'values') for ( key in hash ) list.push(hash[key]); else if (what == 'each') for ( key in hash ) list.push(key, hash[key]); else for ( key in hash ) list.push({ 'key': key, 'value': hash[key] }); return list; } // nsort keys sorted numerically proto.hash_functions.nsort = function(hash) { var list = new Array(); for (var key in hash) list.push(key); return list.sort(function(a, b) { return (a-b) }); } // size number of pairs proto.hash_functions.size = function(hash) { var size = 0; for (var key in hash) size++; return size; } // sort keys sorted alphabetically proto.hash_functions.sort = function(hash) { var list = new Array(); for (var key in hash) list.push(key); return list.sort(); } // values list of values proto.hash_functions.values = function(hash) { var list = new Array(); for ( var key in hash ) list.push(hash[key]); return list; } // delete proto.hash_functions.remove = function(hash, key) { return delete hash[key]; } proto.hash_functions['delete'] = proto.hash_functions.remove; //------------------------------------------------------------------------------ // Jemplate.Iterator class //------------------------------------------------------------------------------ if (typeof Jemplate.Iterator == 'undefined') { Jemplate.Iterator = function(object) { if( object instanceof Array ) { this.object = object; this.size = object.length; this.max = this.size -1; } else if ( object instanceof Object ) { this.object = object; var object_keys = new Array; for( var key in object ) { object_keys[object_keys.length] = key; } this.object_keys = object_keys.sort(); this.size = object_keys.length; this.max = this.size -1; } else if (typeof object == 'undefined' || object == null || object == '') { this.object = null; this.max = -1; } } } proto = Jemplate.Iterator.prototype; proto.get_first = function() { this.index = 0; this.first = 1; this.last = 0; this.count = 1; return this.get_next(1); } proto.get_next = function(should_init) { var object = this.object; var index; if( typeof(should_init) != 'undefined' && should_init ) { index = this.index; } else { index = ++this.index; this.first = 0; this.count = this.index + 1; if( this.index == this.size -1 ) { this.last = 1; } } if (typeof object == 'undefined') throw('No object to iterate'); if( this.object_keys ) { if (index < this.object_keys.length) { this.prev = index > 0 ? this.object_keys[index - 1] : ""; this.next = index < this.max ? this.object_keys[index + 1] : ""; return [this.object_keys[index], false]; } } else { if (index <= this.max) { this.prev = index > 0 ? object[index - 1] : ""; this.next = index < this.max ? object[index +1] : ""; return [object[index], false]; } } return [null, true]; } var stubExplanation = "stub that doesn't do anything. Try including the jQuery, YUI, or XHR option when building the runtime"; Jemplate.Ajax = { get: function(url, callback) { throw("This is a Jemplate.Ajax.get " + stubExplanation); }, processGet: function(url, callback) { throw("This is a Jemplate.Ajax.processGet " + stubExplanation); }, post: function(url, callback) { throw("This is a Jemplate.Ajax.post " + stubExplanation); } }; Jemplate.JSON = { parse: function(decodeValue) { throw("This is a Jemplate.JSON.parse " + stubExplanation); }, stringify: function(encodeValue) { throw("This is a Jemplate.JSON.stringify " + stubExplanation); } }; }()); ... } sub ajax_jquery { <<'...'; ;(function(){ Jemplate.Ajax = { get: function(url, callback) { jQuery.get(url, null, callback); }, processGet: function(url, processor) { jQuery.getJSON(url, null, processor); }, post: function(url, data, callback) { jQuery.post(url, data, callback); } }; }()); ... } sub ajax_xhr { <<'...'; ;(function(){ Jemplate.Ajax = { get: function(url, callback) { var request = new XMLHttpRequest(); request.open('GET', url, Boolean(callback)); request.setRequestHeader('Accept', 'text/json; text/x-json; application/json'); return this.request(request, null, callback); }, processGet: function(url, processor) { this.get(url, function(responseText){ processor(Jemplate.JSON.parse(responseText)); }); }, post: function(url, data, callback) { var request = new XMLHttpRequest(); request.open('POST', url, Boolean(callback)); request.setRequestHeader('Accept', 'text/json; text/x-json; application/json'); request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' ); return this.request(request, data, callback); }, request: function(request, data, callback) { if (callback) { request.onreadystatechange = function() { if (request.readyState == 4) { if(request.status == 200) callback(request.responseText); } }; } request.send(data); if (!callback) { if (request.status != 200) throw('Request for "' + url + '" failed with status: ' + request.status); return request.responseText; } return null; } }; }()); ... } sub ajax_yui { <<'...'; ;(function(){ Jemplate.Ajax = { get: function(url, callback) { if (typeof callback == "function") { callback = { success: callback }; } YAHOO.connect.asyncRequest("GET", url, callback); }, processGet: function(url, processor) { this.get(url, function(responseText){ processor(YAHOO.lang.JSON.parse(responseText)); }); }, post: function(url, data, callback) { if (typeof callback == "function") { callback = { success: callback }; } YAHOO.connect.asyncRequest("POST", url, callback, data); } }; }()); ... } sub json_json2 { <<'...'; ;(function(){ Jemplate.JSON = { parse: function(encoded) { return JSON.parse(encoded); }, stringify: function(decoded) { return JSON.stringify(decoded); } }; }()); ... } sub json_json2_internal { <<'...'; ;(function(){ var JSON; /* json2.js 2008-03-24 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This file creates a global JSON object containing three methods: stringify, parse, and quote. JSON.stringify(value, replacer, space) value any JavaScript value, usually an object or array. replacer an optional parameter that determines how object values are stringified for objects without a toJSON method. It can be a function or an array. space an optional parameter that specifies the indentation of nested structures. If it is omitted, the text will be packed without extra whitespace. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t'), it contains the characters used to indent at each level. This method produces a JSON text from a JavaScript value. When an object value is found, if the object contains a toJSON method, its toJSON method with be called and the result will be stringified. A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key associated with the value, and this will be bound to the object holding the key. This is the toJSON method added to Dates: function toJSON(key) { return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; } You can provide an optional replacer method. It will be passed the key and value of each member, with this bound to the containing object. The value that is returned from your method will be serialized. If your method returns undefined, then the member will be excluded from the serialization. If no replacer parameter is provided, then a default replacer will be used: function replacer(key, value) { return Object.hasOwnProperty.call(this, key) ? value : undefined; } The default replacer is passed the key and value for each item in the structure. It excludes inherited members. If the replacer parameter is an array, then it will be used to select the members to be serialized. It filters the results such that only members with keys listed in the replacer array are stringified. Values that do not have JSON representaions, such as undefined or functions, will not be serialized. Such values in objects will be dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a stringification of the value that is filled with line breaks and indentation to make it easier to read. If the space parameter is a non-empty string, then that string will be used for indentation. If the space parameter is a number, then then indentation will be that many spaces. Example: text = JSON.stringify(['e', {pluribus: 'unum'}]); // text is '["e",{"pluribus":"unum"}]' text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' JSON.parse(text, reviver) This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The optional reviver parameter is a function that can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then structure is not modified. If it returns undefined then the member is deleted. Example: // Parse the text. Values that look like ISO date strings will // be converted to Date objects. myData = JSON.parse(text, function (key, value) { var a; if (typeof value === 'string') { a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; }); JSON.quote(text) This method wraps a string in quotes, escaping some characters as needed. This is a reference implementation. You are free to copy, modify, or redistribute. USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD THIRD PARTY CODE INTO YOUR PAGES. */ /*jslint regexp: true, forin: true, evil: true */ /*global JSON */ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, floor, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, length, parse, propertyIsEnumerable, prototype, push, quote, replace, stringify, test, toJSON, toString */ if (!JSON) var JSON; if (!JSON) { // Create a JSON object only if one does not already exist. We create the // object in a closure to avoid global variables. JSON = function () { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } Date.prototype.toJSON = function () { // Eventually, this method will be based on the date.toISOString method. return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape // sequences. return escapeable.test(string) ? '"' + string.replace(escapeable, function (a) { var c = meta[a]; if (typeof c === 'string') { return c; } c = a.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // If the object has a dontEnum length property, we'll treat it as an array. if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length'))) { // The object is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value, rep); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { v = str(k, value, rep); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } return null; } // Return the JSON object containing the stringify, parse, and quote methods. return { stringify: function (value, replacer, space) { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON text. The replacer can be a function // that can replace values, or an array of strings that will select the keys. // A default replacer method can be provided. Use of the space parameter can // produce text that is more easily readable. var i; gap = ''; indent = ''; if (space) { // If the space parameter is a number, make an indent string containing that // many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } // If the space parameter is a string, it will be used as the indent string. } else if (typeof space === 'string') { indent = space; } } // If there is no replacer parameter, use the default replacer. if (!replacer) { rep = function (key, value) { if (!Object.hasOwnProperty.call(this, key)) { return undefined; } return value; }; // The replacer can be a function or an array. Otherwise, throw an error. } else if (typeof replacer === 'function' || (typeof replacer === 'object' && typeof replacer.length === 'number')) { rep = replacer; } else { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', {'': value}); }, parse: function (text, reviver) { // The parse method takes a text and an optional reviver function, and returns // a JavaScript value if the text is a valid JSON text. var j; function walk(holder, key) { // The walk method is used to recursively walk the resulting structure so // that modifications can be made. var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } // Parsing happens in three stages. In the first stage, we run the text against // regular expressions that look for non-JSON patterns. We are especially // concerned with '()' and 'new' because they can cause invocation, and '=' // because it can cause mutation. But just to be safe, we want to reject all // unexpected forms. // We split the first stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace all backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@'). replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the second stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); // In the optional third stage, we recursively walk the new structure, passing // each name/value pair to a reviver function for possible transformation. return typeof reviver === 'function' ? walk({'': j}, '') : j; } // If the text is not JSON parseable, then a SyntaxError is thrown. throw new SyntaxError('JSON.parse'); }, quote: quote }; }(); } Jemplate.JSON = { parse: function(encoded) { return JSON.parse(encoded); }, stringify: function(decoded) { return JSON.stringify(decoded); } }; }()); ... } sub json_yui { <<'...'; ;(function(){ Jemplate.JSON = { parse: function(encoded) { return YAHOO.lang.JSON.parse(encoded); }, stringify: function(decoded) { return YAHOO.lang.JSON.stringify(decoded); } }; }()); ... } sub json2 { <<'...'; /* json2.js 2008-03-24 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This file creates a global JSON object containing three methods: stringify, parse, and quote. JSON.stringify(value, replacer, space) value any JavaScript value, usually an object or array. replacer an optional parameter that determines how object values are stringified for objects without a toJSON method. It can be a function or an array. space an optional parameter that specifies the indentation of nested structures. If it is omitted, the text will be packed without extra whitespace. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t'), it contains the characters used to indent at each level. This method produces a JSON text from a JavaScript value. When an object value is found, if the object contains a toJSON method, its toJSON method with be called and the result will be stringified. A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key associated with the value, and this will be bound to the object holding the key. This is the toJSON method added to Dates: function toJSON(key) { return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; } You can provide an optional replacer method. It will be passed the key and value of each member, with this bound to the containing object. The value that is returned from your method will be serialized. If your method returns undefined, then the member will be excluded from the serialization. If no replacer parameter is provided, then a default replacer will be used: function replacer(key, value) { return Object.hasOwnProperty.call(this, key) ? value : undefined; } The default replacer is passed the key and value for each item in the structure. It excludes inherited members. If the replacer parameter is an array, then it will be used to select the members to be serialized. It filters the results such that only members with keys listed in the replacer array are stringified. Values that do not have JSON representaions, such as undefined or functions, will not be serialized. Such values in objects will be dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a stringification of the value that is filled with line breaks and indentation to make it easier to read. If the space parameter is a non-empty string, then that string will be used for indentation. If the space parameter is a number, then then indentation will be that many spaces. Example: text = JSON.stringify(['e', {pluribus: 'unum'}]); // text is '["e",{"pluribus":"unum"}]' text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' JSON.parse(text, reviver) This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The optional reviver parameter is a function that can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then structure is not modified. If it returns undefined then the member is deleted. Example: // Parse the text. Values that look like ISO date strings will // be converted to Date objects. myData = JSON.parse(text, function (key, value) { var a; if (typeof value === 'string') { a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; }); JSON.quote(text) This method wraps a string in quotes, escaping some characters as needed. This is a reference implementation. You are free to copy, modify, or redistribute. USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD THIRD PARTY CODE INTO YOUR PAGES. */ /*jslint regexp: true, forin: true, evil: true */ /*global JSON */ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, floor, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, length, parse, propertyIsEnumerable, prototype, push, quote, replace, stringify, test, toJSON, toString */ if (!JSON) var JSON; if (!JSON) { // Create a JSON object only if one does not already exist. We create the // object in a closure to avoid global variables. JSON = function () { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } Date.prototype.toJSON = function () { // Eventually, this method will be based on the date.toISOString method. return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape // sequences. return escapeable.test(string) ? '"' + string.replace(escapeable, function (a) { var c = meta[a]; if (typeof c === 'string') { return c; } c = a.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // If the object has a dontEnum length property, we'll treat it as an array. if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length'))) { // The object is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value, rep); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { v = str(k, value, rep); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } return null; } // Return the JSON object containing the stringify, parse, and quote methods. return { stringify: function (value, replacer, space) { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON text. The replacer can be a function // that can replace values, or an array of strings that will select the keys. // A default replacer method can be provided. Use of the space parameter can // produce text that is more easily readable. var i; gap = ''; indent = ''; if (space) { // If the space parameter is a number, make an indent string containing that // many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } // If the space parameter is a string, it will be used as the indent string. } else if (typeof space === 'string') { indent = space; } } // If there is no replacer parameter, use the default replacer. if (!replacer) { rep = function (key, value) { if (!Object.hasOwnProperty.call(this, key)) { return undefined; } return value; }; // The replacer can be a function or an array. Otherwise, throw an error. } else if (typeof replacer === 'function' || (typeof replacer === 'object' && typeof replacer.length === 'number')) { rep = replacer; } else { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', {'': value}); }, parse: function (text, reviver) { // The parse method takes a text and an optional reviver function, and returns // a JavaScript value if the text is a valid JSON text. var j; function walk(holder, key) { // The walk method is used to recursively walk the resulting structure so // that modifications can be made. var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } // Parsing happens in three stages. In the first stage, we run the text against // regular expressions that look for non-JSON patterns. We are especially // concerned with '()' and 'new' because they can cause invocation, and '=' // because it can cause mutation. But just to be safe, we want to reject all // unexpected forms. // We split the first stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace all backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@'). replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the second stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); // In the optional third stage, we recursively walk the new structure, passing // each name/value pair to a reviver function for possible transformation. return typeof reviver === 'function' ? walk({'': j}, '') : j; } // If the text is not JSON parseable, then a SyntaxError is thrown. throw new SyntaxError('JSON.parse'); }, quote: quote }; }(); } ... } sub xhr_gregory { <<'...'; /* Cross-Browser XMLHttpRequest v1.2 ================================= Emulate Gecko 'XMLHttpRequest()' functionality in IE and Opera. Opera requires the Sun Java Runtime Environment . by Andrew Gregory http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/ This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. Attribution: Leave my name and web address in this script intact. Not Supported in Opera ---------------------- * user/password authentication * responseXML data member Not Fully Supported in Opera ---------------------------- * async requests * abort() * getAllResponseHeaders(), getAllResponseHeader(header) */ // IE support if (window.ActiveXObject && !window.XMLHttpRequest) { window.XMLHttpRequest = function() { var msxmls = new Array( 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'); for (var i = 0; i < msxmls.length; i++) { try { return new ActiveXObject(msxmls[i]); } catch (e) { } } return null; }; } // Gecko support /* ;-) */ // Opera support if (window.opera && !window.XMLHttpRequest) { window.XMLHttpRequest = function() { this.readyState = 0; // 0=uninitialized,1=loading,2=loaded,3=interactive,4=complete this.status = 0; // HTTP status codes this.statusText = ''; this._headers = []; this._aborted = false; this._async = true; this._defaultCharset = 'ISO-8859-1'; this._getCharset = function() { var charset = _defaultCharset; var contentType = this.getResponseHeader('Content-type').toUpperCase(); val = contentType.indexOf('CHARSET='); if (val != -1) { charset = contentType.substring(val); } val = charset.indexOf(';'); if (val != -1) { charset = charset.substring(0, val); } val = charset.indexOf(','); if (val != -1) { charset = charset.substring(0, val); } return charset; }; this.abort = function() { this._aborted = true; }; this.getAllResponseHeaders = function() { return this.getAllResponseHeader('*'); }; this.getAllResponseHeader = function(header) { var ret = ''; for (var i = 0; i < this._headers.length; i++) { if (header == '*' || this._headers[i].h == header) { ret += this._headers[i].h + ': ' + this._headers[i].v + '\n'; } } return ret; }; this.getResponseHeader = function(header) { var ret = getAllResponseHeader(header); var i = ret.indexOf('\n'); if (i != -1) { ret = ret.substring(0, i); } return ret; }; this.setRequestHeader = function(header, value) { this._headers[this._headers.length] = {h:header, v:value}; }; this.open = function(method, url, async, user, password) { this.method = method; this.url = url; this._async = true; this._aborted = false; this._headers = []; if (arguments.length >= 3) { this._async = async; } if (arguments.length > 3) { opera.postError('XMLHttpRequest.open() - user/password not supported'); } this.readyState = 1; if (this.onreadystatechange) { this.onreadystatechange(); } }; this.send = function(data) { if (!navigator.javaEnabled()) { alert("XMLHttpRequest.send() - Java must be installed and enabled."); return; } if (this._async) { setTimeout(this._sendasync, 0, this, data); // this is not really asynchronous and won't execute until the current // execution context ends } else { this._sendsync(data); } } this._sendasync = function(req, data) { if (!req._aborted) { req._sendsync(data); } }; this._sendsync = function(data) { this.readyState = 2; if (this.onreadystatechange) { this.onreadystatechange(); } // open connection var url = new java.net.URL(new java.net.URL(window.location.href), this.url); var conn = url.openConnection(); for (var i = 0; i < this._headers.length; i++) { conn.setRequestProperty(this._headers[i].h, this._headers[i].v); } this._headers = []; if (this.method == 'POST') { // POST data conn.setDoOutput(true); var wr = new java.io.OutputStreamWriter(conn.getOutputStream(), this._getCharset()); wr.write(data); wr.flush(); wr.close(); } // read response headers // NOTE: the getHeaderField() methods always return nulls for me :( var gotContentEncoding = false; var gotContentLength = false; var gotContentType = false; var gotDate = false; var gotExpiration = false; var gotLastModified = false; for (var i = 0; ; i++) { var hdrName = conn.getHeaderFieldKey(i); var hdrValue = conn.getHeaderField(i); if (hdrName == null && hdrValue == null) { break; } if (hdrName != null) { this._headers[this._headers.length] = {h:hdrName, v:hdrValue}; switch (hdrName.toLowerCase()) { case 'content-encoding': gotContentEncoding = true; break; case 'content-length' : gotContentLength = true; break; case 'content-type' : gotContentType = true; break; case 'date' : gotDate = true; break; case 'expires' : gotExpiration = true; break; case 'last-modified' : gotLastModified = true; break; } } } // try to fill in any missing header information var val; val = conn.getContentEncoding(); if (val != null && !gotContentEncoding) this._headers[this._headers.length] = {h:'Content-encoding', v:val}; val = conn.getContentLength(); if (val != -1 && !gotContentLength) this._headers[this._headers.length] = {h:'Content-length', v:val}; val = conn.getContentType(); if (val != null && !gotContentType) this._headers[this._headers.length] = {h:'Content-type', v:val}; val = conn.getDate(); if (val != 0 && !gotDate) this._headers[this._headers.length] = {h:'Date', v:(new Date(val)).toUTCString()}; val = conn.getExpiration(); if (val != 0 && !gotExpiration) this._headers[this._headers.length] = {h:'Expires', v:(new Date(val)).toUTCString()}; val = conn.getLastModified(); if (val != 0 && !gotLastModified) this._headers[this._headers.length] = {h:'Last-modified', v:(new Date(val)).toUTCString()}; // read response data var reqdata = ''; var stream = conn.getInputStream(); if (stream) { var reader = new java.io.BufferedReader(new java.io.InputStreamReader(stream, this._getCharset())); var line; while ((line = reader.readLine()) != null) { if (this.readyState == 2) { this.readyState = 3; if (this.onreadystatechange) { this.onreadystatechange(); } } reqdata += line + '\n'; } reader.close(); this.status = 200; this.statusText = 'OK'; this.responseText = reqdata; this.readyState = 4; if (this.onreadystatechange) { this.onreadystatechange(); } if (this.onload) { this.onload(); } } else { // error this.status = 404; this.statusText = 'Not Found'; this.responseText = ''; this.readyState = 4; if (this.onreadystatechange) { this.onreadystatechange(); } if (this.onerror) { this.onerror(); } } }; }; } // ActiveXObject emulation if (!window.ActiveXObject && window.XMLHttpRequest) { window.ActiveXObject = function(type) { switch (type.toLowerCase()) { case 'microsoft.xmlhttp': case 'msxml2.xmlhttp': case 'msxml2.xmlhttp.3.0': case 'msxml2.xmlhttp.4.0': case 'msxml2.xmlhttp.5.0': return new XMLHttpRequest(); } return null; }; } ... } sub xhr_ilinsky { <<'...'; // Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com) // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. (function () { // Save reference to earlier defined object implementation (if any) var oXMLHttpRequest = window.XMLHttpRequest; // Define on browser type var bGecko = !!window.controllers, bIE = window.document.all && !window.opera; // Constructor function cXMLHttpRequest() { this._object = oXMLHttpRequest ? new oXMLHttpRequest : new window.ActiveXObject('Microsoft.XMLHTTP'); }; // BUGFIX: Firefox with Firebug installed would break pages if not executed if (bGecko && oXMLHttpRequest.wrapped) cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped; // Constants cXMLHttpRequest.UNSENT = 0; cXMLHttpRequest.OPENED = 1; cXMLHttpRequest.HEADERS_RECEIVED = 2; cXMLHttpRequest.LOADING = 3; cXMLHttpRequest.DONE = 4; // Public Properties cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT; cXMLHttpRequest.prototype.responseText = ""; cXMLHttpRequest.prototype.responseXML = null; cXMLHttpRequest.prototype.status = 0; cXMLHttpRequest.prototype.statusText = ""; // Instance-level Events Handlers cXMLHttpRequest.prototype.onreadystatechange = null; // Class-level Events Handlers cXMLHttpRequest.onreadystatechange = null; cXMLHttpRequest.onopen = null; cXMLHttpRequest.onsend = null; cXMLHttpRequest.onabort = null; // Public Methods cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) { // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests this._async = bAsync; // Set the onreadystatechange handler var oRequest = this, nState = this.readyState; // BUGFIX: IE - memory leak on page unload (inter-page leak) if (bIE) { var fOnUnload = function() { if (oRequest._object.readyState != cXMLHttpRequest.DONE) fCleanTransport(oRequest); }; if (bAsync) window.attachEvent("onunload", fOnUnload); } this._object.onreadystatechange = function() { if (bGecko && !bAsync) return; // Synchronize state oRequest.readyState = oRequest._object.readyState; // fSynchronizeValues(oRequest); // BUGFIX: Firefox fires unneccesary DONE when aborting if (oRequest._aborted) { // Reset readyState to UNSENT oRequest.readyState = cXMLHttpRequest.UNSENT; // Return now return; } if (oRequest.readyState == cXMLHttpRequest.DONE) { // fCleanTransport(oRequest); // Uncomment this block if you need a fix for IE cache /* // BUGFIX: IE - cache issue if (!oRequest._object.getResponseHeader("Date")) { // Save object to cache oRequest._cached = oRequest._object; // Instantiate a new transport object cXMLHttpRequest.call(oRequest); // Re-send request oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword); oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0)); // Copy headers set if (oRequest._headers) for (var sHeader in oRequest._headers) if (typeof oRequest._headers[sHeader] == "string") // Some frameworks prototype objects with functions oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]); oRequest._object.onreadystatechange = function() { // Synchronize state oRequest.readyState = oRequest._object.readyState; if (oRequest._aborted) { // oRequest.readyState = cXMLHttpRequest.UNSENT; // Return return; } if (oRequest.readyState == cXMLHttpRequest.DONE) { // Clean Object fCleanTransport(oRequest); // get cached request if (oRequest.status == 304) oRequest._object = oRequest._cached; // delete oRequest._cached; // fSynchronizeValues(oRequest); // fReadyStateChange(oRequest); // BUGFIX: IE - memory leak in interrupted if (bIE && bAsync) window.detachEvent("onunload", fOnUnload); } }; oRequest._object.send(null); // Return now - wait untill re-sent request is finished return; }; */ // BUGFIX: IE - memory leak in interrupted if (bIE && bAsync) window.detachEvent("onunload", fOnUnload); } // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice if (nState != oRequest.readyState) fReadyStateChange(oRequest); nState = oRequest.readyState; }; // Add method sniffer if (cXMLHttpRequest.onopen) cXMLHttpRequest.onopen.apply(this, arguments); this._object.open(sMethod, sUrl, bAsync, sUser, sPassword); // BUGFIX: Gecko - missing readystatechange calls in synchronous requests if (!bAsync && bGecko) { this.readyState = cXMLHttpRequest.OPENED; fReadyStateChange(this); } }; cXMLHttpRequest.prototype.send = function(vData) { // Add method sniffer if (cXMLHttpRequest.onsend) cXMLHttpRequest.onsend.apply(this, arguments); // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard) if (vData && vData.nodeType) { vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml; if (!this._headers["Content-Type"]) this._object.setRequestHeader("Content-Type", "application/xml"); } this._object.send(vData); // BUGFIX: Gecko - missing readystatechange calls in synchronous requests if (bGecko && !this._async) { this.readyState = cXMLHttpRequest.OPENED; // Synchronize state fSynchronizeValues(this); // Simulate missing states while (this.readyState < cXMLHttpRequest.DONE) { this.readyState++; fReadyStateChange(this); // Check if we are aborted if (this._aborted) return; } } }; cXMLHttpRequest.prototype.abort = function() { // Add method sniffer if (cXMLHttpRequest.onabort) cXMLHttpRequest.onabort.apply(this, arguments); // BUGFIX: Gecko - unneccesary DONE when aborting if (this.readyState > cXMLHttpRequest.UNSENT) this._aborted = true; this._object.abort(); // BUGFIX: IE - memory leak fCleanTransport(this); }; cXMLHttpRequest.prototype.getAllResponseHeaders = function() { return this._object.getAllResponseHeaders(); }; cXMLHttpRequest.prototype.getResponseHeader = function(sName) { return this._object.getResponseHeader(sName); }; cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) { // BUGFIX: IE - cache issue if (!this._headers) this._headers = {}; this._headers[sName] = sValue; return this._object.setRequestHeader(sName, sValue); }; cXMLHttpRequest.prototype.toString = function() { return '[' + "object" + ' ' + "XMLHttpRequest" + ']'; }; cXMLHttpRequest.toString = function() { return '[' + "XMLHttpRequest" + ']'; }; // Helper function function fReadyStateChange(oRequest) { // Execute onreadystatechange if (oRequest.onreadystatechange) oRequest.onreadystatechange.apply(oRequest); // Sniffing code if (cXMLHttpRequest.onreadystatechange) cXMLHttpRequest.onreadystatechange.apply(oRequest); }; function fGetDocument(oRequest) { var oDocument = oRequest.responseXML; // Try parsing responseText if (bIE && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) { oDocument = new ActiveXObject('Microsoft.XMLDOM'); oDocument.loadXML(oRequest.responseText); } // Check if there is no error in document if (oDocument) if ((bIE && oDocument.parseError != 0) || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror")) return null; return oDocument; }; function fSynchronizeValues(oRequest) { try { oRequest.responseText = oRequest._object.responseText; } catch (e) {} try { oRequest.responseXML = fGetDocument(oRequest._object); } catch (e) {} try { oRequest.status = oRequest._object.status; } catch (e) {} try { oRequest.statusText = oRequest._object.statusText; } catch (e) {} }; function fCleanTransport(oRequest) { // BUGFIX: IE - memory leak (on-page leak) oRequest._object.onreadystatechange = new window.Function; // Delete private properties delete oRequest._headers; }; // Internet Explorer 5.0 (missing apply) if (!window.Function.prototype.apply) { window.Function.prototype.apply = function(oRequest, oArguments) { if (!oArguments) oArguments = []; oRequest.__func = this; oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]); delete oRequest.__func; }; }; // Register new object with window window.XMLHttpRequest = cXMLHttpRequest; })(); ... } sub xxx { <<'...'; //------------------------------------------------------------------------------ // Debugging Support //------------------------------------------------------------------------------ function XXX(msg) { if (! confirm(msg)) throw("terminated..."); return msg; } function JJJ(obj) { return XXX(JSON.stringify(obj)); } ... } 1; } # # Inline include of Jemplate/Runtime/Compact.pm # BEGIN { $INC{'Jemplate/Runtime/Compact.pm'} = 'dummy/Jemplate/Runtime/Compact.pm'; } BEGIN { #line 0 "Jemplate/Runtime/Compact.pm" package Jemplate::Runtime::Compact; use strict; use warnings; sub main { return &kernel } sub kernel { <<'...'; if(typeof Jemplate=="undefined"){var Jemplate=function(){this.init.apply(this,arguments)}}Jemplate.VERSION="0.22";Jemplate.process=function(){var A=new Jemplate(Jemplate.prototype.config);return A.process.apply(A,arguments)};(function(){if(!Jemplate.templateMap){Jemplate.templateMap={}}var proto=Jemplate.prototype={};proto.config={AUTO_RESET:true,BLOCKS:{},CONTEXT:null,DEBUG_UNDEF:false,DEFAULT:null,ERROR:null,EVAL_JAVASCRIPT:false,GLOBAL:true,SCOPE:this,FILTERS:{},INCLUDE_PATH:[""],INTERPOLATE:false,OUTPUT:null,PLUGINS:{},POST_PROCESS:[],PRE_PROCESS:[],PROCESS:null,RECURSION:false,STASH:null,TOLERANT:null,VARIABLES:{},WRAPPER:[]};proto.defaults={AUTO_RESET:true,BLOCKS:{},CONTEXT:null,DEBUG_UNDEF:false,DEFAULT:null,ERROR:null,EVAL_JAVASCRIPT:false,GLOBAL:true,SCOPE:this,INCLUDE_PATH:[""],INTERPOLATE:false,OUTPUT:null,PLUGINS:{},POST_PROCESS:[],PRE_PROCESS:[],PROCESS:null,RECURSION:false,STASH:null,TOLERANT:null,VARIABLES:{},WRAPPER:[]};Jemplate.init=function(config){Jemplate.prototype.config=config||{};for(var i in Jemplate.prototype.defaults){if(typeof Jemplate.prototype.config[i]=="undefined"){Jemplate.prototype.config[i]=Jemplate.prototype.defaults[i]}}};proto.init=function(config){this.config=config||{};for(var i in Jemplate.prototype.defaults){if(typeof this.config[i]=="undefined"){this.config[i]=Jemplate.prototype.defaults[i]}}};proto.process=function(template,data,output){var context=this.config.CONTEXT||new Jemplate.Context();context.config=this.config;context.stash=new Jemplate.Stash(this.config.STASH,this.config);context.__filter__=new Jemplate.Filter();context.__filter__.config=this.config;context.__plugin__=new Jemplate.Plugin();context.__plugin__.config=this.config;var result;var proc=function(input){try{if(typeof context.config.PRE_PROCESS=="string"){context.config.PRE_PROCESS=[context.config.PRE_PROCESS]}for(var i=0;i/g,">");text=text.replace(/"/g,""");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"

\n"+lines.join("\n

\n\n

\n")+"

\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1
$1
$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1
$1")};proto.filters.uri=function(text){return encodeURIComponent(text)};proto.filters.url=function(text){return encodeURI(text)};proto.filters.indent=function(text,args){var pad=args[0];if(!text){return null}if(typeof pad=="undefined"){pad=4}var finalpad="";if(typeof pad=="number"||String(pad).match(/^\d$/)){for(var i=0;i=0;i=i-size){list.unshift(string.substr(i,size))}if(string.length%size){list.unshift(string.substr(0,string.length%size))}}else{for(i=0;i=0)?1:0};proto.string_functions.size=function(string){return 1};proto.string_functions.split=function(string,re){var regexp=new RegExp(re);var list=string.split(regexp);return list};proto.list_functions={};proto.list_functions["typeof"]=function(list){return"array"};proto.list_functions.list=function(list){return list};proto.list_functions.join=function(list,str){return list.join(str)};proto.list_functions.sort=function(list,key){if(typeof (key)!="undefined"&&key!=""){return list.sort(function(a,b){if(a[key]==b[key]){return 0}else{if(a[key]>b[key]){return 1}else{return -1}}})}return list.sort()};proto.list_functions.nsort=function(list){return list.sort(function(a,b){return(a-b)})};proto.list_functions.grep=function(list,re){var regexp=new RegExp(re);var result=[];for(var i=0;i=0;i--){result.push(list[i])}return result};proto.list_functions.merge=function(list){var result=[];var push_all=function(elem){if(elem instanceof Array){for(var j=0;j0?this.object_keys[index-1]:"";this.next=index0?object[index-1]:"";this.next=index=3){this._async=D}if(arguments.length>3){opera.postError("XMLHttpRequest.open() - user/password not supported")}this.readyState=1;if(this.onreadystatechange){this.onreadystatechange()}};this.send=function(A){if(!navigator.javaEnabled()){alert("XMLHttpRequest.send() - Java must be installed and enabled.");return }if(this._async){setTimeout(this._sendasync,0,this,A)}else{this._sendsync(A)}};this._sendasync=function(A,B){if(!A._aborted){A._sendsync(B)}};this._sendsync=function(Q){this.readyState=2;if(this.onreadystatechange){this.onreadystatechange()}var F=new java.net.URL(new java.net.URL(window.location.href),this.url);var I=F.openConnection();for(var O=0;OC.UNSENT){this._aborted=true}this._object.abort();A(this)};C.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders()};C.prototype.getResponseHeader=function(I){return this._object.getResponseHeader(I)};C.prototype.setRequestHeader=function(I,J){if(!this._headers){this._headers={}}this._headers[I]=J;return this._object.setRequestHeader(I,J)};C.prototype.toString=function(){return"[object XMLHttpRequest]"};C.toString=function(){return"[XMLHttpRequest]"};function F(I){if(I.onreadystatechange){I.onreadystatechange.apply(I)}if(C.onreadystatechange){C.onreadystatechange.apply(I)}}function B(J){var I=J.responseXML;if(E&&I&&!I.documentElement&&J.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){I=new ActiveXObject("Microsoft.XMLDOM");I.loadXML(J.responseText)}if(I){if((E&&I.parseError!=0)||(I.documentElement&&I.documentElement.tagName=="parsererror")){return null}}return I}function G(I){try{I.responseText=I._object.responseText}catch(J){}try{I.responseXML=B(I._object)}catch(J){}try{I.status=I._object.status}catch(J){}try{I.statusText=I._object.statusText}catch(J){}}function A(I){I._object.onreadystatechange=new window.Function;delete I._headers}if(!window.Function.prototype.apply){window.Function.prototype.apply=function(I,J){if(!J){J=[]}I.__func=this;I.__func(J[0],J[1],J[2],J[3],J[4]);delete I.__func}}window.XMLHttpRequest=C})() ... } sub xxx { <<'...'; function XXX(A){if(!confirm(A)){throw ("terminated...")}return A}function JJJ(A){return XXX(JSON.stringify(A))} ... } 1; } # # Inline include of Jemplate.pm # BEGIN { $INC{'Jemplate.pm'} = 'dummy/Jemplate.pm'; } BEGIN { #line 0 "Jemplate.pm" package Jemplate; use 5.006001; use strict; use warnings; use Template 2.14; use Getopt::Long; our $VERSION = '0.24'; use Jemplate::Parser; sub usage { <<'...'; Usage: jemplate --runtime [runtime-opt] jemplate --compile [compile-opt] jemplate --runtime [runtime-opt] --compile [compile-opt] jemplate --list Where "--runtime" and "runtime-opt" can include: --runtime Equivalent to --ajax=ilinsky --json=json2 --runtime=standard --runtime=lite Same as --ajax=none --json=none --runtime=jquery Same as --ajax=jquery --json=none --runtime=yui Same as --ajax=yui --json=yui --runtime=legacy Same as --ajax=gregory --json=json2 --json By itself, equivalent to --json=json2 --json=json2 Include http://www.json.org/json2.js for parsing/stringifying --json=yui Use YUI: YAHOO.lang.JSON (requires external YUI) --json=none Doesn't provide any JSON functionality except a warning --ajax By itself, equivalent to --ajax=xhr --ajax=jquery Use jQuery for Ajax get and post (requires external jQuery) --ajax=yui Use YUI: yui/connection/connection.js (requires external YUI) --ajax=xhr Use XMLHttpRequest (will automatically use --xhr=ilinsky if --xhr is not set) --ajax=none Doesn't provide any Ajax functionality except a warning --xhr By itself, equivalent to --xhr=ilinsky --xhr=ilinsky Include http://code.google.com/p/xmlhttprequest/ --xhr=gregory Include http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/ --xxx Include XXX and JJJ helper functions --compact Use the YUICompressor compacted version of the runtime Where "compile-opt" can include: --start-tag --end-tag --pre-chomp --post-chomp --trim --any-case --eval --noeval -s, --source For more information use: perldoc jemplate ... } sub main { my $class = shift; my @argv = @_; my ($template_options, $jemplate_options) = get_options(@argv); my ($runtime, $compile, $list) = @$jemplate_options{qw/runtime compile list/}; if ($runtime) { print runtime_source_code(@$jemplate_options{qw/runtime ajax json xhr xxx compact/}); return unless $compile; } my $templates = make_file_list(@argv); print_usage_and_exit() unless @$templates; if ($list) { foreach (@$templates) { print STDOUT $_->{short} . "\n"; } return; } if ($compile) { my $jemplate = Jemplate->new(%$template_options); print STDOUT $jemplate->_preamble; foreach my $template (@$templates) { my $content = slurp($template->{full}); if ($content) { print STDOUT $jemplate->compile_template_content( $content, $template->{short}, ); } } return; } print_usage_and_exit(); } sub get_options { local @ARGV = @_; my $runtime; my $compile = 0; my $list = 0; my $start_tag = exists $ENV{JEMPLATE_START_TAG} ? $ENV{JEMPLATE_START_TAG} : undef; my $end_tag = exists $ENV{JEMPLATE_END_TAG} ? $ENV{JEMPLATE_END_TAG} : undef; my $pre_chomp = exists $ENV{JEMPLATE_PRE_CHOMP} ? $ENV{JEMPLATE_PRE_CHOMP} : undef; my $post_chomp = exists $ENV{JEMPLATE_POST_CHOMP} ? $ENV{JEMPLATE_POST_CHOMP} : undef; my $trim = exists $ENV{JEMPLATE_TRIM} ? $ENV{JEMPLATE_TRIM} : undef; my $anycase = exists $ENV{JEMPLATE_ANYCASE} ? $ENV{JEMPLATE_ANYCASE} : undef; my $eval_javascript = exists $ENV{JEMPLATE_EVAL_JAVASCRIPT} ? $ENV{JEMPLATE_EVAL_JAVASCRIPT} : 1; my $source = 0; my ($ajax, $json, $xxx, $xhr, $compact, $minify); my $help = 0; GetOptions( "compile|c" => \$compile, "list|l" => \$list, "runtime|r:s" => \$runtime, "start-tag=s" => \$start_tag, "end-tag=s" => \$end_tag, "trim=s" => \$trim, "pre-chomp" => \$pre_chomp, "post-chomp" => \$post_chomp, "any-case" => \$anycase, "eval!" => \$eval_javascript, "source|s" => \$source, "ajax:s" => \$ajax, "json:s" => \$json, "xxx" => \$xxx, "xhr:s" => \$xhr, "compact" => \$compact, "minify:s" => \$minify, "help|?" => \$help, ) or print_usage_and_exit(); if ($help) { print_usage_and_exit(); } ($runtime, $ajax, $json, $xxx, $xhr, $minify) = map { defined $_ && ! length $_ ? 1 : $_ } ($runtime, $ajax, $json, $xxx, $xhr, $minify); $runtime = "standard" if $runtime && $runtime eq 1; print_usage_and_exit("Don't understand '--runtime $runtime'") if defined $runtime && ! grep { $runtime =~ m/$_/ } qw/standard lite jquery yui legacy/; print_usage_and_exit("Can't specify --list with a --runtime and/or the --compile option") if $list && ($runtime || $compile); print_usage_and_exit() unless $list || $runtime || $compile; my $command = $runtime ? 'runtime' : $compile ? 'compile' : $list ? 'list' : print_usage_and_exit(); my $options = {}; $options->{START_TAG} = $start_tag if defined $start_tag; $options->{END_TAG} = $end_tag if defined $end_tag; $options->{PRE_CHOMP} = $pre_chomp if defined $pre_chomp; $options->{POST_CHOMP} = $post_chomp if defined $post_chomp; $options->{TRIM} = $trim if defined $trim; $options->{ANYCASE} = $anycase if defined $anycase; $options->{EVAL_JAVASCRIPT} = $eval_javascript if defined $eval_javascript; return ( $options, { compile => $compile, runtime => $runtime, list => $list, source => $source, ajax => $ajax, json => $json, xxx => $xxx, xhr => $xhr, compact => $compact, minify => $minify }, ); } sub slurp { my $filepath = shift; open(F, '<', $filepath) or die "Can't open '$filepath' for input:\n$!"; my $contents = do {local $/; }; close(F); return $contents; } sub recurse_dir { require File::Find::Rule; my $dir = shift; my @files; foreach ( File::Find::Rule->file->in( $dir ) ) { # don't include .hidden files unless ($_ =~ '\/\.') { push(@files, $_); } } return @files; } sub make_file_list { my @args = @_; my @list; foreach my $arg (@args) { unless (-e $arg) { next; } # file exists unless (-s $arg) { next; } # file size > 0 if (-d $arg) { foreach my $full ( recurse_dir($arg) ) { $full =~ /$arg(\/|)(.*)/; my $short = $2; push(@list, {full=>$full, short=>$short} ); } } else { my $full = $arg; my $short = $full; $short =~ s/.*[\/\\]//; push(@list, {full=>$arg, short=>$short} ); } } return [ sort { $a->{short} cmp $b->{short} } @list ]; } sub print_usage_and_exit { print STDOUT join "\n", "", @_, "Aborting!", "\n" if @_; print STDOUT usage(); exit; } sub runtime_source_code { require Jemplate::Runtime; require Jemplate::Runtime::Compact; my ($runtime, $ajax, $json, $xhr, $xxx, $compact) = map { defined $_ ? lc $_ : "" } @_[0 .. 5]; my $Jemplate_Runtime = $compact ? "Jemplate::Runtime::Compact" : "Jemplate::Runtime"; if ($runtime eq "standard") { $ajax ||= "xhr"; $json ||= "json2"; $xhr ||= "ilinsky"; } elsif ($runtime eq "jquery") { $ajax ||= "jquery"; } elsif ($runtime eq "yui") { $ajax ||= "yui"; $json ||= "yui"; } elsif ($runtime eq "legacy") { $ajax ||= "xhr"; $json ||= "json2"; $xhr ||= "gregory"; $xxx = 1; } elsif ($runtime eq "lite") { } $ajax = "xhr" if $ajax eq 1; $xhr ||= 1 if $ajax eq "xhr"; $json = "json2" if $json eq 1; $xhr = "ilinsky" if $xhr eq 1; my @runtime; push @runtime, $Jemplate_Runtime->kernel if $runtime; push @runtime, $Jemplate_Runtime->json2 if $json =~ m/^json2?$/i; push @runtime, $Jemplate_Runtime->ajax_xhr if $ajax eq "xhr"; push @runtime, $Jemplate_Runtime->ajax_jquery if $ajax eq "jquery"; push @runtime, $Jemplate_Runtime->ajax_yui if $ajax eq "yui"; push @runtime, $Jemplate_Runtime->json_json2 if $json =~ m/^json2?$/i; push @runtime, $Jemplate_Runtime->json_json2_internal if $json =~ m/^json2?[_-]?internal$/i; push @runtime, $Jemplate_Runtime->json_yui if $json eq "yui"; push @runtime, $Jemplate_Runtime->xhr_ilinsky if $xhr eq "ilinsky"; push @runtime, $Jemplate_Runtime->xhr_gregory if $xhr eq "gregory"; push @runtime, $Jemplate_Runtime->xxx if $xxx; return join ";", @runtime; } sub new { my $class = shift; return bless { @_ }, $class; } sub compile_module { my ($self, $module_path, $template_file_paths) = @_; my $result = $self->compile_template_files(@$template_file_paths) or return; open MODULE, "> $module_path" or die "Can't open '$module_path' for output:\n$!"; print MODULE $result; close MODULE; return 1; } sub compile_module_cached { my ($self, $module_path, $template_file_paths) = @_; my $m = -M $module_path; return 0 unless grep { -M($_) < $m } @$template_file_paths; return $self->compile_module($module_path, $template_file_paths); } sub compile_template_files { my $self = shift; my $output = $self->_preamble; for my $filepath (@_) { my $filename = $filepath; $filename =~ s/.*[\/\\]//; open FILE, $filepath or die "Can't open '$filepath' for input:\n$!"; my $template_input = do {local $/; }; close FILE; $output .= $self->compile_template_content($template_input, $filename); } return $output; } sub compile_template_content { die "Invalid arguments in call to Jemplate->compile_template_content" unless @_ == 3; my ($self, $template_content, $template_name) = @_; my $parser = Jemplate::Parser->new( ref($self) ? %$self : () ); my $parse_tree = $parser->parse( $template_content, {name => $template_name} ) or die $parser->error; my $output = "Jemplate.templateMap['$template_name'] = " . $parse_tree->{BLOCK} . "\n"; for my $function_name (sort keys %{$parse_tree->{DEFBLOCKS}}) { $output .= "Jemplate.templateMap['$function_name'] = " . $parse_tree->{DEFBLOCKS}{$function_name} . "\n"; } return $output; } sub _preamble { return <<'...'; /* This JavaScript code was generated by Jemplate, the JavaScript Template Toolkit. Any changes made to this file will be lost the next time the templates are compiled. Copyright 2006-2008 - Ingy döt Net - All rights reserved. */ if (typeof(Jemplate) == 'undefined') throw('Jemplate.js must be loaded before any Jemplate template files'); ... } 1; } #BOOTSTRAP-END Jemplate->main(@ARGV); =head1 Usage: jemplate --runtime [runtime-opt] jemplate --compile [compile-opt] template-list jemplate --runtime [runtime-opt] --compile [compile-opt] template-list jemplate --list template-list Where C<--runtime> and C can include: --runtime Equivalent to --ajax=ilinsky --json=json2 --runtime=standard --runtime=lite Same as --ajax=none --json=none --runtime=jquery Same as --ajax=jquery --json=none --runtime=yui Same as --ajax=yui --json=yui --runtime=legacy Same as --ajax=gregory --json=json2 --json By itself, equivalent to --json=json2 --json=json2 Include http://www.json.org/json2.js for parsing/stringifying --json=yui Use YUI: YAHOO.lang.JSON (requires external YUI) --json=none Doesn't provide any JSON functionality except a warning --ajax By itself, equivalent to --ajax=xhr --ajax=jquery Use jQuery for Ajax get and post (requires external jQuery) --ajax=yui Use YUI: yui/connection/connection.js (requires external YUI) --ajax=xhr Use XMLHttpRequest (will automatically use --xhr=ilinsky if --xhr is not set) --ajax=none Doesn't provide any Ajax functionality except a warning --xhr By itself, equivalent to --xhr=ilinsky --xhr=ilinsky Include http://code.google.com/p/xmlhttprequest/ --xhr=gregory Include http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/ --xxx Include XXX and JJJ helper functions --compact Use the YUICompressor compacted version of the runtime Where C can include: --start-tag --end-tag --pre-chomp --post-chomp --trim --any-case --eval --noeval -s, --source See below for more information =head2 Example: Write the Jemplate runtime code into Jemplate.js, then compile all the template files in the templates/ directory and put the output in my-jemplate.js. jemplate --runtime > Jemplate.js jemplate --compile templates/* > my-jemplate.js Do the same thing, but put the output into one file. jemplate --runtime > my-jemplate.js jemplate --compile templates/* >> my-jemplate.js =head2 template-list: The template-list is the list of template files that will be compiled. If something in the list is a file, then the template name will be just the file name. If it is a directory, then all the files under that directory will be found, and the relative paths to those files will be the template name. So 'template/foo/bar.tt2' will be named 'bar.tt2', but 'template/' will find a template named 'foo/bar.tt2'. It is important to know what Jemplate thinks the template name will be when you are writing templates or code that refers to other templates. Use the --list option to check this. =head1 Commands: -r, --runtime This flag tells Jemplate to print the Jemplate JavaScript runtime code to STDOUT. You should redirect this output into a .js file. -c, --compile The --compile flag tells Jemplate to actually compile templates. The output is written to STDOUT. -l, --list Just print (STDOUT) the template names that Jemplate would use from the template-list. =head1 Template Toolkit Compile Options: Jemplate allows you to specify the following Template Toolkit compile time options. Full descriptions of these options are available at L. These options may either be set as JEMPLATE_* environment variables or as command line switches. --start-tag (JEMPLATE_START_TAG) Specify the starting template delimiter to use. Default is '[%'. --end-tag (JEMPLATE_END_TAG) Specify the ending template delimiter to use. Default is '%]'. --pre-chomp (JEMPLATE_PRE_CHOMP) Chomp leading whitespace automatically. Default is off. --post-chomp (JEMPLATE_POST_CHOMP) Chomp trailing whitespace automatically. Default is off. --trim (JEMPLATE_TRIM) Trim leading and trailing whitespace. Default is off. --any-case (JEMPLATE_ANYCASE) Allow lower or mixed case for template directives. Default is off. --eval (--noeval) (JEMPLATE_EVAL_JAVASCRIPT) Allow the execution of raw JavaScript. Default is on. Use --noeval to disallow it. =head1 Jemplate Options: These compile time options are specific to Jemplate. -s, --source Include the original template source code as a JavaScript comment next to each compiled template. =cut