package Text::Xslate::Symbol;
use Any::Moose;
use Text::Xslate::Util qw(p $DEBUG);
use overload
bool => sub() { 1 },
'""' => sub { $_[0]->id },
fallback => 1,
;
our @CARP_NOT = qw(Text::Xslate::Parser);
use constant _DUMP_DENOTE => scalar($DEBUG =~ /\b dump=denote \b/xmsi);
has id => (
is => 'rw',
isa => 'Str',
required => 1,
);
has lbp => ( # left binding power
is => 'rw',
isa => 'Int',
lazy => 1,
default => 0,
);
has ubp => ( # unary binding power
is => 'rw',
isa => 'Int',
required => 0,
);
has value => (
is => 'rw',
lazy => 1,
builder => 'id',
trigger => sub {
my($self) = @_;
$self->is_value(1);
return;
},
# default => sub{
# if(!defined $_[0]) { #XXX: Any::Moose::XS's bug
# my(undef, $file, $line) = caller;
# warn "[bug] no invocant at $file line $line.\n";
# return '(null)';
# }
# return $_[0]->id
# },
);
# some tokens have the counterpart token (e.g. '{' to '}')
has counterpart => (
is => 'rw',
isa => 'Str',
required => 0,
);
# flags
has [
'is_reserved', # set by reserve()
'is_defined', # set by define()
'is_block_end', # block ending markers
'is_logical', # logical operators
'is_comma', # comma like operators
'is_value', # symbols with values
'is_statement', # expr but a statement (e.g. assignment)
'can_be_modifier', # statement modifiers (e.g. expr if cond)
] => (
is => 'rw',
isa => 'Bool',
required => 0,
);
has nud => ( # null denotation
is => 'bare',
isa => 'CodeRef',
writer => 'set_nud',
reader => 'get_nud',
predicate => 'has_nud',
clearer => 'remove_nud',
trigger => sub{
my($self) = @_;
$self->is_value(1);
return;
},
lazy_build => 1,
required => 0,
);
has led => ( # left denotation
is => 'bare',
isa => 'CodeRef',
writer => 'set_led',
reader => 'get_led',
predicate => 'has_led',
clearer => 'remove_led',
lazy_build => 1,
required => 0,
);
has std => ( # statement denotation
is => 'bare',
isa => 'CodeRef',
writer => 'set_std',
reader => 'get_std',
predicate => 'has_std',
clearer => 'remove_std',
lazy_build => 1,
required => 0,
);
has [qw(first second third)] => (
is => 'rw',
required => 0,
);
has type => (
is => 'rw',
isa => 'Str',
required => 0,
);
has arity => (
is => 'rw',
isa => 'Str',
lazy => 1,
default => 'name',
required => 0,
);
has assignment => (
is => 'rw',
isa => 'Bool',
required => 0,
);
#has scope => (
# is => 'rw',
# isa => 'HashRef',
#
# required => 0,
#);
has line => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => 0,
);
sub _build_nud {
return \&_nud_default;
}
sub _build_led {
return \&_led_default;
}
sub _build_std {
return \&_std_default;
}
sub _nud_default {
my($parser, $symbol) = @_;
return $parser->default_nud($symbol);
}
sub _led_default {
my($parser, $symbol) = @_;
return $parser->default_led($symbol);
}
sub _std_default {
my($parser, $symbol) = @_;
return $parser->default_std($symbol);
}
sub nud {
my($self, $parser, @args) = @_;
$self->_dump_denote('nud', $parser) if _DUMP_DENOTE;
return $self->get_nud()->($parser, $self, @args);
}
sub led {
my($self, $parser, @args) = @_;
$self->_dump_denote('led', $parser) if _DUMP_DENOTE;
return $self->get_led()->($parser, $self, @args);
}
sub std {
my($self, $parser, @args) = @_;
$self->_dump_denote('std', $parser) if _DUMP_DENOTE;
return $self->get_std()->($parser, $self, @args);
}
sub clone {
my $self = shift;
return $self->meta->clone_object($self, @_);
}
sub _dump_denote {
my($self, $type, $parser) = @_;
my $attr = $self->meta->get_attribute($type);
my $entity = $attr->has_value($self)
? $attr->get_value($self)
: $parser->can('default_' . $type);
require B;
my $cvgv = B::svref_2object($entity)->GV;
printf STDERR "%s: %s::%s (%s:%s)\n",
$type,
$cvgv->STASH->NAME, $cvgv->NAME,
$self->id, $self->line,
;
}
no Any::Moose;
__PACKAGE__->meta->make_immutable;
__END__
=head1 NAME
Text::Xslate::Symbol - The symbol representation used by parsers and compilers
=cut