# # Parser.pm # # Copyright (C) 2001-2005, The Perl Foundation. # This program is free software. It is subject to the same license # as Perl itself. # # $Id: Parser.pm 16255 2006-12-25 22:20:28Z paultcochrane $ # use strict; use warnings; package Jako::Parser; use Carp; use base qw(Jako::Processor); use Jako::Construct::Block; use Jako::Construct::Block::Bare; use Jako::Construct::Block::Conditional::Else; use Jako::Construct::Block::Conditional::If; use Jako::Construct::Block::Conditional::Unless; use Jako::Construct::Block::File; use Jako::Construct::Block::Module; use Jako::Construct::Block::Sub; use Jako::Construct::Block::Loop::Continue; use Jako::Construct::Block::Loop::Until; use Jako::Construct::Block::Loop::While; use Jako::Construct::Declaration::Constant; use Jako::Construct::Declaration::Sub; use Jako::Construct::Declaration::Variable; use Jako::Construct::Expression::Call; use Jako::Construct::Expression::Value; use Jako::Construct::Expression::Value::Identifier; use Jako::Construct::Label; use Jako::Construct::Statement::Arithmetic; use Jako::Construct::Statement::Assign; use Jako::Construct::Statement::Bitwise; use Jako::Construct::Statement::Call; use Jako::Construct::Statement::Concat; use Jako::Construct::Statement::Decrement; use Jako::Construct::Statement::Goto; use Jako::Construct::Statement::Increment; use Jako::Construct::Statement::LoopControl; use Jako::Construct::Statement::New; use Jako::Construct::Statement::Return; # # new() # sub new { my $class = shift; my $root = Jako::Construct::Block::File->new( undef, # No parent 'file', # File scope undef, # No return type undef # No prefix ); return bless { DEBUG => 1, ANON_BLOCK_COUNT => 0, BLOCK_COUNT => 0, BLOCKS => [$root], # Block stack ROOT => $root, TOKENS => [] }, $class; } ############################################################################### ############################################################################### ## ## The Block Stack ## ## $block_count The total number of blocks begun (used for labels) ## @block_stack The stack of active blocks. We keep a block on the ## stack for the file scope. ## ## NOTE: Do NOT access the block stack directly. Access it via routines in ## this section of code. ## ############################################################################### ############################################################################### # # blocks() # sub blocks { my $self = shift; return @{ $self->{BLOCKS} }; } # # block() # sub block { my $self = shift; return $self->{BLOCKS}[shift]; } # # block_depth() # # Block depth zero is when the only block on the block stack is the file # scope block. Therefore, we return one less than the number of blocks on # the stack. # sub block_depth { my $self = shift; return scalar( $self->blocks ) - 1; } # # current_block() # # Returns the block on the top of the block stack. # sub current_block { my $self = shift; $self->INTERNAL_ERROR("Attempt to reference top block with empty block stack!") if scalar( $self->blocks ) == 0; return $self->block(-1); } # # push_block() # # Push a block on the top of the block stack. # sub push_block { my $self = shift; push @{ $self->{BLOCKS} }, shift; } # # pop_block() # # Pop the top block off the block stack and return it. Bounds checks the block # stack to make sure we don't pop off the file scope block. # sub pop_block { my $self = shift; $self->INTERNAL_ERROR("Attempt to pop file-scope block off block stack!") if scalar( $self->blocks ) == 1; return pop @{ $self->{BLOCKS} }; } ############################################################################### ############################################################################### ## ## MAIN PROGRAM ## ############################################################################### ############################################################################### # # Tokenize the input, and possibly dump the tokens. # sub parse { my $self = shift; my $root = $self->block(0); my $last_token = $self->at(-1); my $token = $self->at(-1); while (1) { $token = $self->forth; $last_token = $self->get(-1); last if $token->is_eof; # # Labels: # #