sub
register {
{
extends
=> [
qw(C)
],
overrides
=> [
qw(get_parser)
],
}
}
sub
get_parser {
Inline::C::_parser_test(
$_
[0]->{CONFIG}{DIRECTORY},
"Inline::C::Parser::RegExp::get_parser called\n"
)
if
$_
[0]->{CONFIG}{_TESTING};
bless
{},
'Inline::C::Parser::RegExp'
}
sub
code {
my
(
$self
,
$code
) =
@_
;
my
$RE_comment_C
=
q{(?:(?:\/\*)(?:(?:(?!\*\/)[\s\S])*)(?:\*\/))}
;
my
$RE_comment_Cpp
=
q{(?:\/\*(?:(?!\*\/)[\s\S])*\*\/|\/\/[^\n]*\n)}
;
my
$RE_quoted
= (
q{(?:(?:\")(?:[^\\\"]*(?:\\.[^\\\"]*)*)(?:\")}
.
q{|(?:\')(?:[^\\\']*(?:\\.[^\\\']*)*)(?:\'))}
);
our
$RE_balanced_brackets
;
$RE_balanced_brackets
=
qr'(?:[{]((?:(?>[^{}]+)|(??{$RE_balanced_brackets}))*)[}])'
;
our
$RE_balanced_parens
;
$RE_balanced_parens
=
qr'(?:[(]((?:(?>[^()]+)|(??{$RE_balanced_parens}))*)[)])'
;
$code
=~ s/
$RE_comment_C
/ /go;
$code
=~ s/
$RE_comment_Cpp
/ /go;
$code
=~ s/^\
$code
=~ s/
$RE_balanced_brackets
/{ }/go;
$self
->{_the_code_most_recently_parsed} =
$code
;
my
$normalize_type
=
sub
{
my
(
$type
) =
@_
;
$type
=~ s/\bextern\b//g;
$type
=~ s/\s+/ /g;
$type
=~ s/^\s//;
$type
=~ s/\s$//;
$type
=~ s/\*\s\*/\*\*/g;
$type
=~ s/(?<=[^ \*])\*/ \*/g;
return
$type
;
};
my
$re_plausible_place_to_begin_a_declaration
=
qr {
(?m: ^ ) \s*
}xo;
my
$sp
=
qr{[ \t]|\n(?![ \t]*\n)}
;
my
$re_type
=
qr{
(
(?: \w+ $sp* )+? # words
(?: \* $sp* )* # stars
)
}
xo;
my
$re_identifier
=
qr{ (\w+) $sp* }
xo;
$code
=~ s/\bconst\b//g;
while
(
$code
=~ m{
$re_plausible_place_to_begin_a_declaration
(
$re_type
$re_identifier
$RE_balanced_parens
$sp
* (\;|\{) )
}xgo
) {
my
(
$type
,
$identifier
,
$args
,
$what
) = ($2,$3,$4,$5);
$args
=
""
if
$args
=~ /^\s+$/;
my
$is_decl
=
$what
eq
';'
;
my
$function
=
$identifier
;
my
$return_type
=
&$normalize_type
(
$type
);
my
@arguments
=
split
','
,
$args
;
goto
RESYNC
if
$is_decl
&& !
$self
->{data}{AUTOWRAP};
goto
RESYNC
if
$self
->{data}{done}{
$function
};
goto
RESYNC
if
!
defined
$self
->{data}{typeconv}{valid_rtypes}{
$return_type
};
my
(
@arg_names
,
@arg_types
);
my
$dummy_name
=
'arg1'
;
foreach
my
$arg
(
@arguments
) {
my
$arg_no_space
=
$arg
;
$arg_no_space
=~ s/\s//g;
if
(
my
(
$type
,
$identifier
) =
$arg
=~ /^\s
*$re_type
(?:
$re_identifier
)?\s*$/o
) {
my
$arg_name
=
$identifier
;
my
$arg_type
=
&$normalize_type
(
$type
);
if
((!
defined
$arg_name
) && (
$arg_no_space
ne
'void'
)) {
goto
RESYNC
if
!
$is_decl
;
$arg_name
=
$dummy_name
++;
}
goto
RESYNC
if
((!
defined
$self
->{data}{typeconv}{valid_types}{
$arg_type
}) && (
$arg_no_space
ne
'void'
));
defined
(
$arg_name
) ?
push
(
@arg_names
,
$arg_name
)
:
push
(
@arg_names
,
''
);
if
(
$arg_name
) {
push
(
@arg_types
,
$arg_type
)}
else
{
push
(
@arg_types
,
''
)}
}
elsif
(
$arg
=~ /^\s*\.\.\.\s*$/) {
push
(
@arg_names
,
'...'
);
push
(
@arg_types
,
'...'
);
}
else
{
goto
RESYNC;
}
}
push
@{
$self
->{data}{functions}},
$function
;
$self
->{data}{function}{
$function
}{return_type}=
$return_type
;
$self
->{data}{function}{
$function
}{arg_names} = [
@arg_names
];
$self
->{data}{function}{
$function
}{arg_types} = [
@arg_types
];
$self
->{data}{done}{
$function
} = 1;
next
;
RESYNC:
$code
=~ /\G[^\n]*\n/gc;
}
return
1;
}
1;