def do_append_factories(body, scope, using_ns_arr, using_cls_arr, resolve_factory_name): from pysst.scope import get_full_scope_name, GetScopeError from pysst.keyword import Keyword from pysst.sstglobals import GlobalData # now check for factories scope_arr = scope.split("::") matches = AppendData.factory_regexp.findall(body) for factory_type, read_type, params in matches: factory_type = factory_type.strip().strip("_") full_factory_name = factory_type if resolve_factory_name: try: full_factory_name = get_full_scope_name(factory_type, scope_arr, using_cls_arr, using_ns_arr) except GetScopeError as e: sys.exit("Failed to resolve scope of factory %s" % factory_type) if read_type.endswith("_param"): param_name = param_obj = "" optional_val = None extra = False if read_type == "_optional_param": param_name, optional_val, param_obj = params.split(",")[:3] optional_val = optional_val.replace('"', "").strip() elif read_type == "_extra_param": param_name, param_obj = params.split(",")[:2] extra = True elif read_type == "_param": param_name, param_obj = params.split(",")[:2] param_name = param_name.replace('"', "").strip() keyword = Keyword(param_name, full_factory_name, optional_val, extra) reg_cls = GlobalData.keywords.get_registered_class(full_factory_name) keyword.allowed = reg_cls.allowed keyword.factory_type = True GlobalData.keywords[scope] = keyword else: pass
def do_parse_text(fullpath, text, do_gui=False): from pysst.path import skip_file, get_include_path from pysst.header import get_header_context, HeaderContextError from pysst.standardize import clean_file_text from pysst.sstglobals import GlobalData from pysst.scope import get_full_scope_name, GetScopeError, skip_subclass_of from pysst.append import do_append_keywords, append_keywords, add_registered_class from pysst.keyword import AllowedKeyword, Keyword fxn_re = re.compile("([a-zA-Z\d_::]+)[(]") if skip_file(fullpath): return print "Parsing", fullpath using_cls_arr = [] already_included = {} includes = re.compile("include\s*(.*)").findall(text) folder, name = os.path.split(fullpath) for path in includes: path = path.strip() incpath = "" if '"' in path: path = path.strip('"') incpath = get_include_path(path, folder, local_first=True) else: path = path.strip("<").strip(">") incpath = get_include_path(path, folder, local_first=False) if incpath: try: get_header_context(incpath, using_cls_arr, already_included) except HeaderContextError as e: print traceback(e) sys.exit("In parsing %s, somehow failed in parsing %s" % (fullpath, incpath)) text = clean_file_text(text) nopen = text.count("{") nclose = text.count("}") if nopen != nclose: sys.stderr.write("Skipping file %s with unbalanced brackets\n" % fullpath) return lines = text.split() frame_arr = FrameArray() sst_mode = False sstvariable_arr = [] sstvariable_depth = 0 sstkeyword_arr = [] #for manual sst keywords sstkeyword_scopes_arr = [] sstkeyword_depth = 0 sstobject_arr = [] #for manual sst keywords sstobject_scopes_arr = [] sstobject_depth = 0 scoped_ns_arr = [] my_using_cls_arr = [] using_ns_arr = [] scope_cls_arr = [] fxn_cls_arr = [] idx = 0 def debug_print(pos): return print_str = "%d %s %d %d %d %d %d %d %d %s" % ( idx, line, namespace_depth, class_depth, fxn_depth, struct_depth, declare_depth, template_depth, conditional_increment, pos) sys.stdout("%s\n" % print_str) Namespace = 0 namespace_depth = 0 Class = 1 class_depth = 0 Struct = 2 struct_depth = 0 Enum = 3 enum_depth = 0 Union = 4 union_depth = 0 Extern = 5 extern_depth = 0 Fxn = 6 fxn_depth = 0 Declare = 7 declare_depth = 0 AnonClass = 8 template_depth = 0 template_mode = False parentheses_depth = 0 nextincrement = [] nextdecrement = [] conditional_increment = False typedef_line = False template_inheritance_depth = 0 parent_class_name = "" inheritance_line = False constructor_line = False paren_depth = 0 current_fxn = "" def tostr(val): if val == Namespace: return "Namespace" elif val == Class: return "Class" elif val == Fxn: return "Fxn" elif val == Declare: return "Declare" do_print = False #"programming" in fullpath and "main.cc" in fullpath while idx < len(lines): line = lines[idx] if do_print: print line if False: #"programming" in fullpath and "main.cc" in fullpath: print "%s ns=%d cl=%d st=%d fxn=%d dec=%d tmpl=%d" % ( line, namespace_depth, class_depth, struct_depth, fxn_depth, declare_depth, template_depth), map(tostr, nextincrement), map( tostr, nextdecrement), scope_cls_arr debug_print("top level") if fxn_depth == 0 and re.match(r'template\b', line): template_mode = True template_depth += line.count("<") template_depth -= line.count(">") elif sstvariable_depth == 1: if line == "}": sstvariable_depth = 0 sstvariable_arr.append(line) elif sstobject_depth == 1: if line == "}": sstobject_depth = 0 sstobject_arr.append(line) elif sstkeyword_depth == 1: if line == "}": sstkeyword_depth = 0 #also append any keyword context after it #to tell us what the keyword name is context_arr = [] context_idx = idx context_line = line initial_idx = context_idx try: while not "_param" in context_line: context_arr.append(context_line) context_idx += 1 context_line = lines[context_idx] while not ";" in context_line: context_arr.append(context_line) context_idx += 1 context_line = lines[context_idx] except IndexError: sys.stderr.write("\n".join(sstkeyword_arr)) sys.stderr.write("\n") sys.exit( "Somehow ran off the end trying to parse keyword description and the lines above. Are you sure there's a keyword there in file %s?" % fullpath) context = "\n".join(context_arr) sstkeyword_arr.append(context) sstkeyword_arr.append(line) elif template_mode: template_depth += line.count("<") template_depth -= line.count(">") template_mode = template_depth != 0 elif parentheses_depth: parentheses_depth += line.count("(") parentheses_depth -= line.count(")") elif "SpktRegister" in line: reg_cls_arr = [] while not ";" in line: reg_cls_arr.append(line) idx += 1 line = lines[idx] reg_cls_arr.append(");") reg_cls_specs = " ".join(reg_cls_arr) add_registered_class(reg_cls_specs, scoped_ns_arr, using_ns_arr, using_cls_arr) elif line == "using": idx += 1 #skip namespace line = lines[idx] if line == "namespace": idx += 1 #skip ahead line = lines[idx] scopes = line.strip().strip(";") using_ns_arr.append(scopes) else: cls = line.strip().strip(";") my_using_cls_arr.append(cls) using_cls_arr.append(cls) if "{" in line or "}" in line: sys.exit("using namespace: " + line) elif line == "namespace": nextincrement.append(Namespace) idx += 1 line = lines[idx] debug_print("found namespace") if do_print: print "NS", line scoped_ns_arr.append(line) if do_print: print scoped_ns_arr if line == "{": scoped_ns_arr.append("anon") nextincrement.pop() namespace_depth += 1 nextdecrement.append(Namespace) elif "{" in line or "}" in line: sys.exit("namespace: " + line) elif line == "={": declare_depth += 1 nextdecrement.append(Declare) elif line == "{": inheritance_line = False conditional_increment = False constructor_line = False if nextincrement: incrementer = nextincrement.pop() if incrementer == Namespace: namespace_depth += 1 elif incrementer == Class or incrementer == AnonClass: class_depth += 1 elif incrementer == Fxn: fxn_depth += 1 elif incrementer == Declare: declare_depth += 1 elif incrementer == Union: union_depth += 1 elif incrementer == Enum: enum_depth += 1 elif incrementer == Struct: struct_depth += 1 elif incrementer == Extern: extern_depth += 1 nextdecrement.append(incrementer) else: #nothing pending, a fxn! fxn_depth += 1 nextdecrement.append(Fxn) elif inheritance_line: if "public" in line: pass elif "virtual" in line: pass else: parent_class_name = line if "<" == line: template_inheritance_depth += 1 idx += 1 continue elif ">" == line: template_inheritance_depth -= 1 idx += 1 continue if template_inheritance_depth: idx += 1 continue scope_arr = scoped_ns_arr[:] for entry in scope_cls_arr: scope_arr.extend(entry.split("::")) full_childname = "::".join(scope_arr) for parent in line.strip().split(","): parent = parent.strip() if parent and not skip_subclass_of(parent): try: parent_plus_scope = get_full_scope_name( parent, scope_arr, using_cls_arr, using_ns_arr) except GetScopeError: sys.exit( "Failed to find parent %s for child class %s in parsing %s\n" % (parent, full_childname, fullpath)) if not parent_plus_scope: sys.exit("no parent scope") GlobalData.keywords.add_parent(parent_plus_scope, full_childname) elif line == "}" or line == "};": decrementer = nextdecrement.pop() if decrementer == Namespace: namespace_depth -= 1 if do_print: print "NS Drop" scoped_ns_arr.pop() elif decrementer == AnonClass: class_depth -= 1 elif decrementer == Class: class_depth -= 1 scope_cls_arr.pop() elif decrementer == Fxn: fxn_depth -= 1 if fxn_depth == 0: #close out the scope class_arr = scope_cls_arr[:] class_arr.extend(fxn_cls_arr) classname = "::".join(class_arr) scope = "global" if classname: try: scope = get_full_scope_name( classname, scoped_ns_arr, using_cls_arr, using_ns_arr) except GetScopeError: sys.exit( "Failure resolving namespaces in parsing function %s of class %s" % (current_fxn, classname)) elif scoped_ns_arr: scope = "::".join(scoped_ns_arr) frame_arr.append(" ") #padding to make parsing work body = " ".join(frame_arr) if do_print: print "Scope=", scope do_append_keywords(body, scope, using_ns_arr, using_cls_arr) frame_arr = FrameArray() fxn_cls_arr = [] elif decrementer == Declare: declare_depth -= 1 elif decrementer == Union: union_depth -= 1 elif decrementer == Enum: enum_depth -= 1 elif decrementer == Struct: struct_depth -= 1 elif decrementer == Extern: extern_depth -= 1 elif "{" in line: sys.exit(line) elif "}" in line: sys.exit(line) elif line == "typedef": #peak ahead a bit line_p_1 = lines[idx + 1] if line_p_1 == "struct": line_p_3 = lines[idx + 3] if ";" in line_p_3: #straigh up typedef - skip it all idx += 3 elif line == "class" or line == "struct": next_line = lines[idx + 1] if "{" in next_line: conditional_increment = True nextincrement.append(AnonClass) else: idx += 1 prev_line = line line = lines[idx] if ";" in line: #forward declaration conditional_increment = False elif "{" in line or "}" in line: sys.exit("class: " + line) else: conditional_increment = True nextincrement.append(Class) clsname = line.strip(":") scope_cls_arr.append(clsname) all_scopes = scoped_ns_arr[:] all_scopes.extend(scope_cls_arr) scoped_name = "::".join(all_scopes) GlobalData.keywords.register_scope(scoped_name) print "\t\t", scoped_name elif line == "enum" and paren_depth == 0: nextincrement.append(Enum) conditional_increment = True elif line == "extern": next_line = lines[idx + 1] if next_line == '"C"': idx += 1 else: nextincrement.append(Extern) conditional_increment = True elif ";" in line: #throw away the increment - just a forward declare if conditional_increment: incrementer = nextincrement.pop() if incrementer == Class: scope_cls_arr.pop() #throw out forward declared class conditional_increment = False elif fxn_depth != 0: frame_arr.append(";") elif nextincrement and nextincrement[-1] == Class and fxn_depth == 0: if "public" in line: pass elif "virtual" in line: pass elif line == ":": inheritance_line = True else: pass #some craziness elif fxn_depth == 0 and line.count(":") == 1: constructor_line = True elif not constructor_line and not paren_depth and fxn_depth == 0 and "::" in line and fxn_re.search( line): fxn_spec = fxn_re.search(line).groups()[0] fxn_spec = fxn_spec.split("::") fxn_cls_arr = fxn_spec[:-1] current_fxn = fxn_spec[-1] elif "sstobject" in line: idx += 1 class_arr = scope_cls_arr[:] class_arr.extend(fxn_cls_arr) classname = "::".join(class_arr) scope = "global" if classname: scope = get_full_scope_name(classname, scoped_ns_arr, using_cls_arr, using_ns_arr) sstobject_scopes_arr.append(scope) sstobject_arr.append("sstobject {") sstobject_depth = 1 elif "sstvariable" in line: idx += 1 sstvariable_arr.append("sstvariable {") sstvariable_depth = 1 elif "sstkeyword" in line: idx += 1 class_arr = scope_cls_arr[:] class_arr.extend(fxn_cls_arr) classname = "::".join(class_arr) scope = "global" if classname: scope = get_full_scope_name(classname, scoped_ns_arr, using_cls_arr, using_ns_arr) sstkeyword_scopes_arr.append(scope) sstkeyword_arr.append("sstkeyword {") sstkeyword_depth = 1 else: if fxn_depth > 0: frame_arr.append(line) paren_depth += line.count("(") paren_depth -= line.count(")") idx += 1 from pysst.header import set_using_namespace set_using_namespace(fullpath, my_using_cls_arr) if namespace_depth != 0 or class_depth != 0 or fxn_depth != 0 or struct_depth != 0 or enum_depth != 0 or template_depth != 0 or parentheses_depth != 0 or extern_depth != 0: sys.exit("depths wrong on parsed file") #now process the sst variables sstvariable_text = "\n".join(sstvariable_arr) matches = re.compile('sstvariable\s*[{](.*?[}])', re.DOTALL).findall(sstvariable_text) for body in matches: attr_matches = re.compile("([_a-zA-Z]+)\s*[=](.*?)[;]", re.DOTALL).findall(body) for attr_name, attr_val in attr_matches: attr_val = re.compile("([\n\s]+)").sub(" ", attr_val).strip() GlobalData.sstvariables[attr_name] = attr_val #now process the sst keywords sstkeyword_text = "\n".join(sstkeyword_arr) matches = re.compile( 'sstkeyword\s*[{](.*?[}]).*?param\s*[(]\s*["](.*?)["].', re.DOTALL).findall(sstkeyword_text) # You can declare variables for the documentation system. # This is useful if you have a lot of parameters with basically the same documentation # and you just want to reuse the same documentation for each one def sstkeyword_var_repl(match): varname = match.groups()[0] return GlobalData.sstvariables[varname] for i in range(len(matches)): body, name = matches[i] body = re.compile("[$]([\da-zA-Z_]+)").sub(sstkeyword_var_repl, body) scope = sstkeyword_scopes_arr[i] attr_matches = re.compile("([_a-zA-Z]+)\s*[=](.*?)[;]", re.DOTALL).findall(body) docstring = "" defval = "" allowed = [] extra = None alias = "" tab = "" for attr_name, attr_val in attr_matches: #attr_val = attr_val.strip().replace("\n"," ") attr_val = re.compile("([\n\s]+)").sub(" ", attr_val).strip() if attr_name == "docstring": docstring = attr_val elif attr_name == "gui": defval = attr_val elif attr_name == "default": defval = attr_val elif attr_name == "extra": if attr_val == "true": extra = True elif attr_val == "false": extra = False else: sys.exit("Invalid value %s for extra specification" % attr_val) elif attr_name == "tab": tab = attr_val elif attr_name == "alias": alias = attr_val else: allowed.append((attr_name, attr_val)) keyword = None try: keyword = GlobalData.keywords[scope][name] except: sys.stderr.write("Bad sstkeyword:\nscope=%s\nname=%s\n%s\n" % (scope, name, body)) sys.exit("Probably you forgot a semicolon") docstring_split = docstring.split() docstring_arr = [] docstring_line_arr = [] maxwidth = 50 docstring_line_length = 0 for entry in docstring_split: docstring_line_arr.append(entry) docstring_line_length += len(entry) if "ENDL" in entry: docstring_line_length = 0 elif docstring_line_length > maxwidth: docstring_arr.append(" ".join(docstring_line_arr)) docstring_line_arr = [] docstring_line_length = 0 if docstring_line_arr: docstring_arr.append(" ".join(docstring_line_arr)) docstring = "ENDL".join(docstring_arr) if defval: keyword.gui_default = defval keyword.docstring = docstring keyword.tab = tab keyword.alias = alias if extra != None: keyword.extra = extra for val, valdocstring in allowed: allowed_val = AllowedKeyword(val, valdocstring) keyword.add_allowed(allowed_val) #sst objects are a gui only thing if not do_gui: return #now process the sst objects sstobject_text = "\n".join(sstobject_arr) matches = re.compile('sstobject\s*[{](.*?)[}]', re.DOTALL).findall(sstobject_text) for i in range(len(matches)): body = matches[i] scope = sstobject_scopes_arr[i] attr_matches = re.compile("([_a-zA-Z]+)\s*[=](.*?)[;]", re.DOTALL).findall(body) docstring = "" name = "" defval = "" clstype = "" tab = "" alias = "" yesno = False extra = False for attr_name, attr_val in attr_matches: attr_val = attr_val.strip().replace("\n", " ") if attr_name == "docstring": docstring = attr_val elif attr_name == "gui": defval = attr_val elif attr_name == "name": name = attr_val elif attr_name == "tab": tab = attr_val elif attr_name == "alias": alias = attr_val elif attr_name == "yesno": yesno = True if attr_val != "true": sys.exit( "Invalid yesno specification %s. Should only be true." % attr_val) elif attr_name == "type": clstype = attr_val else: sys.exit("invalid sstobject attribute %s" % attr_name) if not name or not clstype or not defval: sys.exit( "Invalid sstobject. Check that you have all atributes (docstring,gui,name,type) and used semicolons:\n%s" % body) keyword = Keyword(name, clstype, defval, extra, yesno) keyword.gui_default = defval keyword.fake_type = True keyword.tab = tab keyword.alias = alias keyword.docstring = docstring keyword.yesno = yesno if yesno: keyword.fake_type = False allowed_val = AllowedKeyword("yes", "Do use", clstype) keyword.add_allowed(allowed_val) allowed_val = AllowedKeyword("no", "Do NOT use", clstype) keyword.add_allowed(allowed_val) else: allowed_val = AllowedKeyword(defval, "", clstype) keyword.add_allowed(allowed_val) GlobalData.keywords[scope] = keyword
def do_parse_text(fullpath, text, do_gui=False): from pysst.path import skip_file, get_include_path from pysst.header import get_header_context, HeaderContextError from pysst.standardize import clean_file_text from pysst.sstglobals import GlobalData from pysst.scope import get_full_scope_name, GetScopeError, skip_subclass_of from pysst.append import do_append_keywords, append_keywords, add_registered_class from pysst.keyword import AllowedKeyword, Keyword fxn_re = re.compile("([a-zA-Z\d_::]+)[(]") if skip_file(fullpath): return print "Parsing", fullpath using_cls_arr = [] already_included = {} includes = re.compile("include\s*(.*)").findall(text) folder, name = os.path.split(fullpath) for path in includes: path = path.strip() incpath = "" if '"' in path: path = path.strip('"') incpath = get_include_path(path, folder, local_first=True) else: path = path.strip("<").strip(">") incpath = get_include_path(path, folder, local_first=False) if incpath: try: get_header_context(incpath, using_cls_arr, already_included) except HeaderContextError as e: print traceback(e) sys.exit("In parsing %s, somehow failed in parsing %s" % (fullpath, incpath)) text = clean_file_text(text) nopen = text.count("{") nclose = text.count("}") if nopen != nclose: sys.stderr.write("Skipping file %s with unbalanced brackets\n" % fullpath) return lines = text.split() frame_arr = FrameArray() sst_mode = False sstvariable_arr = [] sstvariable_depth = 0 sstkeyword_arr = [] #for manual sst keywords sstkeyword_scopes_arr = [] sstkeyword_depth = 0 sstobject_arr = [] #for manual sst keywords sstobject_scopes_arr = [] sstobject_depth = 0 scoped_ns_arr = [] my_using_cls_arr = [] using_ns_arr = [] scope_cls_arr = [] fxn_cls_arr = [] idx = 0 def debug_print(pos): return print_str = "%d %s %d %d %d %d %d %d %d %s" % (idx, line, namespace_depth, class_depth, fxn_depth, struct_depth, declare_depth, template_depth, conditional_increment, pos) sys.stdout("%s\n" % print_str) Namespace = 0 namespace_depth = 0 Class = 1 class_depth = 0 Struct = 2 struct_depth = 0 Enum = 3 enum_depth = 0 Union = 4 union_depth = 0 Extern = 5 extern_depth = 0 Fxn = 6 fxn_depth = 0 Declare = 7 declare_depth = 0 AnonClass = 8 template_depth = 0 template_mode = False parentheses_depth = 0 nextincrement = [] nextdecrement = [] conditional_increment = False typedef_line = False template_inheritance_depth = 0 parent_class_name = "" inheritance_line = False constructor_line = False paren_depth = 0 current_fxn = "" def tostr(val): if val == Namespace: return "Namespace" elif val == Class: return "Class" elif val == Fxn: return "Fxn" elif val == Declare: return "Declare" do_print = False #"programming" in fullpath and "main.cc" in fullpath while idx < len(lines): line = lines[idx] if do_print: print line if False: #"programming" in fullpath and "main.cc" in fullpath: print "%s ns=%d cl=%d st=%d fxn=%d dec=%d tmpl=%d" % (line, namespace_depth, class_depth, struct_depth, fxn_depth, declare_depth, template_depth), map(tostr, nextincrement), map(tostr, nextdecrement), scope_cls_arr debug_print("top level") if fxn_depth == 0 and re.match(r'template\b', line): template_mode = True template_depth += line.count("<") template_depth -= line.count(">") elif sstvariable_depth == 1: if line == "}": sstvariable_depth = 0 sstvariable_arr.append(line) elif sstobject_depth == 1: if line == "}": sstobject_depth = 0 sstobject_arr.append(line) elif sstkeyword_depth == 1: if line == "}": sstkeyword_depth = 0 #also append any keyword context after it #to tell us what the keyword name is context_arr = [] context_idx = idx context_line = line initial_idx = context_idx try: while not "_param" in context_line: context_arr.append(context_line) context_idx += 1 context_line = lines[context_idx] while not ";" in context_line: context_arr.append(context_line) context_idx += 1 context_line = lines[context_idx] except IndexError: sys.stderr.write("\n".join(sstkeyword_arr)) sys.stderr.write("\n") sys.exit("Somehow ran off the end trying to parse keyword description and the lines above. Are you sure there's a keyword there in file %s?" % fullpath) context = "\n".join(context_arr) sstkeyword_arr.append(context) sstkeyword_arr.append(line) elif template_mode: template_depth += line.count("<") template_depth -= line.count(">") template_mode = template_depth != 0 elif parentheses_depth: parentheses_depth += line.count("(") parentheses_depth -= line.count(")") elif "SpktRegister" in line: reg_cls_arr = [] while not ";" in line: reg_cls_arr.append(line) idx += 1 line = lines[idx] reg_cls_arr.append(");") reg_cls_specs = " ".join(reg_cls_arr) add_registered_class(reg_cls_specs, scoped_ns_arr, using_ns_arr, using_cls_arr) elif line == "using": idx += 1 #skip namespace line = lines[idx] if line == "namespace": idx += 1 #skip ahead line = lines[idx] scopes = line.strip().strip(";") using_ns_arr.append(scopes) else: cls = line.strip().strip(";"); my_using_cls_arr.append(cls) using_cls_arr.append(cls) if "{" in line or "}" in line: sys.exit("using namespace: " + line) elif line == "namespace": nextincrement.append(Namespace) idx += 1 line = lines[idx] debug_print("found namespace") if do_print: print "NS", line scoped_ns_arr.append(line) if do_print: print scoped_ns_arr if line == "{": scoped_ns_arr.append("anon") nextincrement.pop() namespace_depth += 1 nextdecrement.append(Namespace) elif "{" in line or "}" in line: sys.exit("namespace: " + line) elif line == "={": declare_depth += 1 nextdecrement.append(Declare) elif line == "{": inheritance_line = False conditional_increment = False constructor_line = False if nextincrement: incrementer = nextincrement.pop() if incrementer == Namespace: namespace_depth += 1 elif incrementer == Class or incrementer == AnonClass: class_depth += 1 elif incrementer == Fxn: fxn_depth += 1 elif incrementer == Declare: declare_depth += 1 elif incrementer == Union: union_depth += 1 elif incrementer == Enum: enum_depth += 1 elif incrementer == Struct: struct_depth += 1 elif incrementer == Extern: extern_depth += 1 nextdecrement.append(incrementer) else: #nothing pending, a fxn! fxn_depth += 1 nextdecrement.append(Fxn) elif inheritance_line: if "public" in line: pass elif "virtual" in line: pass else: parent_class_name = line if "<" == line: template_inheritance_depth += 1 idx += 1 continue elif ">" == line: template_inheritance_depth -= 1 idx += 1 continue if template_inheritance_depth: idx += 1 continue scope_arr = scoped_ns_arr[:] for entry in scope_cls_arr: scope_arr.extend(entry.split("::")) full_childname = "::".join(scope_arr) for parent in line.strip().split(","): parent = parent.strip() if parent and not skip_subclass_of(parent): try: parent_plus_scope = get_full_scope_name(parent, scope_arr, using_cls_arr, using_ns_arr) except GetScopeError: sys.exit("Failed to find parent %s for child class %s in parsing %s\n" % (parent, full_childname, fullpath)) if not parent_plus_scope: sys.exit("no parent scope") GlobalData.keywords.add_parent(parent_plus_scope, full_childname) elif line == "}" or line == "};": decrementer = nextdecrement.pop() if decrementer == Namespace: namespace_depth -= 1 if do_print: print "NS Drop" scoped_ns_arr.pop() elif decrementer == AnonClass: class_depth -= 1 elif decrementer == Class: class_depth -= 1 scope_cls_arr.pop() elif decrementer == Fxn: fxn_depth -= 1 if fxn_depth == 0: #close out the scope class_arr = scope_cls_arr[:] ; class_arr.extend(fxn_cls_arr) classname = "::".join(class_arr) scope = "global" if classname: try: scope = get_full_scope_name(classname, scoped_ns_arr, using_cls_arr, using_ns_arr) except GetScopeError: sys.exit("Failure resolving namespaces in parsing function %s of class %s" % (current_fxn, classname)) elif scoped_ns_arr: scope = "::".join(scoped_ns_arr) frame_arr.append(" ") #padding to make parsing work body = " ".join(frame_arr) if do_print: print "Scope=",scope do_append_keywords(body, scope, using_ns_arr, using_cls_arr) frame_arr = FrameArray() fxn_cls_arr = [] elif decrementer == Declare: declare_depth -= 1 elif decrementer == Union: union_depth -= 1 elif decrementer == Enum: enum_depth -= 1 elif decrementer == Struct: struct_depth -= 1 elif decrementer == Extern: extern_depth -= 1 elif "{" in line: sys.exit(line) elif "}" in line: sys.exit(line) elif line == "typedef": #peak ahead a bit line_p_1 = lines[idx+1] if line_p_1 == "struct": line_p_3 = lines[idx+3] if ";" in line_p_3: #straigh up typedef - skip it all idx += 3 elif line == "class" or line == "struct": next_line = lines[idx+1] if "{" in next_line: conditional_increment = True nextincrement.append(AnonClass) else: idx += 1 prev_line = line line = lines[idx] if ";" in line: #forward declaration conditional_increment = False elif "{" in line or "}" in line: sys.exit("class: " + line) else: conditional_increment = True nextincrement.append(Class) clsname = line.strip(":") scope_cls_arr.append(clsname) all_scopes = scoped_ns_arr[:] all_scopes.extend(scope_cls_arr) scoped_name = "::".join(all_scopes) GlobalData.keywords.register_scope(scoped_name) print "\t\t", scoped_name elif line == "enum" and paren_depth == 0: nextincrement.append(Enum) conditional_increment = True elif line == "extern": next_line = lines[idx+1] if next_line == '"C"': idx += 1 else: nextincrement.append(Extern) conditional_increment = True elif ";" in line: #throw away the increment - just a forward declare if conditional_increment: incrementer = nextincrement.pop() if incrementer == Class: scope_cls_arr.pop() #throw out forward declared class conditional_increment = False elif fxn_depth != 0: frame_arr.append(";") elif nextincrement and nextincrement[-1] == Class and fxn_depth == 0: if "public" in line: pass elif "virtual" in line: pass elif line == ":": inheritance_line = True else: pass #some craziness elif fxn_depth == 0 and line.count(":") == 1: constructor_line = True elif not constructor_line and not paren_depth and fxn_depth == 0 and "::" in line and fxn_re.search(line): fxn_spec = fxn_re.search(line).groups()[0] fxn_spec = fxn_spec.split("::") fxn_cls_arr = fxn_spec[:-1] current_fxn = fxn_spec[-1] elif "sstobject" in line: idx += 1 class_arr = scope_cls_arr[:] ; class_arr.extend(fxn_cls_arr) classname = "::".join(class_arr) scope = "global" if classname: scope = get_full_scope_name(classname, scoped_ns_arr, using_cls_arr, using_ns_arr) sstobject_scopes_arr.append(scope) sstobject_arr.append("sstobject {") sstobject_depth = 1 elif "sstvariable" in line: idx += 1 sstvariable_arr.append("sstvariable {") sstvariable_depth = 1 elif "sstkeyword" in line: idx += 1 class_arr = scope_cls_arr[:] ; class_arr.extend(fxn_cls_arr) classname = "::".join(class_arr) scope = "global" if classname: scope = get_full_scope_name(classname, scoped_ns_arr, using_cls_arr, using_ns_arr) sstkeyword_scopes_arr.append(scope) sstkeyword_arr.append("sstkeyword {") sstkeyword_depth = 1 else: if fxn_depth > 0: frame_arr.append(line) paren_depth += line.count("(") paren_depth -= line.count(")") idx += 1 from pysst.header import set_using_namespace set_using_namespace(fullpath, my_using_cls_arr) if namespace_depth != 0 or class_depth != 0 or fxn_depth != 0 or struct_depth != 0 or enum_depth != 0 or template_depth != 0 or parentheses_depth != 0 or extern_depth != 0: sys.exit("depths wrong on parsed file") #now process the sst variables sstvariable_text = "\n".join(sstvariable_arr) matches = re.compile('sstvariable\s*[{](.*?[}])',re.DOTALL).findall(sstvariable_text) for body in matches: attr_matches = re.compile("([_a-zA-Z]+)\s*[=](.*?)[;]",re.DOTALL).findall(body) for attr_name, attr_val in attr_matches: attr_val = re.compile("([\n\s]+)").sub(" ",attr_val).strip() GlobalData.sstvariables[attr_name] = attr_val #now process the sst keywords sstkeyword_text = "\n".join(sstkeyword_arr) matches = re.compile('sstkeyword\s*[{](.*?[}]).*?param\s*[(]\s*["](.*?)["].',re.DOTALL).findall(sstkeyword_text) # You can declare variables for the documentation system. # This is useful if you have a lot of parameters with basically the same documentation # and you just want to reuse the same documentation for each one def sstkeyword_var_repl(match): varname = match.groups()[0] return GlobalData.sstvariables[varname] for i in range(len(matches)): body, name = matches[i] body = re.compile("[$]([\da-zA-Z_]+)").sub(sstkeyword_var_repl, body) scope = sstkeyword_scopes_arr[i] attr_matches = re.compile("([_a-zA-Z]+)\s*[=](.*?)[;]",re.DOTALL).findall(body) docstring = "" defval = "" allowed = [] extra = None alias = "" tab = "" for attr_name, attr_val in attr_matches: #attr_val = attr_val.strip().replace("\n"," ") attr_val = re.compile("([\n\s]+)").sub(" ",attr_val).strip() if attr_name == "docstring": docstring = attr_val elif attr_name == "gui": defval = attr_val elif attr_name == "default": defval = attr_val elif attr_name == "extra": if attr_val == "true": extra = True elif attr_val == "false": extra = False else: sys.exit("Invalid value %s for extra specification" % attr_val) elif attr_name == "tab": tab = attr_val elif attr_name == "alias": alias = attr_val else: allowed.append((attr_name,attr_val)) keyword = None try: keyword = GlobalData.keywords[scope][name] except: sys.stderr.write("Bad sstkeyword:\nscope=%s\nname=%s\n%s\n" % (scope,name,body)) sys.exit("Probably you forgot a semicolon") docstring_split = docstring.split() docstring_arr = [] docstring_line_arr = [] maxwidth = 50 docstring_line_length = 0 for entry in docstring_split: docstring_line_arr.append(entry) docstring_line_length += len(entry) if "ENDL" in entry: docstring_line_length = 0 elif docstring_line_length > maxwidth: docstring_arr.append(" ".join(docstring_line_arr)) docstring_line_arr = [] docstring_line_length = 0 if docstring_line_arr: docstring_arr.append(" ".join(docstring_line_arr)) docstring = "ENDL".join(docstring_arr) if defval: keyword.gui_default = defval keyword.docstring = docstring keyword.tab = tab keyword.alias = alias if extra != None: keyword.extra = extra for val, valdocstring in allowed: allowed_val = AllowedKeyword(val, valdocstring) keyword.add_allowed(allowed_val) #sst objects are a gui only thing if not do_gui: return #now process the sst objects sstobject_text = "\n".join(sstobject_arr) matches = re.compile('sstobject\s*[{](.*?)[}]',re.DOTALL).findall(sstobject_text) for i in range(len(matches)): body = matches[i] scope = sstobject_scopes_arr[i] attr_matches = re.compile("([_a-zA-Z]+)\s*[=](.*?)[;]",re.DOTALL).findall(body) docstring = "" name = "" defval = "" clstype = "" tab = "" alias = "" yesno = False extra = False for attr_name, attr_val in attr_matches: attr_val = attr_val.strip().replace("\n"," ") if attr_name == "docstring": docstring = attr_val elif attr_name == "gui": defval = attr_val elif attr_name == "name": name = attr_val elif attr_name == "tab": tab = attr_val elif attr_name == "alias": alias = attr_val elif attr_name == "yesno": yesno = True; if attr_val != "true": sys.exit("Invalid yesno specification %s. Should only be true." % attr_val) elif attr_name == "type": clstype = attr_val else: sys.exit("invalid sstobject attribute %s" % attr_name) if not name or not clstype or not defval: sys.exit("Invalid sstobject. Check that you have all atributes (docstring,gui,name,type) and used semicolons:\n%s" % body) keyword = Keyword(name, clstype, defval, extra, yesno) keyword.gui_default = defval keyword.fake_type = True keyword.tab = tab keyword.alias = alias keyword.docstring = docstring keyword.yesno = yesno if yesno: keyword.fake_type = False allowed_val = AllowedKeyword("yes", "Do use", clstype) keyword.add_allowed(allowed_val) allowed_val = AllowedKeyword("no", "Do NOT use", clstype) keyword.add_allowed(allowed_val) else: allowed_val = AllowedKeyword(defval, "", clstype) keyword.add_allowed(allowed_val) GlobalData.keywords[scope] = keyword
def add_registered_class(text, scoped_ns_arr, using_ns_arr, using_cls_arr): from pysst.scope import get_full_scope_name, GetScopeError from pysst.keyword import Keyword from pysst.sstglobals import GlobalData regexp = "SpktRegister(.*?)\s*[(](.*?)[)][;]" match = re.compile(regexp,re.DOTALL).search(text) if not match: return clsname, specs = match.groups() # The regexp accidentally picks up function declarations rather # than actual instantiations. This ignores the declaration function if '?"' in clsname or "appstr" in specs or "servstr" in specs: return # We have in this order: # allowed values "|" separated # the type name of the class # optionally, a doc string for the keyword match = None keyvals = typenames = docstring = "" match = re.compile('["](.*?)["]\s*[,](.*?)["](.*?)["]').search(specs) if not match: match = re.compile('["](.*?)["]\s*[,](.*)').search(specs) if not match: sys.exit("Could not parse SpktRegister %s" % specs) keyvals, typenames = match.groups() typenames = typenames.strip().strip(")").strip() else: keyvals, typenames, docstring = match.groups() typenames = typenames.strip(",").strip().strip(",").strip() keyvals = keyvals.replace('"','') keyvals = keyvals.strip() #docstring = docstring.replace('"','') docstring = docstring.strip() docstring = docstring.replace("\n"," ") length = len(docstring) newlength = length + 1 while length != newlength: length = len(docstring) docstring = docstring.replace(" "," ") newlength = len(docstring) parent = child = None if clsname == "App": parent = "sstmac::sw::app" child = typenames else: parent, child = typenames.split(",") parent = parent.replace('"','') parent = parent.strip() try: parent = get_full_scope_name(parent, scoped_ns_arr, using_cls_arr, using_ns_arr) except GetScopeError as e: child = child.replace('"','') child = child.strip() sys.exit("Could not resolve parent name %s for subclass %s" % (parent, child)) child = child.replace('"','') child = child.strip() child = get_full_scope_name(child, scoped_ns_arr, using_ns_arr, using_cls_arr) # parent = X in SpktRegisterX(...) # keyvals = "|" separated valid keywords # child = actual name of the class in C++ code # docstring = optional docstring GlobalData.keywords.add_registered_class(parent, keyvals, child, docstring)