The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/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.09';
@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 File::Spec;
use Text::Glob 'glob_to_regex';
use Number::Compare;
use Carp qw/croak/;
use File::Find (); # we're only wrapping for now

our $VERSION = '0.32';

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    => [],
        subs     => {},
        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;
    # compile all the subrules to code fragments
    push @{ $self->{rules} }, {
        rule => "any",
        code => '(' . join( ' || ', map '( ' . $_->_compile . ' )', @_ ). ')',
        args => \@_,
    };
    
    # merge all the subs hashes of the kids into ourself
    %{ $self->{subs} } = map { %{ $_->{subs} } } $self, @_;
    $self;
}

*or = \&any;


sub not {
    my $self = _force_object shift;

    push @{ $self->{rules} }, {
        rule => 'not',
        args => \@_,
        code => '(' . join ( ' && ', map { "!(". $_->_compile . ")" } @_ ) . ")",
    };
    
    # merge all the subs hashes into us
    %{ $self->{subs} } = map { %{ $_->{subs} } } $self, @_;
    $self;
}

*none = \&not;


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 (<FILE>) {
            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 {
    our $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;
    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' $@";
    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 );
    }

    return @found;
}

sub _call_find {
    my $self = shift;
    File::Find::find( @_ );
}

sub _compile {
    my $self = shift;

    return '1' unless @{ $self->{rules} };
    my $code = join " && ", map {
        if (ref $_->{code}) {
            my $key = "$_->{code}";
            $self->{subs}{$key} = $_->{code};
            "\$subs{'$key'}->(\@args) # $_->{rule}\n";
        }
        else {
            "( $_->{code} ) # $_->{rule}\n";
        }
    } @{ $self->{rules} };

    #warn $code;
    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 Exporter;
use vars qw( @EXPORT_OK %EXPORT_TAGS );
use vars qw( $DEBUG_OPTIONS @STATUS @ERROR @CHOMP @DEBUG @ISA );
@ISA = qw( Exporter );

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] && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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]) && ref($_[0]) eq '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(?!#line)/\n    /g;
    $block =~ s/\s+$//;

    $defblocks = join('', map {
        my $code = $defblocks->{ $_ };
        $code =~ s/\n(?!#line)/\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 <<EOF

$class->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;
use Scalar::Util 'blessed';

use constant EXCEPTION => 'Template::Exception';

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 : '<no 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 blessed($$error) && $$error->isa(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 <<EOF;
$self
PRE_PROCESS  => [ @{ $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 : '<no 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 $_ ? $_ : '<undef>' } @$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 : '<no 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 = <FH>;
        $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() : '<no parser>';
    $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 $_ ? $_ : '<undef>' }
                               @{ $lookup->{ $_ } }) . ' ]') : '<undef>');
    } 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 }<-": '<undef>';
            $next = $next ? "->#$lut->{ $next }": '<undef>';
            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 5.006;
use base 'Template::Base';

use Template::Config;
use Template::Constants;
use Template::Provider;  
use Template::Service;
use File::Basename;
use File::Path;
use Scalar::Util qw(blessed);

