sub
new {
my
$class
=
shift
;
bless
{
@_
},
$class
;
}
sub
init {
my
$self
=
shift
;
@{
$self
}{
qw(Declarator Offset)
} =
@_
;
return
$self
;
}
sub
offset {
my
$self
=
shift
;
return
$self
->{Offset}
}
sub
inc_offset {
my
$self
=
shift
;
$self
->{Offset} +=
shift
;
}
sub
declarator {
my
$self
=
shift
;
return
$self
->{Declarator}
}
sub
skip_declarator {
my
$self
=
shift
;
my
$decl
=
$self
->declarator;
my
$len
= Devel::Declare::toke_scan_word(
$self
->offset, 0);
confess
"Couldn't find declarator '$decl'"
unless
$len
;
my
$linestr
=
$self
->get_linestr;
my
$name
=
substr
(
$linestr
,
$self
->offset,
$len
);
confess
"Expected declarator '$decl', got '${name}'"
unless
$name
eq
$decl
;
$self
->inc_offset(
$len
);
}
sub
skipspace {
my
$self
=
shift
;
$self
->inc_offset(Devel::Declare::toke_skipspace(
$self
->offset));
}
sub
get_linestr {
my
$self
=
shift
;
my
$line
= Devel::Declare::get_linestr();
return
$line
;
}
sub
set_linestr {
my
$self
=
shift
;
my
(
$line
) =
@_
;
Devel::Declare::set_linestr(
$line
);
}
sub
strip_name {
my
$self
=
shift
;
$self
->skipspace;
if
(
my
$len
= Devel::Declare::toke_scan_word(
$self
->offset, 1 )) {
my
$linestr
=
$self
->get_linestr();
my
$name
=
substr
(
$linestr
,
$self
->offset,
$len
);
substr
(
$linestr
,
$self
->offset,
$len
) =
''
;
$self
->set_linestr(
$linestr
);
return
$name
;
}
$self
->skipspace;
return
;
}
sub
strip_ident {
my
$self
=
shift
;
$self
->skipspace;
if
(
my
$len
= Devel::Declare::toke_scan_ident(
$self
->offset )) {
my
$linestr
=
$self
->get_linestr();
my
$ident
=
substr
(
$linestr
,
$self
->offset,
$len
);
substr
(
$linestr
,
$self
->offset,
$len
) =
''
;
$self
->set_linestr(
$linestr
);
return
$ident
;
}
$self
->skipspace;
return
;
}
sub
strip_proto {
my
$self
=
shift
;
$self
->skipspace;
my
$linestr
=
$self
->get_linestr();
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
'('
) {
my
$length
= Devel::Declare::toke_scan_str(
$self
->offset);
my
$proto
= Devel::Declare::get_lex_stuff();
Devel::Declare::clear_lex_stuff();
$linestr
=
$self
->get_linestr();
substr
(
$linestr
,
$self
->offset,
$length
) =
''
;
$self
->set_linestr(
$linestr
);
return
$proto
;
}
return
;
}
sub
strip_names_and_args {
my
$self
=
shift
;
$self
->skipspace;
my
@args
;
my
$linestr
=
$self
->get_linestr;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
'('
) {
substr
(
$linestr
,
$self
->offset, 1) =
''
;
$self
->set_linestr(
$linestr
);
$self
->skipspace;
while
(1) {
my
$thing
=
$self
->strip_name;
confess
"failed to parse bareword. found ${linestr}"
unless
defined
$thing
;
$linestr
=
$self
->get_linestr;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
'('
) {
push
(
@args
, [
$thing
,
$self
->strip_proto ]);
}
else
{
push
(
@args
, [
$thing
,
undef
]);
}
$self
->skipspace;
$linestr
=
$self
->get_linestr;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
','
) {
substr
(
$linestr
,
$self
->offset, 1) =
''
;
$self
->set_linestr(
$linestr
);
$self
->skipspace;
}
else
{
last
;
}
}
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
')'
) {
substr
(
$linestr
,
$self
->offset, 1) =
''
;
$self
->set_linestr(
$linestr
);
$self
->skipspace;
}
else
{
confess
"couldn't find closing paren for argument. found ${linestr}"
}
}
else
{
my
$thing
=
$self
->strip_name;
confess
"failed to parse bareword. found ${linestr}"
unless
defined
$thing
;
$linestr
=
$self
->get_linestr;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
'('
) {
push
(
@args
, [
$thing
,
$self
->strip_proto ]);
}
else
{
push
(
@args
, [
$thing
,
undef
]);
}
}
return
\
@args
;
}
sub
strip_attrs {
my
$self
=
shift
;
$self
->skipspace;
my
$linestr
= Devel::Declare::get_linestr;
my
$attrs
=
''
;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
':'
) {
while
(
substr
(
$linestr
,
$self
->offset, 1) ne
'{'
) {
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
':'
) {
substr
(
$linestr
,
$self
->offset, 1) =
''
;
Devel::Declare::set_linestr(
$linestr
);
$attrs
.=
':'
;
}
$self
->skipspace;
$linestr
= Devel::Declare::get_linestr();
if
(
my
$len
= Devel::Declare::toke_scan_word(
$self
->offset, 0)) {
my
$name
=
substr
(
$linestr
,
$self
->offset,
$len
);
substr
(
$linestr
,
$self
->offset,
$len
) =
''
;
Devel::Declare::set_linestr(
$linestr
);
$attrs
.=
" ${name}"
;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
'('
) {
my
$length
= Devel::Declare::toke_scan_str(
$self
->offset);
my
$arg
= Devel::Declare::get_lex_stuff();
Devel::Declare::clear_lex_stuff();
$linestr
= Devel::Declare::get_linestr();
substr
(
$linestr
,
$self
->offset,
$length
) =
''
;
Devel::Declare::set_linestr(
$linestr
);
$attrs
.=
"(${arg})"
;
}
}
}
$linestr
= Devel::Declare::get_linestr();
}
return
$attrs
;
}
sub
get_curstash_name {
return
Devel::Declare::get_curstash_name;
}
sub
shadow {
my
$self
=
shift
;
my
$pack
=
$self
->get_curstash_name;
Devel::Declare::shadow_sub(
$pack
.
'::'
.
$self
->declarator,
$_
[0] );
}
sub
inject_if_block {
my
$self
=
shift
;
my
$inject
=
shift
;
my
$before
=
shift
||
''
;
$self
->skipspace;
my
$linestr
=
$self
->get_linestr;
if
(
substr
(
$linestr
,
$self
->offset, 1) eq
'{'
) {
substr
(
$linestr
,
$self
->offset + 1, 0) =
$inject
;
substr
(
$linestr
,
$self
->offset, 0) =
$before
;
$self
->set_linestr(
$linestr
);
return
1;
}
return
0;
}
sub
scope_injector_call {
my
$self
=
shift
;
my
$inject
=
shift
||
''
;
return
' BEGIN { '
.
ref
(
$self
) .
"->inject_scope('${inject}') }; "
;
}
sub
inject_scope {
my
$class
=
shift
;
my
$inject
=
shift
;
on_scope_end {
my
$linestr
= Devel::Declare::get_linestr;
return
unless
defined
$linestr
;
my
$offset
= Devel::Declare::get_linestr_offset;
substr
(
$linestr
,
$offset
, 0 ) =
';'
.
$inject
;
Devel::Declare::set_linestr(
$linestr
);
};
}
1;