[Templates-cvs] cvs commit: TT3/lib/Template Parser.pm

cvs@template-toolkit.org cvs@template-toolkit.org
Fri, 03 Dec 2004 13:38:15 +0000


cvs         04/12/03 13:38:15

  Modified:    lib/Template Parser.pm
  Log:
  * added parse_tag() to handle nested tags
  
  Revision  Changes    Path
  1.19      +90 -21    TT3/lib/Template/Parser.pm
  
  Index: Parser.pm
  ===================================================================
  RCS file: /template-toolkit/TT3/lib/Template/Parser.pm,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- Parser.pm	2004/12/03 11:13:42	1.18
  +++ Parser.pm	2004/12/03 13:38:15	1.19
  @@ -18,7 +18,7 @@
   #   modify it under the same terms as Perl itself.
   #
   # REVISION
  -#   $Id: Parser.pm,v 1.18 2004/12/03 11:13:42 abw Exp $
  +#   $Id: Parser.pm,v 1.19 2004/12/03 13:38:15 abw Exp $
   #
   #========================================================================
   
  @@ -29,7 +29,7 @@
   use Template::Base;
   use base qw( Template::Base );
   
  -our $VERSION = sprintf("%d.%02d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/);
  +our $VERSION = sprintf("%d.%02d", q$Revision: 1.19 $ =~ /(\d+)\.(\d+)/);
   our $DEBUG   = 0 unless defined $DEBUG;
   our $ERROR   = '';
   our $THROW   = 'parser';
  @@ -90,17 +90,19 @@
   
   # regexen to match various unquoted strings.  $IDENT matches a simple
   # identifier (e.g. foo), while $KEYWORD adds the requirement of a word
  -# boundary at the end (TODO: check why this is).  $FILENAME allows
  -# dots (e.g. foo.txt) and $RESOURCE allows dots and colon
  -# (e.g. file:foo.txt).  $HASHKEY matches valid hash keys which can be
  +# boundary at the end (TODO: check why this is).  $FILEPATH allows
  +# dots, slashes and colon (e.g. /foo/bar.txt) and $RESOURCE is a
  +# special case of this with an explicit leading resource identifier
  +# (e.g.  file:foo.txt).  $HASHKEY matches valid hash keys which can be
   # bare identifiers ($IDENT) or single quoted string ($SQUOTE).  (TODO:
   # why not double quoted strings?)
   
   our $IDENT    = qr/ \G ( \w+ ) /x;
   our $KEYWORD  = qr/ \G ( \w+ )\b /x;
  -our $FILENAME = qr/ \G ( [\w\.\/:]+ ) /x;
  +our $FILEPATH = qr/ \G ( [\w\.\/:]+ ) /x;
   our $RESOURCE = qr/ \G ( \w+ ) : ( [\w\.\/:]+ ) /x;
   our $HASHKEY  = qr/ \G $IDENT | $SQUOTE /ox;
  +our $PLUSPATH = qr/ \+ /x;
   
   # regex to match the dot operator, making sure that another dot doesn't
   # follow, preventing it from mistakenly identifying the list range op '..'
  @@ -191,6 +193,7 @@
       my $unary    = $config->{ op_unary    } || $self->pkgvar( UNARY    => $UNARY );
       my $binary   = $config->{ op_binary   } || $self->pkgvar( BINARY   => $BINARY );
       my $tertiary = $config->{ op_tertiary } || $self->pkgvar( TERTIARY => $TERTIARY );
  +    my $pluspath = $config->{ op_pluspath } || $self->pkgvar( PLUSPATH => $PLUSPATH );
   
       # construct regexen to match ignorable whitespace and comments,
       # and various other punctuation tokens, including commas,
  @@ -202,12 +205,15 @@
       $self->{ wspace    } = qr/ \G $wspace /x;
       $self->{ comma     } = qr/ \G (?:$wspace,)? $wspace /x;
       $self->{ semicolon } = qr/ \G $wspace ; $wspace /x;
  +    $self->{ pluspath  } = qr/ \G $wspace $pluspath $wspace /x;
       $self->{ assign    } = qr/ \G $wspace ($assign) $wspace /x;
       $self->{ range     } = qr/ \G $wspace ($range) $wspace /x;
       $self->{ unary     } = qr/ \G $wspace ($unary) $wspace /x;
       $self->{ binary    } = qr/ \G $wspace ($binary) $wspace /x;
       $self->{ tertiary  } = qr/ \G $wspace ($tertiary->[0]) $wspace /x;
       $self->{ otherwise } = qr/ \G $wspace ($tertiary->[1]) $wspace /x;
  +    $self->{ tag_start } = qr/ \G $wspace ($config->{ tag_start }) /x
  +        if $config->{ tag_start };
       $self->{ tag_end   } = qr/ (?= \G $wspace $tag_end ) /sx
           if $tag_end;
   
  @@ -367,7 +373,7 @@
   
   sub parse_term {
       my ($self, $textref) = @_;
  -    my ($term);
  +    my ($term, $tag);
   
       $self->debug("parse_term(", $self->next_chunk($textref), ")\n")
           if $DEBUG;
  @@ -375,8 +381,14 @@
       # skip any leading whitespace
       # $$textref =~ /$self->{ wspace }/cgx;
   
  +
       # match one of the term types
  -    if ($$textref =~ /$NUMBER/cog) {
  +
  +    if (($tag = $self->{ tag_start }) && ($$textref =~ /$tag/cg )) {
  +        # the start of a nested tag
  +        return $self->parse_tag($textref, $1);
  +    }
  +    elsif ($$textref =~ /$NUMBER/cog) {
           $term = [ number => $1 ];
       }
       elsif ($$textref =~ /$SQUOTE/cog) {
  @@ -435,6 +447,44 @@
   
   
   
  +sub parse_tag {
  +    my ($self, $textref, $start) = @_;
  +    
  +    $self->debug("parse_tag(", $start, $self->next_chunk($textref), ")\n")
  +        if $DEBUG;
  +
  +    # NOTE: temporary hack initiated by T::Tag::Directive scan()
  +    my $match = $self->{ match } 
  +        || return $self->error("no match data to parse tag");
  +    my $tag = $match->{ tag } 
  +        || return $self->error("no tag object");
  +    my $handler = $match->{ handler } 
  +        || return $self->error("no tag handler");
  +
  +    # count any newlines consumed between last known offset (e.g. start
  +    # of outer tag) and current position
  +    my $off   = $match->{ offset };
  +    my $pos   = pos $$textref;
  +    my $sub   = substr($$textref, $off, $pos - $off);
  +    my $lines = ($sub =~ tr/\n//);
  +
  +    # create a new handler, detached from the current handler
  +    $handler = $handler->new();
  +
  +    $match = {
  +        text    => $textref,
  +        line    => $match->{ line } + $lines,
  +        start   => $start,
  +        offset  => $pos,
  +    };
  +    $handler = $tag->scan($textref, $handler, $match)
  +        || return $self->error($tag->error());
  +    
  +    return $handler->end()
  +        || $self->error($handler->error());
  +}
  +
  +
   #========================================================================
   # terminals and other similar simple productions
   #========================================================================
  @@ -652,13 +702,13 @@
   
       my $pos = pos $$textref;
   
  -    if ($$textref =~ /$FILENAME/cog) {
  +    if ($$textref =~ /$FILEPATH/cog) {
           # unquoted filename, but make sure it's not a directive keyword
           if ($self->{ directives }->{ $1 }) {
               pos $$textref = $pos;
               return $self->decline("not a path (got keyword: $1)");
           }
  -        $term = [ filename => $1 ];
  +        $term = [ path => $1 ];
       }
       elsif ($$textref =~ /$SQUOTE/cog) {
           $term = [ squote => $1 ];
  @@ -697,6 +747,35 @@
   
   
   #------------------------------------------------------------------------
  +# parse_paths()
  +#
  +# Parse one or more template paths separated by '+'.
  +#------------------------------------------------------------------------
  +
  +sub parse_paths {
  +    my ($self, $textref) = @_;
  +    my ($path, @paths);
  +
  +    $self->debug("parse_paths(", $self->next_chunk($textref), ")") if $DEBUG;
  +
  +    # skip any leading whitespace, comments, etc.
  +    $$textref =~ /$self->{ wspace }/cg;
  +
  +    while ($path = $self->parse_path($textref)) {
  +        push(@paths, $path);
  +
  +        # skip plus sign and/or whitespace
  +        $$textref =~ /$self->{ pluspath }/cg;
  +    }
  +   
  +    # remove any trailing whitespace    (TODO: is this required?)
  +    $$textref =~ /$self->{ wspace }/cg;
  +
  +    return [ paths => \@paths ];
  +}
  +
  +
  +#------------------------------------------------------------------------
   # parse_static_path($textref)
   #
   # Wrapper around parse_path() which sets the 'static' option to 1.
  @@ -735,16 +814,6 @@
   
   
   
  -#------------------------------------------------------------------------
  -# parse_paths()
  -#
  -# Parse one or more template paths separated by '+'.
  -#------------------------------------------------------------------------
  -
  -sub parse_paths {
  -    my $self = shift;
  -    return $self->error("parse_paths() not yet implemented");
  -}
   
   
   
  @@ -2576,7 +2645,7 @@
   
   =head1 VERSION
   
  -$Revision: 1.18 $
  +$Revision: 1.19 $
   
   =head1 COPYRIGHT