- extra spaces are removed

- static class member modifier processing is fixed (moved from 'rettype' to 'func_modlist')
This commit is contained in:
Andrey Pavlenko 2011-05-17 12:52:07 +00:00
parent 2935bb29e5
commit 0f5f60f7f5
2 changed files with 92 additions and 91 deletions

View File

@ -749,8 +749,9 @@ class PythonWrapperGenerator(object):
if __name__ == "__main__": if __name__ == "__main__":
srcfiles = hdr_parser.opencv_hdr_list srcfiles = hdr_parser.opencv_hdr_list
dstdir = "/Users/vp/tmp" dstdir = "/Users/vp/tmp"
if len(sys.argv) > 2: if len(sys.argv) > 1:
dstdir = sys.argv[1] dstdir = sys.argv[1]
if len(sys.argv) > 2:
srcfiles = sys.argv[2:] srcfiles = sys.argv[2:]
generator = PythonWrapperGenerator() generator = PythonWrapperGenerator()
generator.gen(srcfiles, dstdir) generator.gen(srcfiles, dstdir)

View File

@ -20,7 +20,7 @@ where each element of <list_of_arguments> is 4-element list itself:
[argtype, argname, default_value /* or "" if none */, <list_of_modifiers>] [argtype, argname, default_value /* or "" if none */, <list_of_modifiers>]
where the list of modifiers is yet another nested list of strings where the list of modifiers is yet another nested list of strings
(currently recognized are "/O" for output argument, "/S" for static (i.e. class) methods (currently recognized are "/O" for output argument, "/S" for static (i.e. class) methods
and "/A value" for the plain C arrays with counters) and "/A value" for the plain C arrays with counters)
""" """
class CppHeaderParser(object): class CppHeaderParser(object):
@ -31,18 +31,18 @@ class CppHeaderParser(object):
self.PROCESS_FLAG = 2 self.PROCESS_FLAG = 2
self.PUBLIC_SECTION = 3 self.PUBLIC_SECTION = 3
self.CLASS_DECL = 4 self.CLASS_DECL = 4
def batch_replace(self, s, pairs): def batch_replace(self, s, pairs):
for before, after in pairs: for before, after in pairs:
s = s.replace(before, after) s = s.replace(before, after)
return s return s
def get_macro_arg(self, arg_str, npos): def get_macro_arg(self, arg_str, npos):
npos2 = npos3 = arg_str.find("(", npos) npos2 = npos3 = arg_str.find("(", npos)
if npos2 < 0: if npos2 < 0:
print "Error: no arguments for the macro at %d" % (self.lineno,) print "Error: no arguments for the macro at %d" % (self.lineno,)
sys.exit(-1) sys.exit(-1)
balance = 1 balance = 1
while 1: while 1:
t, npos3 = self.find_next_token(arg_str, ['(', ')'], npos3+1) t, npos3 = self.find_next_token(arg_str, ['(', ')'], npos3+1)
if npos3 < 0: if npos3 < 0:
@ -54,9 +54,9 @@ class CppHeaderParser(object):
balance -= 1 balance -= 1
if balance == 0: if balance == 0:
break break
return arg_str[npos2+1:npos3].strip(), npos3 return arg_str[npos2+1:npos3].strip(), npos3
def parse_arg(self, arg_str, argno): def parse_arg(self, arg_str, argno):
""" """
Parses <arg_type> [arg_name] Parses <arg_type> [arg_name]
@ -67,12 +67,12 @@ class CppHeaderParser(object):
"arg" + str(argno), and then argno is incremented. "arg" + str(argno), and then argno is incremented.
""" """
modlist = [] modlist = []
# pass 0: extracts the modifiers # pass 0: extracts the modifiers
if "CV_OUT" in arg_str: if "CV_OUT" in arg_str:
modlist.append("/O") modlist.append("/O")
arg_str = arg_str.replace("CV_OUT", "") arg_str = arg_str.replace("CV_OUT", "")
if "CV_IN_OUT" in arg_str: if "CV_IN_OUT" in arg_str:
modlist.append("/IO") modlist.append("/IO")
arg_str = arg_str.replace("CV_IN_OUT", "") arg_str = arg_str.replace("CV_IN_OUT", "")
@ -82,25 +82,25 @@ class CppHeaderParser(object):
if npos >= 0: if npos >= 0:
isarray = True isarray = True
macro_arg, npos3 = self.get_macro_arg(arg_str, npos) macro_arg, npos3 = self.get_macro_arg(arg_str, npos)
modlist.append("/A " + macro_arg) modlist.append("/A " + macro_arg)
arg_str = arg_str[:npos] + arg_str[npos3+1:] arg_str = arg_str[:npos] + arg_str[npos3+1:]
npos = arg_str.find("CV_CUSTOM_CARRAY") npos = arg_str.find("CV_CUSTOM_CARRAY")
if npos >= 0: if npos >= 0:
isarray = True isarray = True
macro_arg, npos3 = self.get_macro_arg(arg_str, npos) macro_arg, npos3 = self.get_macro_arg(arg_str, npos)
modlist.append("/CA " + macro_arg) modlist.append("/CA " + macro_arg)
arg_str = arg_str[:npos] + arg_str[npos3+1:] arg_str = arg_str[:npos] + arg_str[npos3+1:]
arg_str = arg_str.strip() arg_str = arg_str.strip()
word_start = 0 word_start = 0
word_list = [] word_list = []
npos = -1 npos = -1
#print self.lineno, ":\t", arg_str #print self.lineno, ":\t", arg_str
# pass 1: split argument type into tokens # pass 1: split argument type into tokens
while 1: while 1:
npos += 1 npos += 1
@ -121,9 +121,9 @@ class CppHeaderParser(object):
arg_type = "" arg_type = ""
arg_name = "" arg_name = ""
angle_stack = [] angle_stack = []
#print self.lineno, ":\t", word_list #print self.lineno, ":\t", word_list
# pass 2: decrypt the list # pass 2: decrypt the list
wi = -1 wi = -1
prev_w = "" prev_w = ""
@ -160,7 +160,7 @@ class CppHeaderParser(object):
else: else:
arg_type += w arg_type += w
prev_w = w prev_w = w
counter_str = "" counter_str = ""
add_star = False add_star = False
if ("[" in arg_name) and not ("operator" in arg_str): if ("[" in arg_name) and not ("operator" in arg_str):
@ -177,24 +177,24 @@ class CppHeaderParser(object):
modlist.append("/A " + counter_str.strip()) modlist.append("/A " + counter_str.strip())
arg_name = arg_name[:p1] arg_name = arg_name[:p1]
add_star = True add_star = True
if not arg_name: if not arg_name:
if arg_type.startswith("operator"): if arg_type.startswith("operator"):
arg_type, arg_name = "", arg_type arg_type, arg_name = "", arg_type
else: else:
arg_name = "arg" + str(argno) arg_name = "arg" + str(argno)
argno += 1 argno += 1
while arg_type.endswith("_end_"): while arg_type.endswith("_end_"):
arg_type = arg_type[:-len("_end_")] arg_type = arg_type[:-len("_end_")]
if add_star: if add_star:
arg_type += "*" arg_type += "*"
arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", "")]) arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", "")])
return arg_type, arg_name, modlist, argno return arg_type, arg_name, modlist, argno
def parse_enum(self, decl_str): def parse_enum(self, decl_str):
l = decl_str l = decl_str
ll = l.split(",") ll = l.split(",")
@ -214,7 +214,7 @@ class CppHeaderParser(object):
prev_val = val = pv[1].strip() prev_val = val = pv[1].strip()
decl.append(["const " + self.get_dotted_name(pv[0].strip()), val, [], []]) decl.append(["const " + self.get_dotted_name(pv[0].strip()), val, [], []])
return decl return decl
def parse_class_decl(self, decl_str): def parse_class_decl(self, decl_str):
""" """
Parses class/struct declaration start in the form: Parses class/struct declaration start in the form:
@ -234,7 +234,7 @@ class CppHeaderParser(object):
macro_arg, npos3 = self.get_macro_arg(l, npos) macro_arg, npos3 = self.get_macro_arg(l, npos)
modlist.append("=" + macro_arg) modlist.append("=" + macro_arg)
l = l[:npos] + l[npos3+1:] l = l[:npos] + l[npos3+1:]
l = self.batch_replace(l, [("CV_EXPORTS_W", ""), ("CV_EXPORTS", ""), ("public ", " "), ("::", ".")]).strip() l = self.batch_replace(l, [("CV_EXPORTS_W", ""), ("CV_EXPORTS", ""), ("public ", " "), ("::", ".")]).strip()
ll = re.split(r'\s*[,:]?\s*', l) ll = re.split(r'\s*[,:]?\s*', l)
ll = [le for le in ll if le] ll = [le for le in ll if le]
@ -249,18 +249,18 @@ class CppHeaderParser(object):
[~]<function_name> [~]<function_name>
(<arg_type1> <arg_name1>[=<default_value1>] [, <arg_type2> <arg_name2>[=<default_value2>] ...]) (<arg_type1> <arg_name1>[=<default_value1>] [, <arg_type2> <arg_name2>[=<default_value2>] ...])
[const] {; | <function_body>} [const] {; | <function_body>}
Returns the function declaration entry: Returns the function declaration entry:
[<function_name>, <rettype>, <the_list_of_argument_descriptions>] (see above) [<func name>, <return value C-type>, <list of modifiers>, <list of arguments>] (see above)
""" """
if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or \ if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or \
("CV_WRAP" in decl_str) or ("CV_WRAP_AS" in decl_str)): ("CV_WRAP" in decl_str) or ("CV_WRAP_AS" in decl_str)):
return [] return []
top = self.block_stack[-1] top = self.block_stack[-1]
func_modlist = [] func_modlist = []
npos = decl_str.find("CV_EXPORTS_AS") npos = decl_str.find("CV_EXPORTS_AS")
if npos >= 0: if npos >= 0:
arg, npos3 = self.get_macro_arg(decl_str, npos) arg, npos3 = self.get_macro_arg(decl_str, npos)
@ -271,7 +271,7 @@ class CppHeaderParser(object):
arg, npos3 = self.get_macro_arg(decl_str, npos) arg, npos3 = self.get_macro_arg(decl_str, npos)
func_modlist.append("="+arg) func_modlist.append("="+arg)
decl_str = decl_str[:npos] + decl_str[npos3+1:] decl_str = decl_str[:npos] + decl_str[npos3+1:]
# filter off some common prefixes, which are meaningless for Python wrappers. # filter off some common prefixes, which are meaningless for Python wrappers.
# note that we do not strip "static" prefix, which does matter; # note that we do not strip "static" prefix, which does matter;
# it means class methods, not instance methods # it means class methods, not instance methods
@ -283,7 +283,7 @@ class CppHeaderParser(object):
if decl_str.startswith("static") and (context == "class" or context == "struct"): if decl_str.startswith("static") and (context == "class" or context == "struct"):
decl_str = decl_str[len("static"):].lstrip() decl_str = decl_str[len("static"):].lstrip()
static_method = True static_method = True
args_begin = decl_str.find("(") args_begin = decl_str.find("(")
if decl_str.startswith("CVAPI"): if decl_str.startswith("CVAPI"):
rtype_end = decl_str.find(")", args_begin+1) rtype_end = decl_str.find(")", args_begin+1)
@ -295,7 +295,7 @@ class CppHeaderParser(object):
if args_begin < 0: if args_begin < 0:
print "Error at %d: no args in '%s'" % (self.lineno, decl_str) print "Error at %d: no args in '%s'" % (self.lineno, decl_str)
sys.exit(-1) sys.exit(-1)
decl_start = decl_str[:args_begin].strip() decl_start = decl_str[:args_begin].strip()
# handle operator () case # handle operator () case
if decl_start.endswith("operator"): if decl_start.endswith("operator"):
@ -304,9 +304,9 @@ class CppHeaderParser(object):
print "Error at %d: no args in '%s'" % (self.lineno, decl_str) print "Error at %d: no args in '%s'" % (self.lineno, decl_str)
sys.exit(-1) sys.exit(-1)
decl_start = decl_str[:args_begin].strip() decl_start = decl_str[:args_begin].strip()
rettype, funcname, modlist, argno = self.parse_arg(decl_start, -1) rettype, funcname, modlist, argno = self.parse_arg(decl_start, -1)
if argno >= 0: if argno >= 0:
classname = top[1] classname = top[1]
if rettype == classname or rettype == "~" + classname: if rettype == classname or rettype == "~" + classname:
@ -314,7 +314,7 @@ class CppHeaderParser(object):
else: else:
print "Error at %d. the function/method name is missing: '%s'" % (self.lineno, decl_start) print "Error at %d. the function/method name is missing: '%s'" % (self.lineno, decl_start)
sys.exit(-1) sys.exit(-1)
if ("::" in funcname) or funcname.startswith("~"): if ("::" in funcname) or funcname.startswith("~"):
# if there is :: in function name (and this is in the header file), # if there is :: in function name (and this is in the header file),
# it means, this is inline implementation of a class method. # it means, this is inline implementation of a class method.
@ -322,9 +322,9 @@ class CppHeaderParser(object):
# declaration. # declaration.
# Also, skip the destructors, as they are always wrapped # Also, skip the destructors, as they are always wrapped
return [] return []
funcname = self.get_dotted_name(funcname) funcname = self.get_dotted_name(funcname)
arg_start = args_begin+1 arg_start = args_begin+1
npos = arg_start-1 npos = arg_start-1
balance = 1 balance = 1
@ -333,7 +333,7 @@ class CppHeaderParser(object):
args_decls = [] args_decls = []
args = [] args = []
argno = 1 argno = 1
while balance > 0: while balance > 0:
npos += 1 npos += 1
t, npos = self.find_next_token(decl_str, ["(", ")", ",", "<", ">"], npos) t, npos = self.find_next_token(decl_str, ["(", ")", ",", "<", ">"], npos)
@ -350,7 +350,7 @@ class CppHeaderParser(object):
balance += 1 balance += 1
if t == ")": if t == ")":
balance -= 1 balance -= 1
if (t == "," and balance == 1 and angle_balance == 0) or balance == 0: if (t == "," and balance == 1 and angle_balance == 0) or balance == 0:
# process next function argument # process next function argument
a = decl_str[arg_start:npos].strip() a = decl_str[arg_start:npos].strip()
@ -390,31 +390,31 @@ class CppHeaderParser(object):
("OutputArrayOfArrays", "vector<Mat>"), ("OutputArrayOfArrays", "vector<Mat>"),
("InputArray", "Mat"), ("InputArray", "Mat"),
("InputOutputArray", "Mat"), ("InputOutputArray", "Mat"),
("OutputArray", "Mat")]).strip() ("OutputArray", "Mat")]).strip()
args.append([arg_type, arg_name, defval, modlist]) args.append([arg_type, arg_name, defval, modlist])
npos = arg_start-1 npos = arg_start-1
npos = decl_str.replace(" ", "").find("=0", npos) npos = decl_str.replace(" ", "").find("=0", npos)
if npos >= 0: if npos >= 0:
# skip pure virtual functions # skip pure virtual functions
return [] return []
if static_method: if static_method:
rettype = " ".join([rettype, "/S"]) func_modlist.append("/S")
return [funcname, rettype, func_modlist, args] return [funcname, rettype, func_modlist, args]
def get_dotted_name(self, name): def get_dotted_name(self, name):
""" """
adds the dot-separated container class/namespace names to the bare function/class name, e.g. when we have adds the dot-separated container class/namespace names to the bare function/class name, e.g. when we have
namespace cv { namespace cv {
class A { class A {
public: public:
f(int); f(int);
}; };
} }
the function will convert "A" to "cv.A" and "f" to "cv.A.f". the function will convert "A" to "cv.A" and "f" to "cv.A.f".
""" """
if not self.block_stack: if not self.block_stack:
@ -430,24 +430,24 @@ class CppHeaderParser(object):
if block_name: if block_name:
n += block_name + "." n += block_name + "."
return n + name return n + name
def parse_stmt(self, stmt, end_token): def parse_stmt(self, stmt, end_token):
""" """
parses the statement (ending with ';' or '}') or a block head (ending with '{') parses the statement (ending with ';' or '}') or a block head (ending with '{')
The function calls parse_class_decl or parse_func_decl when necessary. It returns The function calls parse_class_decl or parse_func_decl when necessary. It returns
<block_type>, <block_name>, <parse_flag>, <declaration> <block_type>, <block_name>, <parse_flag>, <declaration>
where the first 3 values only make sense for blocks (i.e. code blocks, namespaces, classes, enums and such) where the first 3 values only make sense for blocks (i.e. code blocks, namespaces, classes, enums and such)
""" """
stack_top = self.block_stack[-1] stack_top = self.block_stack[-1]
context = stack_top[self.BLOCK_TYPE] context = stack_top[self.BLOCK_TYPE]
stmt_type = "" stmt_type = ""
if end_token == "{": if end_token == "{":
stmt_type = "block" stmt_type = "block"
if context == "block": if context == "block":
print "Error at %d: should not call parse_stmt inside blocks" % (self.lineno,) print "Error at %d: should not call parse_stmt inside blocks" % (self.lineno,)
sys.exit(-1) sys.exit(-1)
if context == "class" or context == "struct": if context == "class" or context == "struct":
@ -463,11 +463,11 @@ class CppHeaderParser(object):
stack_top[self.PUBLIC_SECTION] = False stack_top[self.PUBLIC_SECTION] = False
stmt = stmt[colon_pos+1:].strip() stmt = stmt[colon_pos+1:].strip()
break break
# do not process hidden class members and template classes/functions # do not process hidden class members and template classes/functions
if not stack_top[self.PUBLIC_SECTION] or stmt.startswith("template"): if not stack_top[self.PUBLIC_SECTION] or stmt.startswith("template"):
return stmt_type, "", False, None return stmt_type, "", False, None
if end_token == "{": if end_token == "{":
if stmt.startswith("class") or stmt.startswith("struct"): if stmt.startswith("class") or stmt.startswith("struct"):
stmt_type = stmt.split()[0] stmt_type = stmt.split()[0]
@ -478,16 +478,16 @@ class CppHeaderParser(object):
if bases: if bases:
decl[1] = ": " + " ".join(bases) decl[1] = ": " + " ".join(bases)
return stmt_type, classname, True, decl return stmt_type, classname, True, decl
if stmt.startswith("enum"): if stmt.startswith("enum"):
return "enum", "", True, None return "enum", "", True, None
if stmt.startswith("namespace"): if stmt.startswith("namespace"):
stmt_list = stmt.split() stmt_list = stmt.split()
return stmt_list[0], stmt_list[1], True, None return stmt_list[0], stmt_list[1], True, None
if stmt.startswith("extern") and "\"C\"" in stmt: if stmt.startswith("extern") and "\"C\"" in stmt:
return "namespace", "", True, None return "namespace", "", True, None
if end_token == "}" and context == "enum": if end_token == "}" and context == "enum":
decl = self.parse_enum(stmt) decl = self.parse_enum(stmt)
return "enum", "", False, decl return "enum", "", False, decl
@ -495,7 +495,7 @@ class CppHeaderParser(object):
if end_token == ";" and stmt.startswith("typedef"): if end_token == ";" and stmt.startswith("typedef"):
# TODO: handle typedef's more intelligently # TODO: handle typedef's more intelligently
return stmt_type, "", False, None return stmt_type, "", False, None
paren_pos = stmt.find("(") paren_pos = stmt.find("(")
if paren_pos >= 0: if paren_pos >= 0:
# assume it's function or method declaration, # assume it's function or method declaration,
@ -518,18 +518,18 @@ class CppHeaderParser(object):
var_list = stmt.split(",") var_list = stmt.split(",")
var_type, var_name1, modlist, argno = self.parse_arg(var_list[0], -1) var_type, var_name1, modlist, argno = self.parse_arg(var_list[0], -1)
var_list = [var_name1] + [i.strip() for i in var_list[1:]] var_list = [var_name1] + [i.strip() for i in var_list[1:]]
for v in var_list: for v in var_list:
class_decl[3].append([var_type, v, "", var_modlist]) class_decl[3].append([var_type, v, "", var_modlist])
return stmt_type, "", False, None return stmt_type, "", False, None
# something unknown # something unknown
return stmt_type, "", False, None return stmt_type, "", False, None
def find_next_token(self, s, tlist, p=0): def find_next_token(self, s, tlist, p=0):
""" """
Finds the next token from the 'tlist' in the input 's', starting from position 'p'. Finds the next token from the 'tlist' in the input 's', starting from position 'p'.
Returns the first occured token and its position, or ("", len(s)) when no token is found Returns the first occured token and its position, or ("", len(s)) when no token is found
""" """
token = "" token = ""
tpos = len(s) tpos = len(s)
@ -551,55 +551,55 @@ class CppHeaderParser(object):
f = open(hname, "rt") f = open(hname, "rt")
linelist = list(f.readlines()) linelist = list(f.readlines())
f.close() f.close()
# states: # states:
SCAN = 0 # outside of a comment or preprocessor directive SCAN = 0 # outside of a comment or preprocessor directive
COMMENT = 1 # inside a multi-line comment COMMENT = 1 # inside a multi-line comment
DIRECTIVE = 2 # inside a multi-line preprocessor directive DIRECTIVE = 2 # inside a multi-line preprocessor directive
state = SCAN state = SCAN
self.block_stack = [["file", hname, True, True, None]] self.block_stack = [["file", hname, True, True, None]]
block_head = "" block_head = ""
self.lineno = 0 self.lineno = 0
for l0 in linelist: for l0 in linelist:
self.lineno += 1 self.lineno += 1
#print self.lineno #print self.lineno
l = l0.strip() l = l0.strip()
if state == SCAN and l.startswith("#"): if state == SCAN and l.startswith("#"):
state = DIRECTIVE state = DIRECTIVE
# fall through to the if state == DIRECTIVE check # fall through to the if state == DIRECTIVE check
if state == DIRECTIVE: if state == DIRECTIVE:
if not l.endswith("\\"): if not l.endswith("\\"):
state = SCAN state = SCAN
continue continue
if state == COMMENT: if state == COMMENT:
pos = l.find("*/") pos = l.find("*/")
if pos < 0: if pos < 0:
continue continue
l = l[pos+2:] l = l[pos+2:]
state = SCAN state = SCAN
if state != SCAN: if state != SCAN:
print "Error at %d: invlid state = %d" % (self.lineno, state) print "Error at %d: invlid state = %d" % (self.lineno, state)
sys.exit(-1) sys.exit(-1)
while 1: while 1:
token, pos = self.find_next_token(l, [";", "\"", "{", "}", "//", "/*"]) token, pos = self.find_next_token(l, [";", "\"", "{", "}", "//", "/*"])
if not token: if not token:
block_head += " " + l block_head += " " + l
break break
if token == "//": if token == "//":
block_head += " " + l[:pos] block_head += " " + l[:pos]
break break
if token == "/*": if token == "/*":
block_head += " " + l[:pos] block_head += " " + l[:pos]
pos = l.find("*/", pos+2) pos = l.find("*/", pos+2)
@ -608,7 +608,7 @@ class CppHeaderParser(object):
break break
l = l[pos+2:] l = l[pos+2:]
continue continue
if token == "\"": if token == "\"":
pos2 = pos + 1 pos2 = pos + 1
while 1: while 1:
@ -619,15 +619,15 @@ class CppHeaderParser(object):
if t2 == "\"": if t2 == "\"":
break break
pos2 += 2 pos2 += 2
block_head += " " + l[:pos2+1] block_head += " " + l[:pos2+1]
l = l[pos2+1:] l = l[pos2+1:]
continue continue
stmt = (block_head + " " + l[:pos]).strip() stmt = (block_head + " " + l[:pos]).strip()
stmt = " ".join(stmt.split()) # normalize the statement stmt = " ".join(stmt.split()) # normalize the statement
stack_top = self.block_stack[-1] stack_top = self.block_stack[-1]
decl = None decl = None
if stack_top[self.PROCESS_FLAG]: if stack_top[self.PROCESS_FLAG]:
# even if stack_top[PUBLIC_SECTION] is False, we still try to process the statement, # even if stack_top[PUBLIC_SECTION] is False, we still try to process the statement,
@ -641,26 +641,26 @@ class CppHeaderParser(object):
decls.append(decl) decls.append(decl)
else: else:
stmt_type, name, parse_flag = "block", "", False stmt_type, name, parse_flag = "block", "", False
if token == "{": if token == "{":
if stmt_type == "class": if stmt_type == "class":
public_section = False public_section = False
else: else:
public_section = True public_section = True
self.block_stack.append([stmt_type, name, parse_flag, public_section, decl]) self.block_stack.append([stmt_type, name, parse_flag, public_section, decl])
if token == "}": if token == "}":
if not self.block_stack: if not self.block_stack:
print "Error at %d: the block stack is empty" % (self.lineno,) print "Error at %d: the block stack is empty" % (self.lineno,)
self.block_stack[-1:] = [] self.block_stack[-1:] = []
if pos+1 < len(l) and l[pos+1] == ';': if pos+1 < len(l) and l[pos+1] == ';':
pos += 1 pos += 1
block_head = "" block_head = ""
l = l[pos+1:] l = l[pos+1:]
return decls return decls
def print_decls(self, decls): def print_decls(self, decls):
""" """
Prints the list of declarations, retrieived by the parse() method Prints the list of declarations, retrieived by the parse() method
@ -668,7 +668,7 @@ class CppHeaderParser(object):
for d in decls: for d in decls:
print d[0], d[1], ";".join(d[2]) print d[0], d[1], ";".join(d[2])
for a in d[3]: for a in d[3]:
print " ", a[0], a[1], a[2], print " ", a[0], a[1], a[2],
if a[3]: if a[3]:
print "; ".join(a[3]) print "; ".join(a[3])
else: else:
@ -676,7 +676,7 @@ class CppHeaderParser(object):
if __name__ == '__main__': if __name__ == '__main__':
parser = CppHeaderParser() parser = CppHeaderParser()
decls = [] decls = []
for hname in opencv_hdr_list: for hname in opencv_hdr_list:
decls += parser.parse(hname) decls += parser.parse(hname)
parser.print_decls(decls) parser.print_decls(decls)