4 # Copyright (C) 2002-2005, The Perl Foundation.
5 # This program is free software. It is subject to the same license
6 # as the Parrot interpreter.
14 package Jako
::Processor
;
23 confess
"Subclass responsibility";
34 $self->{DEBUG
} = shift;
37 return $self->{DEBUG
};
47 if (@_) { $self->{FILE
} = shift; }
49 return defined $self->{FILE
} ?
$self->{FILE
} : '<NO FILE>';
59 if (@_) { $self->{LINE
} = shift; }
61 return defined $self->{LINE
} ?
$self->{LINE
} : '';
64 ###############################################################################
65 ###############################################################################
69 ###############################################################################
70 ###############################################################################
80 $self->{TOKENS
} = [@_];
83 return @
{ $self->{TOKENS
} };
90 # Returns the number of tokens.
96 return scalar( @
{ $self->{TOKENS
} } );
102 # Returns (or sets) the abolute position.
109 if ( defined $pos ) {
110 my $count = scalar( @
{ $self->{TOKENS
} } );
112 $pos = -1 if $pos < 0; # Just before the beginning
113 $pos = $count if $pos > $count; # Just past the end (in case we get more tokens)
117 $self->file( $self->at($pos)->file );
118 $self->line( $self->at($pos)->line );
121 return defined $self->{POS
} ?
$self->{POS
} : -1;
127 # Without an argument, gives the current token. With an argument, gives the
128 # token at that absolute position. If a count is given, then that many tokens
129 # (at most, given the possibilitiy of running off the end) are returned. If
130 # a count is not given, 1 is inferred.
135 my ( $index, $count ) = @_;
137 $index = $self->pos unless defined $index;
139 $count = 1 unless defined $count;
141 $self->INTERNAL_ERROR( "Attempt to get fewer than 1 token (%s)!", $count )
145 return map { $self->at( $index + $_ ) } ( 0 .. $count );
148 my $pos = $self->pos;
150 $self->INTERNAL_ERROR("Position is not defined") unless defined $pos;
152 return Jako
::Token
->BOF if $index < 0;
153 return Jako
::Token
->EOF if $index >= @
{ $self->{TOKENS
} };
155 return $self->{TOKENS
}[$index];
161 # Without an argument, gives the current token. With an argument, gives the
162 # token at that offset from the current one. If a count is given, then that
163 # many tokens (at most, given the possibility of running of the end) are
164 # returned. If a count is not given, 1 is inferred.
169 my ( $offset, $count ) = @_;
171 $offset = 0 unless defined $offset;
173 my $pos = $self->pos;
175 $self->INTERNAL_ERROR("Position is not defined") unless defined $pos;
176 $self->INTERNAL_ERROR("Offset is not defined") unless defined $offset;
178 # DEBUG(0, "Current position is $pos");
181 # DEBUG(0, "Getting token at $pos");
183 return $self->at( $pos, $count );
189 # Moves the current token position $offset tokens forward. Returns the
190 # token at the new absolute position.
197 $offset = 1 unless defined $offset;
199 my $pos = $self->pos;
201 $self->INTERNAL_ERROR("Position is undefined") unless defined $pos;
203 # DEBUG(0, "Position starts as $pos");
207 # DEBUG(0, "Setting position to $pos");
210 # DEBUG(0, "forth(): Position is now %d", $self->pos);
212 my $token = $self->get;
214 $self->file( $token->file );
215 $self->line( $token->line );
223 # Moves the current token position $offset tokens backward. Returns the new
231 $offset = 1 unless defined $offset;
233 return $self->forth( -$offset );
246 my $tok = $self->forth;
248 printf STDERR
"%6d : %-30s : %5s : %-15s: %1s : %s\n", $self->pos, $tok->file, $tok->line,
249 $tok->kind, $tok->type || '', $tok->text;
251 last if $tok->is_eof;
256 foreach (my $i = 0; $i < scalar(@{$self->{TOKENS}}); $i++) {
257 my $tok = $self->at($i);
259 printf STDERR "%6d : %-30s : %5s : %-15s: %1s : %s\n",
267 last if $tok->is_eof;
277 # Require consumes and returns the token if the requirement is met, otherwise
278 # a Syntax Error is raised.
280 # If more than one type is specified, the semantics are "or".
286 # DEBUG(0, "Requiring '$kind'");
289 "Expected %s, but found '%s'.",
290 @_ > 1 ?
"one of (" . join( ", ", @_ ) . ")" : $_[0],
292 ) unless grep { $self->get(1)->kind eq $_ } @_;
301 sub require_assign
{ return shift->require('assign'); }
302 sub require_close_brace
{ return shift->require('close-brace'); }
303 sub require_close_bracket
{ return shift->require('close-bracket'); }
304 sub require_close_paren
{ return shift->require('close-paren'); }
305 sub require_comma
{ return shift->require('comma'); }
306 sub require_ident
{ return shift->require('ident'); }
307 sub require_literal
{ return shift->require('literal'); }
308 sub require_open_brace
{ return shift->require('open-brace'); }
309 sub require_open_bracket
{ return shift->require('open-bracket'); }
310 sub require_open_paren
{ return shift->require('open-paren'); }
311 sub require_infix_rel
{ return shift->require('infix-rel'); }
312 sub require_semicolon
{ return shift->require('semicolon'); }
313 sub require_type
{ return shift->require('type'); }
315 sub require_value
{ return shift->require( 'ident', 'literal' ); }
320 # Skips the token type specified if it is present. Returns undef if nothing
321 # was skipped, otherwise returns the token skipped.
323 # If more than one type is specified, the semantics are "or".
330 return undef unless grep { $self->get(1)->kind eq $_ } @_;
339 sub skip_assign
{ return shift->skip('assign'); }
340 sub skip_colon
{ return shift->skip('colon'); }
341 sub skip_comma
{ return shift->skip('comma'); }
342 sub skip_close_brace
{ return shift->skip('close-brace'); }
343 sub skip_close_bracket
{ return shift->skip('close-bracket'); }
344 sub skip_close_paren
{ return shift->skip('close-paren'); }
345 sub skip_ident
{ return shift->skip('ident'); }
346 sub skip_literal
{ return shift->skip('literal'); }
347 sub skip_new
{ return shift->skip('new'); }
348 sub skip_open_brace
{ return shift->skip('open-brace'); }
349 sub skip_open_bracket
{ return shift->skip('open-bracket'); }
350 sub skip_open_paren
{ return shift->skip('open-paren'); }
351 sub skip_infix_rel
{ return shift->skip('infix-rel'); }
352 sub skip_semicolon
{ return shift->skip('semicolon'); }
353 sub skip_type
{ return shift->skip('type'); }
355 sub skip_value
{ return shift->skip( 'ident', 'literal' ); }
357 ###############################################################################
358 ###############################################################################
362 ###############################################################################
363 ###############################################################################
370 my ( $self, $level, $format, @args ) = @_;
372 return unless defined $self->debug and $self->debug >= $level;
374 my $message = $format ?
sprintf( $format, @args ) : '<no message>';
376 printf STDERR
"%s [%s]: Debug message: %s\n", $self->file, $self->line, $message;
384 my ( $self, $format, @args ) = @_;
386 my $message = sprintf( $format, @args );
388 print STDERR
"%s [%s]: Warning: %s", $self->file, $self->line, $message;
396 my ( $self, $kind, $format, @args ) = @_;
398 my $message = sprintf( $format, @args );
400 $message = sprintf( "%s [%s]: %s error: %s", $self->file, $self->line, $kind, $message );
402 if ( $self->debug ) { confess
$message; }
403 else { die "$message\n"; }
411 my ( $self, $format, @args ) = @_;
412 $self->ERROR( 'Parse', $format, @args );
420 my ( $self, $format, @args ) = @_;
421 $self->ERROR( 'Syntax', $format, @args );
429 my ( $self, $format, @args ) = @_;
430 $self->ERROR( 'Internal', $format, @args );
438 # cperl-indent-level: 4
441 # vim: expandtab shiftwidth=4: