in reply to Parsing C Functions..
This isn't particularly hard if you pick the right approach. I think the easiest way it to tokenize the language you are parsing and then build a simple state machine to parse just enough of the tokens to get the information you want.
Since type declarations can contain parens (though usually don't) I settled on considering ") {" as the start of a function body. I think that can't happen elsewhere in valid C code. I didn't check my POD syntax and the code is very imcomplete, intentionally.
=for state_machine START \n -> {flush} START ws -> START else -> DECL DECL ; -> {flush} START ) -> CLOSE CLOSE { -> {block=1} FUNC else -> DECL FUNC { -> {++block} FUNC } -> { --block ? FUNC : END } END ws -> END \n -> {save} START else -> {save} DECL =end use enum qw( START DECL CLOSE FUNC END ); my $state= START(); my $part= ''; while( $code =~ m{ \G( \n # newline | [^\S\n]+ # horizontal whitespace | [a-z]\w* # identifier | \d+ # digit string | "(?:[^\\"]+|\\[^\n])*" | '(?:[^\\']+|\\[^\n])*' | /\*.*?\*/ # C comment | //[^\n]*\n # C++ comment | [^\w\s] # punctuation mark ) }xsg ) { my $token= $1; if( START() == $state ) { if( $token eq "\n" ) { $token= $part= ''; } elsif( $token =~ /\S/ ) { $state= DECL(); } ... } elsif( END() == $state ) { if( $token =~ /\S/ ) { push @func, $part; $part= ''; ... } } $part .= $token; }
And it is pretty easy to extend the state machine to track nesting of parens so you can extract the identifier before the last outer open paren before the body of the function is detected, for example (which would be the name of the function).
- tye
|
|---|