# 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
syntax highlighted by Code2HTML, v. 0.9.1