# Get functions names with regex

**URL:** <https://www.ruby-forum.com/t/get-functions-names-with-regex/176138>\
**Category:** Ruby\
**Created:** [September 25, 2009, 4:17am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138 "2009-09-25T04:17:34Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ahmet](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@ahmet](https://www.ruby-forum.com/u/ahmet)\
**Post date:** [September 25, 2009, 4:17am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138/1 "2009-09-25T04:17:34Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ahmet](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@ahmet](https://www.ruby-forum.com/u/ahmet)\
**Post date:** [September 25, 2009, 6:15am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138/2 "2009-09-25T06:15:56Z")

</div>

On Thu, Sep 24, 2009 at 9:17 PM, Ahmet K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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(/^\s_function\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

---

<div class="post-metadata">

**Author:** ![ahmet](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@ahmet](https://www.ruby-forum.com/u/ahmet)\
**Post date:** [September 25, 2009, 7:54am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138/3 "2009-09-25T07:54:12Z")

</div>

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

> str.scan(/^\s_function\s_([^(]+)(([^)]+)/).map do |name,args|  
> to  
> /procedure|function\s+(\w+)([^\s(]+)\s\*(([^)]+))\s\*:\s\*(\S+)\s\*;\s\*^\s_var\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…

---

<div class="post-metadata">

**Author:** ![ahmet](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@ahmet](https://www.ruby-forum.com/u/ahmet)\
**Post date:** [September 25, 2009, 8:05am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138/4 "2009-09-25T08:05:25Z")

</div>

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

> On Thu, Sep 24, 2009 at 9:17 PM, Ahmet K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> functs = Array.new
> 
> str.scan(/^\s_function\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

---

<div class="post-metadata">

**Author:** ![ahmet](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@ahmet](https://www.ruby-forum.com/u/ahmet)\
**Post date:** [September 25, 2009, 9:53am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138/5 "2009-09-25T09:53:21Z")

</div>

Josh C. wrote:

> On Fri, Sep 25, 2009 at 12:54 AM, Ahmet K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> 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(/^\s_function\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.

---

<div class="post-metadata">

**Author:** ![ahmet](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ac91a4/32.png) [@ahmet](https://www.ruby-forum.com/u/ahmet)\
**Post date:** [September 25, 2009, 8:39am UTC](https://www.ruby-forum.com/t/get-functions-names-with-regex/176138/6 "2009-09-25T08:39:58Z")

</div>

On Fri, Sep 25, 2009 at 12:54 AM, Ahmet K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Thank you very much,  
> I am making customize the code but when I change this part from
> 
> > str.scan(/^\s_function\s_([^(]+)(([^)]+)/).map do |name,args|  
> > to
> 
> /procedure|function\s+(\w+)([^\s(]+)\s\*(([^)]+))\s\*:\s\*(\S+)\s\*;\s\*^\s_var\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  
(?🙂

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.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)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(/^\s_function\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.
