Chess-Plisco
view release on metacpan or search on metacpan
lib/Chess/Plisco/Macro.pm view on Meta::CPAN
my $code = pop @args;
$code = '' if !defined $code;
if (exists $defines{$name}) {
require Carp;
Carp::croak("duplicate macro definition '$name'");
}
my $code_doc = PPI::Document->new(\$code);
if (!$code_doc) {
require Carp;
my $msg = $@->message;
Carp::croak("cannot parse code for '$name': $msg\n");
}
$code_doc->prune('PPI::Token::Comment');
$defines{$name} = {
args => [@args],
code => $code_doc,
};
return;
}
sub _define_from_file {
my ($name, @args) = @_;
my $relname = pop @args;
my $filename = __FILE__;
$filename =~ s{\.pm$}{/$relname};
open my $fh, '<', $filename
or die "cannot open '$filename' for reading: $!";
my $code = join '', <$fh>;
return _define $name, @args, $code;
}
sub _extract_arguments {
my ($word) = @_;
my $parent = $word->parent;
my @siblings = $parent->children;
my $pos;
for (my $i = 0; $i < @siblings; ++$i) {
if ($siblings[$i] == $word) {
$pos = $i;
last;
}
}
return if !defined $pos;
# No arguments?
return if $pos == $#siblings;
# Skip insignicant tokens.
my $argidx;
for (my $i = $pos + 1; $i < @siblings; ++$i) {
if ($siblings[$i]->significant) {
$argidx = $i;
last;
}
}
return if !defined $argidx;
my @argnodes;
my $argnodes_parent = $parent;
if ($siblings[$argidx]->isa('PPI::Token::Structure')) {
# No arguments.
return;
} elsif ($siblings[$argidx]->isa('PPI::Structure::List')) {
# Call with parentheses. The only child should be an expression.
my @expression = $siblings[$argidx]->children;
return if @expression != 1;
$argnodes_parent = $expression[0];
return if !$argnodes_parent->isa('PPI::Statement::Expression');
@argnodes = $argnodes_parent->children;
} else {
for (my $i = $argidx; $i < @siblings; ++$i) {
# Call without parentheses.
if ($siblings[$i]->isa('PPI::Token::Structure')
&& ';' eq $siblings[$i]->content) {
last;
}
push @argnodes, $siblings[$i];
}
}
return _split_arguments $argnodes_parent, @argnodes;
}
sub _split_arguments {
my ($parent, @argnodes) = @_;
my @arguments;
my @argument;
for (my $i = 0; $i < @argnodes; ++$i) {
my $argnode = $argnodes[$i];
$parent->remove_child($argnode);
if ($argnode->isa('PPI::Token::Operator')
&& ',' eq $argnode->content) {
push @arguments, [@argument];
undef @argument;
} else {
push @argument, $argnode;
}
}
push @arguments, [@argument] if @argument;
foreach my $argument (@arguments) {
while (!$argument->[0]->significant) {
shift @$argument;
}
while (!$argument->[-1]->significant) {
pop @$argument;
}
}
return @arguments;
}
1;
( run in 1.188 second using v1.01-cache-2.11-cpan-5735350b133 )