# pparse.rb # $Id: pparse.rb,v 1.5 2000/11/12 00:37:33 keiko Exp $ require "prototype" class PrototypeParser def parse(&block) @cpp.each do |line| case line when /^\s*$/ next when /^#/ macro(line, &block) # retain as macros when /(\S+)\s+FUNCTION\s+(\w+)\s*\(/ func($1, $2) when /SUBROUTINE\s+(\w+)\s*\(/ subr($1) when /^\s*\)\s*$/ close(&block) else line.gsub!(/(^\s+)|(\s+$)/, "") line.chomp! var(line) end end end private def delete_comment(src) # [ruby-list:32030] [ruby-list:32049] src.gsub(%r@ ([\'\"])(\\.|.)*?\1 | (/\*.*?\*/) | (//)[^\n]*$ @mx) { if $3 s = $3.delete("^\n") s = ' ' if s.empty? s elsif $4 '' else $& end } end def initialize(file) input = if file.is_a? IO file else File::open(file) end @cpp = delete_comment(input.read) end def func(type, name) @type, @name = type, name.downcase @var = [] @rtn = [] if (/(\d+)|\*\((.*)\)/ =~ type) charlen = ($1||$2).downcase # may be charcter length @type = type.scan(/\w+/)[0] else charlen = nil end @rtn.push Variable("rtn_val", @type, "o", false, charlen) p [:func, type, name] if $DEBUG end def subr(name) @type, @name = nil, name.downcase @var = [] @rtn = [] p [:subr, name] if $DEBUG end def var(decl) name, *tmp = decl.split.reverse tmp.reverse! attr = (tmp[-1] =~ /^[a-z]+$/ ? tmp.pop : "i") ary = (tmp[-1] =~ /^\((.*)\)/ ? (tmp.pop; $1.downcase) : false) vtype = tmp.pop if (/(\d+)|\*\((.*)\)/ =~ vtype) charlen = ($1||$2).downcase # may be charcter length vtype = vtype.scan(/\w+/)[0] else charlen = nil end attr0 = attr.scan(/./).sort.uniq.join r = (attr =~ /i/ ? (attr.delete!("i"); true) : false) w = (attr =~ /o/ ? (attr.delete!("o"); true) : false) t = (attr =~ /t/ ? (attr.delete!("t"); true) : false) raise "unexpected decl `#{decl.inspect}'" unless tmp.empty? raise "unexpected read/write attr `#{decl.inspect}'" unless attr.empty? v = Variable(name.downcase, vtype, attr0, ary, charlen) @var.push v @rtn.push v if (!@type && w) p decl if $DEBUG p v if $DEBUG end def close val = Prototype.new(@type, @name, @var, @rtn) p val if $DEBUG @var = nil @rtn = nil # puts if $DEBUG if block_given? yield(val) else val end end def macro(line) if block_given? yield(line) else line end end def method_missing(m, *a, &b) p [m, a.join(" ")] end # Var = Struct.new("Var", # "vtype", "ary?", "attr", "r?", "w?", "t?", "name", # "ignore?").freeze end