use strict; #use warnings; package RDF::Notation3::Template::TReader; require 5.005_62; use Carp; ############################################################ sub get { my ($self) = @_; unless ($self->{tokens}->[0]) { $self->_more_tokens; } return shift @{$self->{tokens}}; } sub try { my ($self) = @_; unless ($self->{tokens}->[0]) { $self->_more_tokens; } return $self->{tokens}->[0]; } sub _more_tokens { my ($self) = @_; $self->{currentline} = $self->_new_line; my $line = \$self->{currentline}; unless ($$line) { push @{$self->{tokens}}, ' EOF '; return; } while (1) { last unless $$line; my $token; if ( $$line =~ /^\"/ ) { my $tok = $self->_get_string; push @{$self->{tokens}}, $tok; } elsif ( $$line =~ /^\s+/ ) { $$line = $'; } # " is sticked to the previous character, such as (" elsif ( $$line =~ /^([^\s\"]+)\"/ ) { $$line = '"' . $'; push @{$self->{tokens}}, $1; } elsif ( $$line =~ /^(\S+)/ ) { $$line = $'; push @{$self->{tokens}}, $1; } } push @{$self->{tokens}}, ' EOL '; } # returns a quoted string to be eval'ed sub _get_string { my $self = shift; my $lineref = \$self->{currentline}; # Handle escaped newlines my $have_escaped_newlines = ($$lineref =~ /\\\n$/); # Check if it's a python string if ( $$lineref =~ /^\"{3}/ ) { return $self->_get_triple_quoted_string; } my @parts = split /\"/, $$lineref; # First part should be empty shift @parts; my $return = ""; my $part; while ( $part = shift @parts ) { $return .= $part; last unless $return =~ /\\$/; $return .= '"'; } # if chewed up everything and not ending in a quote if ( @parts == 0 && $$lineref !~ /[^\\]\"$/) { # Escaped newlines should be ignored. if ( $have_escaped_newlines ) { # if there are more lines my $line = $self->_new_line(1); if ( $line ) { # tack them on and try again. $$lineref .= $line; return $self->_get_string( $lineref ); } } $self->_do_error(111, $$lineref); } $$lineref = join '"', @parts; return "\"$return\""; } sub _get_triple_quoted_string { my $self = shift; my $lineref = \$self->{currentline}; if ( $$lineref =~ /^\"{6}/ ) { $$lineref = $'; return "\"\""; } elsif ( $$lineref =~ /^\"{3}(.*?[^\\])\"{3}/ ) { $$lineref = $'; my $tok = $1; # quote unquoted double quotes while ($tok =~ s/(^|[^\\])\"/$1\\\"/ ){} return "\"$tok\""; } my $return = $$lineref; my $line = ""; while ( $line = $self->_new_line(1) ) { if ( $line =~ /^((.*?[^\\])?\"{3})/ ) { $return .= $1; $$lineref = $'; # remove the surrounding quotes $return =~ s/^\"{3}//; $return =~ s/\"{3}$//; # Handle escaped newlines $return =~ s/\\\n//g; # quote unquoted double quotes while ($return =~ s/(^|[^\\])\"/$1\\\"/ ){} return "\"$return\""; } else { $return .= $line; } } # Ran out of lines! $self->_do_error(113, $return); } sub _do_error { my ($self, $n, $tk) = @_; my %msg = ( 111 => 'string1 ("...") is not terminated', 113 => 'string2 ("""...""")is not terminated', 114 => 'string1 ("...") can\'t include newlines', ); my $msg = "[Error $n]"; $msg .= " line $self->{ln}, token" if $n > 100; $msg .= " \"$tk\"\n"; $msg .= "$msg{$n}!\n"; croak $msg; } 1; __END__ # Below is a documentation. =head1 NAME RDF::Notation3::Template::TReader - RDF Notation3 file reader template =head1 LICENSING Copyright (c) 2001 Ginger Alliance. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR Petr Cimprich, petr@gingerall.cz =head1 SEE ALSO perl(1), RDF::Notation3. =cut