Another possibility to consider is Parse::RecDescent or something along those lines – a true parser. You can write your grammar so that it looks for function declarations and ignores everything else, and now the solution is truly generalized. When, inevitably, a programmer did something that your current crop of regular-expressions didn’t recognize (if you caught it), you would find yourself maybe going through more-and-more calisthenics. Whereas a parser avoids all that.
I have personal experience with this. In a past life, I concocted a system that parsed a mess of SAS® source-files, Korn(!) shell scripts, and Tivoli job-files, to construct a data-flow picture of what this old application was actually doing. Parse::RecDescent frankly astounded me with its ability to do so much of the job “with speed, grace, and style.” I had prior experience with other parsers based on Bison and Yacc (which are also supported through Perl ...), but this was considerably more flexible, allowing me to write grammars to zero-in on what I needed out of the files without having to create a grammar for all of its irrelevant-to-me twists and turns.
As the system I was building became more visible, its requirements expanded several times. But, thanks to the parser and my experience with it at that time, I was able to accommodate those new requests without major re-design. That positively sold me on it, hence my suggestion.