/usr/local/CPAN/Text-PORE/Text/PORE/Node.pm
# Node -- generic parse tree node ("abstract class")
# lineno (scalar): corresponding line number in source code (for debugging)
package Text::PORE::Node;
use strict;
use Exporter;
@Text::PORE::Node::ISA = qw(Exporter);
$Text::PORE::Node::debug = 0;
use Text::PORE::Node::Attr;
use Text::PORE::Node::Container;
use Text::PORE::Node::Freetext;
use Text::PORE::Node::If;
use Text::PORE::Node::Standalone;
use Text::PORE::Node::Queue;
sub new {
my $type = shift;
my $lineno = shift;
my ($self) = { };
bless $self, ref($type) || $type;
$self->setLineNo($lineno);
$self->{'errors'} = [ ];
$self;
}
sub setLineNo {
my $self = shift;
my $lineno = shift;
$self->{'lineno'} = $lineno;
}
# a 'final' method
sub setDebug {
my $self = shift;
my $value = shift;
$Node::debug = $value;
}
# a 'final' method
sub getDebug {
my $self = shift;
$Node::debug;
}
# a 'final' method
sub setOutput {
my $self = shift;
my $output = shift;
$Node::output = $output;
}
# a 'final' method
sub output {
my $self = shift;
my $output = shift;
$Node::output->print($output);
}
# A "virtual" method
sub traverse {
my $self = shift;
my $context = shift;
my $globals = shift;
# need to return an empty list of error messages
[ ];
}
sub error {
my $self = shift;
my $text = join('',@_); # not always needed, but it's easy enough to do
# push onto the error list; if it's an array ref, push the array,
# else push the string prepended by the line number
# note - we would rather just use push, but it won't work on anon arrays
$self->{'errors'} =
[
@{$self->{'errors'}} ,
(ref $_[0] eq 'ARRAY' ? @{$_[0]} : "$self->{'lineno'}: $text\n"),
];
}
sub errorDump {
my $self = shift;
my $errors = $self->{'errors'};
$self->{'errors'} = [ ];
$errors;
}
sub retrieveSlot {
my $self = shift; # operating node
my $globals = shift; # global objects to assist in lookup
my $slot = shift; # name of slot to lookup
my ($lineno) = $self->{'lineno'};
my ($obj);
my (@attr_list);
unless (defined($slot)) {
return undef;
}
@attr_list = split(/\./, $slot);
# if it's explicitly a global object, start from there,
# else default to _context
if ($attr_list[0] =~ m/^_/) {
$obj = $globals->GetAttribute($attr_list[0]);
unless (ref($obj)) {
$self->error("'$attr_list[0] is not a defined global object");
return undef;
}
shift @attr_list;
} else {
$obj = $globals->GetAttribute('_context');
}
# Get attribute by parsing dot-notation
while (@attr_list) {
my $attr = shift @attr_list;
if (! ref($obj) || ref($obj) =~ /(ARRAY|HASH)/) {
$self->error("Attempt to take attribute '$attr' from non-object");
return "";
}
$obj = $obj->GetAttribute($attr);
}
return $obj;
}
1;