Get functions names with regex

I have text file like this,

str = “function ExecMain.GetApiErrorMessage(ApiErrCode :DWORD) :String;
var
Buf: array[0…511] of Char;
MsgCnt :DWORD;
begin
function THandle.SetPrivilege(PrivilegeName: String;
Enable: Boolean): Boolean;
var
tpPrev,
tp : TTokenPrivileges;
token : THandle;
dwRetLen : DWord;
begin
function Privileges.SetPrivilege(PrivilegeName: String;
Enable: Boolean): Boolean;
var
tpPrev,
tp : Privileges;
token : THandleTest;
dwRetLen : DWord;
begin”

str =~ /(function)\s+(\w+)(.*);/
func_names = $1
puts “#{$’}”
while(str) # while(true)
str = $’ #second function
str =~ /:(\w+);/m
args = $1

str.scan(/:(\w+);/m) do |d|

puts $1 # private method error

end

if args == func_names
puts func_names
end
puts “-----------------------------”
puts “#{$’}”
end

I am writing this script for getting the function names and args names.
but there is some rules:
1- if I want to scan one function name, next time I need scan second
function name.(because I need which args belongs to which functions
name)
2- If args names same as functions names I want to print the function
name.

with this code I am not get the args name.
please help me.

On Thu, Sep 24, 2009 at 9:17 PM, Ahmet K. [email protected]
wrote:

tpPrev,
dwRetLen : DWord;

puts $1 # private method error

1- if I want to scan one function name, next time I need scan second

#try this code (I’m on 1.8.6)

#a function declaration that was parsed out of some text
class ParsedFunction

attr_accessor :name , :args

#expects args to be in format [[name,type],[name,type]]
def initialize( name , *args )
@name , @args = name , *args
end

#call like this: funct.each_arg{|arg_name,arg_type| … }
def each_arg
args.each do |arg|
yield *arg
end
end

def to_s
“function #{name}( #{args.map{|arg| arg.join(': ‘) }.join(’; ')} )”
end
end

functs = Array.new

str.scan(/^\sfunction\s([^(]+)(([^)]+)/).map do |name,args|
name.gsub!(/\s/,‘’)
args.gsub!(/\s/,‘’)
functs << ParsedFunction.new( name , args.split(/;/).map{|arg|
arg.split(/:/) } )
end

puts “THE FUNCTIONS FOUND WERE: \n\n”
functs.each do |f|
puts “signature: #{f}”
puts “name: #{f.name}”
puts “number of args: #{f.args.size}”
puts “list of args:”
f.each_arg{|arg_name,arg_type| puts " #{arg_name} : #{arg_type}" }
puts
end

END
I get the following output:

THE FUNCTIONS FOUND WERE:

signature: function ExecMain.GetApiErrorMessage( ApiErrCode: DWORD )
name: ExecMain.GetApiErrorMessage
number of args: 1
list of args:
ApiErrCode : DWORD

signature: function THandle.SetPrivilege( PrivilegeName: String; Enable:
Boolean )
name: THandle.SetPrivilege
number of args: 2
list of args:
PrivilegeName : String
Enable : Boolean

signature: function Privileges.SetPrivilege( PrivilegeName: String;
Enable:
Boolean )
name: Privileges.SetPrivilege
number of args: 2
list of args:
PrivilegeName : String
Enable : Boolean

Thank you very much,
I am making customize the code but when I change this part from

str.scan(/^\sfunction\s([^(]+)(([^)]+)/).map do |name,args|
to
/procedure|function\s+(\w+)([^\s(]+)\s*(([^)]+))\s*:\s*(\S+)\s*;\s*^\svar\s$(.*?)^begin/xm

i could`t get the args name.
an the results like this:

THE FUNCTIONS FOUND WERE:

signature: function ExecMain( .GetApiErrorMessage )
name: ExecMain
number of args: 1
list of args:
.GetApiErrorMessage :

signature: function THandle( .SetPrivilege )
name: THandle
number of args: 1
list of args:
.SetPrivilege :

signature: function Privileges( .SetPrivilege )
name: Privileges
number of args: 1
list of args:
.SetPrivilege :

I think something changing somewhere…

On 09/25/2009 06:15 AM, Josh C. wrote:

On Thu, Sep 24, 2009 at 9:17 PM, Ahmet K. [email protected] wrote:

functs = Array.new

str.scan(/^\sfunction\s([^(]+)(([^)]+)/).map do |name,args|
name.gsub!(/\s/,‘’)
args.gsub!(/\s/,‘’)
functs << ParsedFunction.new( name , args.split(/;/).map{|arg|
arg.split(/:/) } )
end

Either you should not be using #map above or assign the result of #map
to functs. A #map without using the result is pretty useless.

But definitively #scan is the right tool for the job. If only printing
of function names and arguments is interesting that could be done inside
the #scan body as well avoiding a second pass.

Kind regards

robert

Josh C. wrote:

On Fri, Sep 25, 2009 at 12:54 AM, Ahmet K. [email protected]
wrote:

To see what is going on, you can have the block accept a variable list
of
arguments, then print that out to see what was passed in, something like
this:

“ab cdef”.scan(/(b)(\s*)(?:c)de(f)/).each do |*args|
p *args
end

Which would print out [“b”, " ", “f”] Then you can go and change your
groups around, and see how that affects it.

functs = str.scan(/^\sfunction\s([^(]+)(([^)]+)/).map do |name,args|
name.gsub!(/\s/,‘’)
args.gsub!(/\s/,‘’)
ParsedFunction.new( name , args.split(/;/).map{|arg| arg.split(/:/) }
)

Thanks I think it is clear now.

On Fri, Sep 25, 2009 at 12:54 AM, Ahmet K. [email protected]
wrote:

Thank you very much,
I am making customize the code but when I change this part from

str.scan(/^\sfunction\s([^(]+)(([^)]+)/).map do |name,args|
to

/procedure|function\s+(\w+)([^\s(]+)\s*(([^)]+))\s*:\s*(\S+)\s*;\s*^\svar\s$(.*?)^begin/xm

I don’t know what you are looking for exactly, but it looks like
procedure|functions should be grouped. Also, all your capture groups are
going to get passed into the block, so for each of them, you need a
variable. Any groups that you don’t want passed in, you should make into
a
non capture group by placing ?: after the opening of the group, like
this
(?:slight_smile:

To see what is going on, you can have the block accept a variable list
of
arguments, then print that out to see what was passed in, something like
this:

“ab cdef”.scan(/(b)(\s*)(?:c)de(f)/).each do |*args|
p *args
end

Which would print out [“b”, " ", “f”] Then you can go and change your
groups around, and see how that affects it.

On Fri, Sep 25, 2009 at 1:05 AM, Robert K.
[email protected]wrote:

name.gsub!(/\s/,‘’)
function names and arguments is interesting that could be done inside the

Yes, that should be replaced with “each”. I initially had it like this

functs = str.scan(/^\sfunction\s([^(]+)(([^)]+)/).map do |name,args|
name.gsub!(/\s/,‘’)
args.gsub!(/\s/,‘’)
ParsedFunction.new( name , args.split(/;/).map{|arg| arg.split(/:/) }
)
end

But I thought it might be easier to follow if I separated the functs
variable. When I did that, I should have also switched map to each.