Devel-Declare-Lexer
view release on metacpan or search on metacpan
lib/Devel/Declare/Lexer.pm view on Meta::CPAN
no strict 'refs';
my %subinject = ();
if(ref($args[0]) =~ /HASH/) {
$DEBUG and print STDERR "Using hash for import\n";
%subinject = %{$args[0]};
@args = keys %subinject;
}
my @consts;
my %tags = map { $_ => 1 } @args;
if($tags{":debug"}) {
$DEBUG = 1;
}
if($tags{":lexer_test"}) {
$DEBUG and print STDERR "Adding 'lexer_test' to keyword list\n";
push @consts, "lexer_test";
}
my @names = @args;
for my $name (@names) {
next if $name =~ /:/;
$DEBUG and print STDERR "Adding '$name' to keyword list\n";
push @consts, $name;
}
for my $word (@consts) {
$DEBUG and print STDERR "Injecting '$word' into '$caller'\n";
Devel::Declare->setup_for(
$caller,
{
$word => { const => \&lexer }
}
);
if($subinject{$word}) {
$DEBUG and print STDERR "- Using sub provided in import\n";
*{$caller.'::'.$word} = $subinject{$word};
} else {
$DEBUG and print STDERR "- Using default sub\n";
*{$caller.'::'.$word} = sub () { 1; };
}
}
}
my %named_lexed_stack = ();
sub lexed
{
my ($key, $callback) = @_;
$DEBUG and print STDERR "Registered callback for keyword '$key'\n";
$named_lexed_stack{$key} = $callback;
}
sub call_lexed
{
my ($name, $stream) = @_;
$DEBUG and print STDERR "Checking for callbacks for keyword '$name'\n";
$DEBUG and print STDERR Dumper($stream) . "\n";
my $callback = $named_lexed_stack{$name};
if($callback) {
$DEBUG and print STDERR "Found callback '$callback' for keyword '$name'\n";
$stream = &$callback($stream);
}
$DEBUG and print STDERR Dumper($stream) . "\n";
return $stream;
}
sub lexer
{
my ($symbol, $offset) = @_;
$DEBUG and print "=" x 80, "\n";
my $linestr = Devel::Declare::get_linestr;
my $original_linestr = $linestr;
my $original_offset = $offset;
$DEBUG and print STDERR "Starting with linestr '$linestr'\n";
my @tokens = ();
tie @tokens, "Devel::Declare::Lexer::Stream";
my ($len, $tok);
my $eoleos = 0;
my $line = 1;
# Skip the declarator
$offset += Devel::Declare::toke_move_past_token($offset);
push @tokens, new Devel::Declare::Lexer::Token::Declarator( value => $symbol );
$DEBUG and print STDERR "Skipped declarator '$symbol'\n";
my %lineoffsets = ( 1 => $offset );
# We call this from a few places inside the loop
my $skipspace = sub {
# Move past any whitespace
$len = Devel::Declare::toke_skipspace($offset);
if($len > 0) {
$tok = substr($linestr, $offset, $len);
$DEBUG and print STDERR "Skipped whitespace '$tok', length [$len]\n";
push @tokens, new Devel::Declare::Lexer::Token::Whitespace( value => $tok );
$offset += $len;
if($tok =~ /\n/) {
# its odd that this works without handling any line numbering
# I think we end up here when an end of line is found after a bareword (e.g. print\n"something")
# It probably still needs some work on line numbering, but everything just seems to work!
$DEBUG and print STDERR "Got end of line in skipspace, probable bareword preceeding EOL\n";
Devel::Declare::clear_lex_stuff;
# We've got a new line so we need to refresh our linestr
$linestr = Devel::Declare::get_linestr;
$original_linestr = $linestr;
$DEBUG and print STDERR "Refreshed linestr [$linestr]\n";
}
( run in 0.582 second using v1.01-cache-2.11-cpan-0b5f733616e )