our $VERSION = '2.22';
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) && ref($opts[0]) eq '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 (blessed($where) && $where->can('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]->block_label('last ', ';')    }
	],
	[#Rule 40
		 'atomdir', 1,
sub
{ $_[0]->in_block('FOR')
                                        ? $factory->next($_[0]->block_label)
                                        : $_[0]->block_label('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]->enter_block('FOR')           }
	],
	[#Rule 57
		 'loop', 6,
sub
{ $factory->foreach(@{$_[2]}, $_[5], $_[0]->leave_block)  }
	],
	[#Rule 58
		 'loop', 3,
sub
{ $factory->foreach(@{$_[3]}, $_[1])  }
	],
	[#Rule 59
		 '@2-3', 0,
sub
{ $_[0]->enter_block('WHILE')         }
	],
	[#Rule 60
		 'loop', 6,
sub
{ $factory->while(@_[2, 5], $_[0]->leave_block) }
	],
	[#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 <<EOF;
sub {
    my \$context = shift || die "template sub called without context\\n";
    my \$stash   = \$context->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 <<EOF;

$OUTPUT do {
    my \$output  = '';
    my \$_tt_error;
    
    eval { BLOCK: {
$block
    } };
    if (\$@) {
        \$_tt_error = \$context->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, $label) = @_;
    $args  = shift @$args;
    $args  = @$args ? ', { ' . join(', ', @$args) . ' }' : '';
    $label ||= 'LOOP';

    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 <<EOF;

do {
    my (\$_tt_value, \$_tt_error, \$_tt_oldloop);
    my \$_tt_list = $list;
    
    unless (UNIVERSAL::isa(\$_tt_list, 'Template::Iterator')) {
        \$_tt_list = Template::Config->iterator(\$_tt_list)
            || die \$Template::Config::ERROR, "\\n"; 
    }

    (\$_tt_value, \$_tt_error) = \$_tt_list->get_first();
    $loop_save;
    \$stash->set('loop', \$_tt_list);
    eval {
$label:   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 {
    my ($class, $label) = @_;
    $label ||= 'LOOP';
    return <<EOF;
(\$_tt_value, \$_tt_error) = \$_tt_list->get_next();
next $label;
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 <<EOF;

$OUTPUT do {
    my \$output = '';
$block
    \$context->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 <<EOF;

$OUTPUT do {
    my \$output = '';
$block
    foreach ($file) {
        \$output = \$context->include(\$_$hash); 
    }
    \$output;
};
EOF
}



sub while {
    my ($class, $expr, $block, $label) = @_;
    $block = pad($block, 2) if $PRETTY;
    $label ||= 'LOOP';

    return <<EOF;

do {
    my \$_tt_failsafe = $WHILE_MAX;
$label:
    while (--\$_tt_failsafe && ($expr)) {
$block
    }
    die "WHILE loop terminated (> $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 .= <<EOF;
\$_tt_match = $match;
\$_tt_match = [ \$_tt_match ] unless ref \$_tt_match eq 'ARRAY';
if (grep(/^\\Q\$_tt_result\\E\$/, \@\$_tt_match)) {
$block
    last SWITCH;
}
EOF
    }

    $caseblock .= $default
        if defined $default;
    $caseblock = pad($caseblock, 2) if $PRETTY;

return <<EOF;

do {
    my \$_tt_result = $expr;
    my \$_tt_match;
    SWITCH: {
$caseblock
    }
};
EOF
}



sub try {
    my ($class, $block, $catch) = @_;
    my @catch = @$catch;
    my ($match, $mblock, $default, $final, $n);
    my $catchblock = '';
    my $handlers = [];

    $block = pad($block, 2) if $PRETTY;
    $final = pop @catch;
    $final = "# FINAL\n" . ($final ? "$final\n" : '')
           . 'die $_tt_error if $_tt_error;' . "\n" . '$output;';
    $final = pad($final, 1) if $PRETTY;

    $n = 0;
    foreach $catch (@catch) {
        $match = $catch->[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 <<EOF;

$OUTPUT do {
    my \$output = '';
    my (\$_tt_error, \$_tt_handler);
    eval {
$block
    };
    if (\$@) {
        \$_tt_error = \$context->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 OLD_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 <<EOF;
do {
    my \$output = '';
    my \$_tt_oldv = \$stash->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 <<EOF;

\$context->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 <<EOF;
$block
EOF
}




sub filter {
    my ($class, $lnameargs, $block) = @_;
    my ($name, $args, $alias) = @$lnameargs;
    $name = shift @$name;
    $args = &args($class, $args);
    $args = $args ? "$args, $alias" : ", undef, $alias"
        if $alias;
    $name .= ", $args" if $args;
    $block = pad($block, 1) if $PRETTY;
 
    return <<EOF;

$OUTPUT do {
    my \$output = '';
    my \$_tt_filter = \$context->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 <<EOF;

\$stash->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 <<EOF;

\$stash->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 <<EOF;

\$stash->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] && ref($_[0]) eq '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      => '',
        IN_BLOCK    => [ ],
        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 enter_block {
    my ($self, $name) = @_;
    my $blocks = $self->{ IN_BLOCK };
    push(@{ $self->{ IN_BLOCK } }, $name);
}

sub leave_block {
    my $self = shift;
    my $label = $self->block_label;
    pop(@{ $self->{ IN_BLOCK } });
    return $label;
}

sub in_block {
    my ($self, $name) = @_;
    my $blocks = $self->{ IN_BLOCK };
    return @$blocks && $blocks->[-1] eq $name;
}

sub block_label {
    my ($self, $prefix, $suffix) = @_;
    my $blocks = $self->{ IN_BLOCK };
    my $name   = @$blocks 
        ? $blocks->[-1] . scalar @$blocks 
        : undef;
    return join('', grep { defined $_ } $prefix, $name, $suffix);
}




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} ? qr<TAGS>i : qr<TAGS>;

    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{ (\r?\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)) {
            # Fold potential keywords to UPPER CASE if the ANYCASE option is
            # set, unless (we've got some preceeding tokens and) the previous
            # token is a DOT op.  This prevents the 'last' in 'data.last'
            # from being interpreted as the LAST keyword.
            $uctoken = 
                ($anycase && (! @tokens || $tokens[-2] ne 'DOT'))
                    ? 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'
    $line ||= 1;
    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 = '<undef>' 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 _attempt_range_expand_val ($) {
    my $val = shift;
    return $val unless
        my ( $from, $to ) = $val =~ m/\s*\[\s*(\S+)\s*\.\.\s*(\S+)\s*\]/;

    die "Range expansion is current supported for positive/negative integer values only (e.g. [ 1 .. 10 ])\nCannot expand: $val" unless $from =~ m/^-?\d+$/ && $to =~ m/^-?\d+$/;

    return join '', '[', join( ',', $from .. $to ), ']';
}


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 =  _attempt_range_expand_val $val;
    $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()';
    }

    $list = _attempt_range_expand_val $list;

    return <<EOF;

// FOREACH 
(function() {
    var list = $list;
    list = new Jemplate.Iterator(list);
    var retval = list.get_first();
    var value = retval[0];
    var done = retval[1];
    var oldloop;
    $loop_save
    stash.set('loop', list);
    try {
        while (! done) {
            $loop_set;
$block;
            retval = list.get_next();
            value = retval[0];
            done = retval[1];
        }
    }
    catch(e) {
        throw(context.set_error(e, output));
    }
    $loop_restore;
})();
EOF
}



sub next {
  return <<EOF;
  retval = list.get_next();
  value = retval[0];
  done = retval[1];
  continue;
EOF
}

sub wrapper {
    my ($class, $nameargs, $block) = @_;
    my ($file, $args) = @$nameargs;
    my $hash = shift @$args;

    s/ => /: / for @$hash;
    return $class->multi_wrapper($file, $hash, $block)
        if @$file > 1;
    $file = shift @$file;
    push(@$hash, "'content': output");
    $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';

    return <<EOF;

// WRAPPER
$OUTPUT (function() {
    var output = '';
$block;
    return context.include($file);
})();
EOF
}

sub multi_wrapper {
    my ($class, $file, $hash, $block) = @_;

    push(@$hash, "'content': output");
    $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';

    $file = join(', ', reverse @$file);

    return <<EOF;

// WRAPPER
$OUTPUT (function() {
    var output = '';
$block;
    var files = new Array($file);
    for (var i = 0; i < files.length; i++) {
        output = context.include(files[i]$hash);
    }
    return output;
})();
EOF
}



sub while {
    my ($class, $expr, $block) = @_; 
    
    return <<EOF;
    
// WHILE
var failsafe = $WHILE_MAX;
while (--failsafe && ($expr)) {
$block
}
if (! failsafe)
    throw("WHILE loop terminated (> $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 .= <<EOF;
case $match:
$block
break;

EOF
    }

    if (defined $default) {
        $caseblock .= <<EOF;
default:
$default
break;
EOF
    }

return <<EOF;

    switch($expr) {
$caseblock
    }

EOF
}



sub throw {
    my ($class, $nameargs) = @_;
    my ($type, $args) = @$nameargs;
    my $hash = shift(@$args);
    my $info = shift(@$args);
    $type = shift @$type;

    return qq{throw([$type, $info]);};
}



sub clear {
    return "output = '';";
}



sub break {
    return 'break;';
}                       
        

sub return {
    return "return output;"
}



sub stop {
    return "throw('Jemplate.STOP\\n' + 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, context.plugin($file));";
}



sub raw {
    my ($class, $lnameargs) = @_;
    my ($file, $args, $alias) = @$lnameargs;
    $file = shift @$file;       # same production rule as INCLUDE
    $alias ||= $file;
    $args = &args($class, $args);
    $file =~ s/'|"//g;
    return "// RAW\n"
         . "stash.set($alias, $file);";
}



sub filter {
    my ($class, $lnameargs, $block) = @_;
    my ($name, $args, $alias) = @$lnameargs;
    $name = shift @$name;
    $args = &args($class, $args);
    $args = $args ? "$args, $alias" : ", null, $alias"
        if $alias;
    $name .= ", $args" if $args;
    return <<EOF;

// FILTER
$OUTPUT (function() {
    var output = '';

$block

    return context.filter(output, $name);
})();
EOF
}

sub quoted {
    my $class = shift;
    if ( @_ && ref($_[0]) ) {
        return join( " + ", @{$_[0]} );
    }
    return "throw('QUOTED called with unknown arguments in Jemplate');";
}   


sub macro {
    my ($class, $ident, $block, $args) = @_;

    if ($args) {
        $args = join(';', map { "args['$_'] = fargs.shift()" } @$args);

        return <<EOF;

//MACRO
stash.set('$ident', function () {
    var output = '';
    var args = {};
    var fargs = Array.prototype.slice.call(arguments);
    $args;
    args.arguments = Array.prototype.slice.call(arguments);

    var params = fargs.shift() || {};

    for (var key in params) {
        args[key] = params[key];
    }

    context.stash.clone(args);
    try {
$block
    }
    catch(e) {
        var error = context.set_error(e, output);
        throw(error);
    }

    context.stash.declone();
    return output;
});

EOF

    }
    else {
        return <<EOF;

//MACRO

stash.set('$ident', function () {
    var output = '';
    var args = {};
    
    var fargs = Array.prototype.slice.call(arguments);
    args.arguments = Array.prototype.slice.call(arguments);   
    
    if (typeof arguments[0] == 'object') args = arguments[0];
    
    context.stash.clone(args);
    try {
$block
    }
    catch(e) {
        var error = context.set_error(e, output);
        throw(error);
    }

    context.stash.declone(); 
    return output;});

EOF
    }
}

sub capture {
    my ($class, $name, $block) = @_;

    if (ref $name) {
        if (scalar @$name == 2 && ! $name->[1]) {
            $name = $name->[0];
        }
        else {
            $name = '[' . join(', ', @$name) . ']';
        }
    }

    return <<EOF;

// CAPTURE
(function() {
	var output = '';
	$block
	stash.set($name, output);
})();
EOF

}   

BEGIN {
    return;  # Comment out this line to get callback traces
    no strict 'refs';
    my $pkg = __PACKAGE__ . '::';
    my $stash = \ %$pkg;
    use strict 'refs';
    for my $name (keys %$stash) {
        my $glob = $stash->{$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]) == false", @_[4, 5])  }
	],
	[#Rule 49
		 'condition', 3,
sub
{ $factory->if("($_[3]) == false", $_[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
{ "Math.floor($_[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 <ingy@cpan.org>

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, '&amp;');
    text = text.replace(/</g, '&lt;');
    text = text.replace(/>/g, '&gt;');
    text = text.replace(/"/g, '&quot;'); // " end quote for emacs
    return text;
}

proto.filters.html_para = function(text) {
    var lines = text.split(/(?:\r?\n){2,}/);
    return "<p>\n" + lines.join("\n</p>\n\n<p>\n") + "</p>\n";
}

proto.filters.html_break = function(text) {
    return text.replace(/(\r?\n){2,}/g, "$1<br />$1<br />$1");
}

proto.filters.html_line_break = function(text) {
    return text.replace(/(\r?\n)/g, "$1<br />$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;
    }


    //root is complex object, not scalar
    if (atroot || (root instanceof Object && !(root instanceof Array)) || 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 (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 (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 (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 == undefined ? 'g' : 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 == undefined ? 'g' : 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) {
    // To make it like slice in TT
    // See rt53453
    if ( end == -1 ) {
        return list.slice( start );
    }
    return list.slice( start, end + 1 );
}

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) });
}

// item           return a value by key
proto.hash_functions.item = function(hash, key) {
    return hash[key];
}

// 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;
}

proto.hash_functions.pairs = function(hash) {
    var list = new Array();
    var keys = new Array();
    for ( var key in hash ) {
        keys.push( key );
    }
    keys.sort();
    for ( var key in keys ) {
        key = keys[key]
        list.push( { 'key': key, 'value': 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;

/*
    http://www.JSON.org/json2.js
    2009-04-16

    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 two methods: stringify
    and parse.

        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. It can be a
                        function or an array of strings.

            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' or '&nbsp;'),
                        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 will 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.

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    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 the replacer parameter is an array of strings, 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 representations, 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
            the 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]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        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 the 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;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.

    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/

// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (!this.JSON) {
    this.JSON = {};
}
(function () {

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };

        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/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.

        escapable.lastIndex = 0;
        return escapable.test(string) ?
            '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + 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 = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value 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 (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        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 '';
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        JSON.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 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 a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                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});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.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 four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second 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 second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON 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(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third 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 fourth 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');
        };
    }
}());


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 {
    <<'...';
/*
    http://www.JSON.org/json2.js
    2009-04-16

    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 two methods: stringify
    and parse.

        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. It can be a
                        function or an array of strings.

            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' or '&nbsp;'),
                        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 will 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.

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    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 the replacer parameter is an array of strings, 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 representations, 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
            the 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]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        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 the 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;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.

    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/

// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (!this.JSON) {
    this.JSON = {};
}
(function () {

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };

        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/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.

        escapable.lastIndex = 0;
        return escapable.test(string) ?
            '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + 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 = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value 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 (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        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 '';
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        JSON.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 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 a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                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});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.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 four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second 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 second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON 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(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third 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 fourth 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');
        };
    }
}());

...
}

sub xhr_gregory {
    <<'...';
/*

Cross-Browser XMLHttpRequest v1.2
=================================

Emulate Gecko 'XMLHttpRequest()' functionality in IE and Opera. Opera requires
the Sun Java Runtime Environment <http://www.java.com/>.

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<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"){var url=data;Jemplate.Ajax.processGet(url,function(data){proc(data)});return null}}return proc(data)};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+"'"}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+"'"}};if(typeof Jemplate.Plugin=="undefined"){Jemplate.Plugin=function(){}}proto=Jemplate.Plugin.prototype;proto.plugins={};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,"&amp;");text=text.replace(/</g,"&lt;");text=text.replace(/>/g,"&gt;");text=text.replace(/"/g,"&quot;");return text};proto.filters.html_para=function(text){var lines=text.split(/(?:\r?\n){2,}/);return"<p>\n"+lines.join("\n</p>\n\n<p>\n")+"</p>\n"};proto.filters.html_break=function(text){return text.replace(/(\r?\n){2,}/g,"$1<br />$1<br />$1")};proto.filters.html_line_break=function(text){return text.replace(/(\r?\n)/g,"$1<br />$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}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)};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 instanceof Object&&!(root instanceof Array))||root==this.data.GLOBAL){if(typeof root[item]!="undefined"&&root[item]!=null&&(!is_function_call||!this.hash_functions[item])){if(typeof root[item]=="function"){result=root[item].apply(root,args)}else{return root[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(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(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={};proto.string_functions["typeof"]=function(value){return typeof value};proto.string_functions.chunk=function(string,size){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};proto.string_functions.defined=function(string){return 1};proto.string_functions.hash=function(string){return{"value":string}};proto.string_functions.length=function(string){return string.length};proto.string_functions.list=function(string){return[string]};proto.string_functions.match=function(string,re,modifiers){var regexp=new RegExp(re,modifiers==undefined?"g":modifiers);var list=string.match(regexp);return list};proto.string_functions.repeat=function(string,args){var n=args||1;var output="";for(var i=0;i<n;i++){output+=string}return output};proto.string_functions.replace=function(string,re,sub,modifiers){var regexp=new RegExp(re,modifiers==undefined?"g":modifiers);if(!sub){sub=""}return string.replace(regexp,sub)};proto.string_functions.search=function(string,re){var regexp=new RegExp(re);return(string.search(regexp)>=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<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){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){if(end==-1){return list.slice(start)}return list.slice(start,end+1)};proto.list_functions.splice=function(list){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={};proto.hash_functions["typeof"]=function(hash){return"object"};proto.hash_functions.each=function(hash){var list=new Array();for(var key in hash){list.push(key,hash[key])}return list};proto.hash_functions.exists=function(hash,key){return(typeof (hash[key])=="undefined")?0:1};proto.hash_functions["import"]=function(hash,hash2){for(var key in hash2){hash[key]=hash2[key]}return""};proto.hash_functions.keys=function(hash){var list=new Array();for(var key in hash){list.push(key)}return list};proto.hash_functions.list=function(hash,what){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};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)})};proto.hash_functions.item=function(hash,key){return hash[key]};proto.hash_functions.size=function(hash){var size=0;for(var key in hash){size++}return size};proto.hash_functions.sort=function(hash){var list=new Array();for(var key in hash){list.push(key)}return list.sort()};proto.hash_functions.values=function(hash){var list=new Array();for(var key in hash){list.push(hash[key])}return list};proto.hash_functions.pairs=function(hash){var list=new Array();var keys=new Array();for(var key in hash){keys.push(key)}keys.sort();for(var key in keys){key=keys[key];list.push({"key":key,"value":hash[key]})}return list};proto.hash_functions.remove=function(hash,key){return delete hash[key]};proto.hash_functions["delete"]=proto.hash_functions.remove;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(A,B){jQuery.get(A,null,B)},processGet:function(A,B){jQuery.getJSON(A,null,B)},post:function(A,B,C){jQuery.post(A,B,C)}}}())
...
}

sub ajax_xhr {
    <<'...';
(function(){Jemplate.Ajax={get:function(A,C){var B=new XMLHttpRequest();B.open("GET",A,Boolean(C));B.setRequestHeader("Accept","text/json; text/x-json; application/json");return this.request(B,null,C)},processGet:function(A,B){this.get(A,function(C){B(Jemplate.JSON.parse(C))})},post:function(A,C,D){var B=new XMLHttpRequest();B.open("POST",A,Boolean(D));B.setRequestHeader("Accept","text/json; text/x-json; application/json");B.setRequestHeader("Content-Type","application/x-www-form-urlencoded");return this.request(B,C,D)},request:function(A,B,C){if(C){A.onreadystatechange=function(){if(A.readyState==4){if(A.status==200){C(A.responseText)}}}}A.send(B);if(!C){if(A.status!=200){throw ('Request for "'+url+'" failed with status: '+A.status)}return A.responseText}return null}}}())
...
}

sub ajax_yui {
    <<'...';
(function(){Jemplate.Ajax={get:function(A,B){if(typeof B=="function"){B={success:B}}YAHOO.connect.asyncRequest("GET",A,B)},processGet:function(A,B){this.get(A,function(C){B(YAHOO.lang.JSON.parse(C))})},post:function(A,B,C){if(typeof C=="function"){C={success:C}}YAHOO.connect.asyncRequest("POST",A,C,B)}}}())
...
}

sub json_json2 {
    <<'...';
(function(){Jemplate.JSON={parse:function(A){return JSON.parse(A)},stringify:function(A){return JSON.stringify(A)}}}())
...
}

sub json_json2_internal {
    <<'...';
;(function(){

var JSON;

if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z"};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}return""}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){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)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}())

Jemplate.JSON={parse:function(A){return JSON.parse(A)},stringify:function(A){return JSON.stringify(A)}}

}());
...
}

sub json_yui {
    <<'...';
(function(){Jemplate.JSON={parse:function(A){return YAHOO.lang.JSON.parse(A)},stringify:function(A){return YAHOO.lang.JSON.stringify(A)}}}())
...
}

sub json2 {
    <<'...';
if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z"};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}return""}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){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)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}())
...
}

sub xhr_gregory {
    <<'...';
if(window.ActiveXObject&&!window.XMLHttpRequest){window.XMLHttpRequest=function(){var C=new Array("Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP");for(var A=0;A<C.length;A++){try{return new ActiveXObject(C[A])}catch(B){}}return null}}if(window.opera&&!window.XMLHttpRequest){window.XMLHttpRequest=function(){this.readyState=0;this.status=0;this.statusText="";this._headers=[];this._aborted=false;this._async=true;this._defaultCharset="ISO-8859-1";this._getCharset=function(){var B=_defaultCharset;var A=this.getResponseHeader("Content-type").toUpperCase();val=A.indexOf("CHARSET=");if(val!=-1){B=A.substring(val)}val=B.indexOf(";");if(val!=-1){B=B.substring(0,val)}val=B.indexOf(",");if(val!=-1){B=B.substring(0,val)}return B};this.abort=function(){this._aborted=true};this.getAllResponseHeaders=function(){return this.getAllResponseHeader("*")};this.getAllResponseHeader=function(C){var A="";for(var B=0;B<this._headers.length;B++){if(C=="*"||this._headers[B].h==C){A+=this._headers[B].h+": "+this._headers[B].v+"\n"}}return A};this.getResponseHeader=function(C){var A=getAllResponseHeader(C);var B=A.indexOf("\n");if(B!=-1){A=A.substring(0,B)}return A};this.setRequestHeader=function(B,A){this._headers[this._headers.length]={h:B,v:A}};this.open=function(E,C,D,A,B){this.method=E;this.url=C;this._async=true;this._aborted=false;this._headers=[];if(arguments.length>=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;O<this._headers.length;O++){I.setRequestProperty(this._headers[O].h,this._headers[O].v)}this._headers=[];if(this.method=="POST"){I.setDoOutput(true);var B=new java.io.OutputStreamWriter(I.getOutputStream(),this._getCharset());B.write(Q);B.flush();B.close()}var L=false;var J=false;var E=false;var C=false;var H=false;var P=false;for(var O=0;;O++){var N=I.getHeaderFieldKey(O);var K=I.getHeaderField(O);if(N==null&&K==null){break}if(N!=null){this._headers[this._headers.length]={h:N,v:K};switch(N.toLowerCase()){case"content-encoding":L=true;break;case"content-length":J=true;break;case"content-type":E=true;break;case"date":C=true;break;case"expires":H=true;break;case"last-modified":P=true;break}}}var R;R=I.getContentEncoding();if(R!=null&&!L){this._headers[this._headers.length]={h:"Content-encoding",v:R}}R=I.getContentLength();if(R!=-1&&!J){this._headers[this._headers.length]={h:"Content-length",v:R}}R=I.getContentType();if(R!=null&&!E){this._headers[this._headers.length]={h:"Content-type",v:R}}R=I.getDate();if(R!=0&&!C){this._headers[this._headers.length]={h:"Date",v:(new Date(R)).toUTCString()}}R=I.getExpiration();if(R!=0&&!H){this._headers[this._headers.length]={h:"Expires",v:(new Date(R)).toUTCString()}}R=I.getLastModified();if(R!=0&&!P){this._headers[this._headers.length]={h:"Last-modified",v:(new Date(R)).toUTCString()}}var D="";var G=I.getInputStream();if(G){var A=new java.io.BufferedReader(new java.io.InputStreamReader(G,this._getCharset()));var M;while((M=A.readLine())!=null){if(this.readyState==2){this.readyState=3;if(this.onreadystatechange){this.onreadystatechange()}}D+=M+"\n"}A.close();this.status=200;this.statusText="OK";this.responseText=D;this.readyState=4;if(this.onreadystatechange){this.onreadystatechange()}if(this.onload){this.onload()}}else{this.status=404;this.statusText="Not Found";this.responseText="";this.readyState=4;if(this.onreadystatechange){this.onreadystatechange()}if(this.onerror){this.onerror()}}}}}if(!window.ActiveXObject&&window.XMLHttpRequest){window.ActiveXObject=function(A){switch(A.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 {
    <<'...';
(function(){var D=window.XMLHttpRequest;var H=!!window.controllers,E=window.document.all&&!window.opera;function C(){this._object=D?new D:new window.ActiveXObject("Microsoft.XMLHTTP")}if(H&&D.wrapped){C.wrapped=D.wrapped}C.UNSENT=0;C.OPENED=1;C.HEADERS_RECEIVED=2;C.LOADING=3;C.DONE=4;C.prototype.readyState=C.UNSENT;C.prototype.responseText="";C.prototype.responseXML=null;C.prototype.status=0;C.prototype.statusText="";C.prototype.onreadystatechange=null;C.onreadystatechange=null;C.onopen=null;C.onsend=null;C.onabort=null;C.prototype.open=function(L,O,K,P,J){this._async=K;var N=this,M=this.readyState;if(E){var I=function(){if(N._object.readyState!=C.DONE){A(N)}};if(K){window.attachEvent("onunload",I)}}this._object.onreadystatechange=function(){if(H&&!K){return }N.readyState=N._object.readyState;G(N);if(N._aborted){N.readyState=C.UNSENT;return }if(N.readyState==C.DONE){A(N);if(E&&K){window.detachEvent("onunload",I)}}if(M!=N.readyState){F(N)}M=N.readyState};if(C.onopen){C.onopen.apply(this,arguments)}this._object.open(L,O,K,P,J);if(!K&&H){this.readyState=C.OPENED;F(this)}};C.prototype.send=function(I){if(C.onsend){C.onsend.apply(this,arguments)}if(I&&I.nodeType){I=window.XMLSerializer?new window.XMLSerializer().serializeToString(I):I.xml;if(!this._headers["Content-Type"]){this._object.setRequestHeader("Content-Type","application/xml")}}this._object.send(I);if(H&&!this._async){this.readyState=C.OPENED;G(this);while(this.readyState<C.DONE){this.readyState++;F(this);if(this._aborted){return }}}};C.prototype.abort=function(){if(C.onabort){C.onabort.apply(this,arguments)}if(this.readyState>C.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.260';

use Jemplate::Parser;

sub usage {
    <<'...';
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 "--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 $/; <F>};
    close(F);
    return $contents;
}

sub recurse_dir {
    require File::Find::Rule;

    my $dir = shift;
    my @files;
    foreach ( File::Find::Rule->file->in( $dir ) ) {
        if ( m{/\.[^\.]+} ) {} # Skip ".hidden" files or directories
        else {
            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 or -d $arg) { next; } # file size > 0 or directory (for Win platform)

        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;

    unshift @_, "standard" unless @_;

    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 $/; <FILE>};
        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<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 C<compile-opt> 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<http://www.template-toolkit.org/docs/plain/Manual/Config.html>.

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