论坛首页 编程语言技术论坛

浏览(遍历)Ruby模块

浏览 6771 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-06-15  
假如有个Ruby源文件如下:
module AA
  # something else...
  module BB
     # something else...
  end
  module CC
     # something else...
  end
  # something else...
end


如何做一个module browser,也就是说,找出它的模块结构树(如下)呢?

引用
module AA
  - module BB
  - module CC


用regular express读入源文件分析,还是用reflection机制?

两种方法我都考虑过,reflection机制,module好像没有sub_modules方法;直接分析源文件,遇到一些细节问题,如单双引号,也挺繁的。

做这个是因为最近考虑用Ruby做网页自动测试(比方调用WATIR或Selenium),testcase很多,需要模块化,所以想做一个模块浏览器。请问各位有何高招呢?
   发表时间:2006-06-15  
刚刚看了一下Eclipse RDT,它就做得比较好,能随着源代码的改变,自动生成一个模块、类和方法的outline。不知道它的实现机理是什么。见附件。
0 请登录后投票
   发表时间:2006-06-15  
做了些实验,觉得RDT采用的方式,不象是在用reflection,而是直接对源文件进行语法分析(比方分块)。

仔细想想,也觉得这样做比较合适。看来我得继续朝这个方向努力了。有什么结果我会告诉大家。我会先用Ruby写一个分析器,整理出一棵树,然后套上GUI。

有何高见,希望继续讨论。谢谢。
0 请登录后投票
   发表时间:2006-06-16  
哈哈,FreeRIDE也有这个功能,而且是用Ruby写成。可是对一个三千多行的.rb文件(watir.rb,Web自动测试库),它却分析不出来了,RDT可以。

继续研究。
0 请登录后投票
   发表时间:2006-06-16  
Find配合正则就差不多了
0 请登录后投票
   发表时间:2006-06-16  
是这样,不过做起来还是需要仔细的。比方不能把单引号和双引号里的字符串、regex、单行注释与多行注释里的关键字也算进去。有点语法分析器的味道。还是要花些时间的。
0 请登录后投票
   发表时间:2006-06-17  
找到了:
http://rubyforge.org/projects/rubylexer/

这个ruby库可以解析ruby源文件 成 一个个token 并可遍历。
原以为太复杂自已玩不转,试了试还可以。下面是解析出module结构树的代码:

require "rubylexer.rb"
f = open('d:\test\testrr6.rb')
lexer=RubyLexer.new('d:\test\testrr6.rb', f)

# module tree node
class ModNode
  attr_reader :children, :mod_name
  def initialize(mod_name)
    @mod_name = mod_name
    @children = []
  end
  
  def <<(child_mod)
    @children << child_mod
  end
  
  def dump(level)
    self.class.dump_level(level)
    print @mod_name
    print "\n"
    if not @children.empty? then
      for child in @children
        child.dump(level+1)
      end
    end
  end
  
  def self.dump_level(level)
    print '--' * level
  end
end

need_capture = false # whether should capture next VarNameToken as module name 
mod_stack = [] 
keyword_stack = [] 
root = ModNode.new('root')
mod_stack.push root

# iterate tokens
until EoiToken===(tok=lexer.get1token)
 
  if tok.kind_of?(KeywordToken) then
    next if tok.has_end?.nil?
    if tok.has_end? == true then
      keyword_stack.push tok.ident
    elsif tok.ident == 'end' then
      ident = keyword_stack.pop
      mod_stack.pop if ident == 'module' 
    end

    if tok.ident == 'module'  then
      need_capture = true
      next
    end
  end
  
  if need_capture and tok.kind_of?(VarNameToken) then
    mod_name = tok.ident
    mod = ModNode.new(mod_name)
    mod_stack.last << mod
    mod_stack.push mod
    need_capture = false
  end

end

# dump the module tree
root.dump(0)


执行结果是:
引用
root
--AA
----BB
----CC


3000行的watir行不行,很期待 
0 请登录后投票
   发表时间:2006-06-17  
原先考虑过这种方式:
s = open('d:\test\testrr6.rb').read
module XX
end

XX.module_eval(s)

ObjectSpace.each_object(Module) do |clazz|
   puts clazz.name if clazz.name.match(/^XX\:\:/) and not clazz.kind_of?(Class)
end

执行结果是:
引用
XX::AA::CC
XX::AA::BB
XX::AA


d:\test\testrr6.rb 是待解析的ruby源文件。
对过滤出的clazz.name做下处理就会有收获,不过实在是.... 太土了
0 请登录后投票
   发表时间:2006-06-17  
哈哈,非常谢谢找出了这个rubylexer,经过n秒钟之后,watir.rb的结果也正确地出来了:
引用
root
--Watir
----SupportsSubElements
----FormAccess
----OptionAccess
----CommonCollection


接下来,我看看怎样把class和method什么的都搞进去,我试了一下class,结果一不小心,把level搞乱了,再仔细调试调试。

另外,ObjectSpace的方法我也试了一下,关键是它会去执行一遍被分析的文件,有时候不是我们所希望的,呵呵。

liusong1111 写道
找到了:
http://rubyforge.org/projects/rubylexer/

这个ruby库可以解析ruby源文件 成 一个个token 并可遍历。
原以为太复杂自已玩不转,试了试还可以。下面是解析出module结构树的代码:

...

执行结果是:
引用
root
--AA
----BB
----CC


3000行的watir行不行,很期待 
0 请登录后投票
   发表时间:2006-06-20  
呼呼,又知道了个新东东~
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics