Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Respect #line preprocessor directives #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 106 additions & 61 deletions CppHeaderParser/CppHeaderParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@
# Controls trace_print
debug_trace = 0

if sys.version_info >= (3, 3):
# `raise e from src_e` syntax only supported on python 3.3+
exec("def raise_exc(e, src_e): raise e from src_e", globals())
else:

def raise_exc(e, src_e):
raise e


def error_print(arg):
if print_errors:
Expand Down Expand Up @@ -223,16 +231,11 @@ def is_property_namestack(nameStack):
return r


def detect_lineno(s):
"""Detect the line number for a given token string"""
try:
rtn = s.lineno()
if rtn != -1:
return rtn
except:
pass
global curLine
return curLine
def set_location_info(thing, location):
filename, line_number = location
if filename:
thing["filename"] = filename
thing["line_number"] = line_number


def filter_out_attribute_keyword(stack):
Expand Down Expand Up @@ -320,22 +323,11 @@ def _split_by_comma(namestack):
class TagStr(str):
"""Wrapper for a string that allows us to store the line number associated with it"""

lineno_reg = {}

def __new__(cls, *args, **kw):
new_obj = str.__new__(cls, *args)
if "lineno" in kw:
TagStr.lineno_reg[id(new_obj)] = kw["lineno"]
return new_obj

def __del__(self):
try:
del TagStr.lineno_reg[id(self)]
except:
pass

def lineno(self):
return TagStr.lineno_reg.get(id(self), -1)
def __new__(cls, *args, **kwargs):
location = kwargs.pop("location")
s = str.__new__(cls, *args, **kwargs)
s.location = location
return s


class CppParseError(Exception):
Expand Down Expand Up @@ -420,7 +412,7 @@ def get_pure_virtual_methods(self, type="public"):
r[meth["name"]] = meth
return r

def __init__(self, nameStack, curTemplate, doxygen):
def __init__(self, nameStack, curTemplate, doxygen, location):
#: hm
self["nested_classes"] = []
self["parent"] = None
Expand Down Expand Up @@ -472,7 +464,7 @@ def __init__(self, nameStack, curTemplate, doxygen):
pass

self["name"] = nameStack[1]
self["line_number"] = detect_lineno(nameStack[0])
set_location_info(self, location)

# Handle template classes
if len(nameStack) > 3 and nameStack[2].startswith("<"):
Expand Down Expand Up @@ -706,8 +698,8 @@ class CppUnion(CppClass):
* ``members`` - List of members of the union
"""

def __init__(self, nameStack, doxygen):
CppClass.__init__(self, nameStack, None, doxygen)
def __init__(self, nameStack, doxygen, location):
CppClass.__init__(self, nameStack, None, doxygen, location)
self["name"] = "union " + self["name"]
self["members"] = self["properties"]["public"]

Expand Down Expand Up @@ -837,7 +829,7 @@ def show(self):
r.append("destructor")
return "\n\t\t ".join(r)

def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen):
def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen, location):
debug_print("Method: %s" % nameStack)
debug_print("Template: %s" % curTemplate)

Expand Down Expand Up @@ -903,7 +895,7 @@ def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen):
break

self.update(methinfo)
self["line_number"] = detect_lineno(nameStack[0])
set_location_info(self, location)

# Filter out initializer lists used in constructors
try:
Expand Down Expand Up @@ -959,8 +951,12 @@ def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen):
i += 1

if param_separator:
tpstack = paramsStack[0:param_separator]
param = CppVariable(
paramsStack[0:param_separator], None, doxyVarDesc=doxyVarDesc
tpstack,
None,
getattr(tpstack[0], "location", location),
doxyVarDesc=doxyVarDesc,
)
if len(list(param.keys())):
params.append(param)
Expand All @@ -969,7 +965,12 @@ def __init__(self, nameStack, curClass, methinfo, curTemplate, doxygen):
self["vararg"] = True
paramsStack = paramsStack[1:]
else:
param = CppVariable(paramsStack, None, doxyVarDesc=doxyVarDesc)
param = CppVariable(
paramsStack,
None,
getattr(paramsStack[0], "location", location),
doxyVarDesc=doxyVarDesc,
)
if len(list(param.keys())):
params.append(param)
break
Expand Down Expand Up @@ -1037,7 +1038,7 @@ class CppVariable(_CppVariable):

Vars = []

def __init__(self, nameStack, doxygen, **kwargs):
def __init__(self, nameStack, doxygen, location, **kwargs):
debug_print("trace %s" % nameStack)
if len(nameStack) and nameStack[0] == "extern":
self["extern"] = True
Expand Down Expand Up @@ -1075,7 +1076,7 @@ def __init__(self, nameStack, doxygen, **kwargs):

debug_print("Variable: %s" % nameStack)

self["line_number"] = detect_lineno(nameStack[0])
set_location_info(self, location)
self["function_pointer"] = 0

if len(nameStack) < 2: # +++
Expand Down Expand Up @@ -1217,7 +1218,7 @@ class CppEnum(_CppEnum):
if a value for a given enum value was defined
"""

def __init__(self, nameStack, doxygen):
def __init__(self, nameStack, doxygen, location):
if doxygen:
self["doxygen"] = doxygen
if len(nameStack) == 3 and nameStack[0] == "enum":
Expand All @@ -1229,7 +1230,7 @@ def __init__(self, nameStack, doxygen):
debug_print("Bad enum")
return
valueList = []
self["line_number"] = detect_lineno(nameStack[0])
set_location_info(self, location)
# Figure out what values it has
valueStack = nameStack[nameStack.index("{") + 1 : nameStack.index("}")]
while len(valueStack):
Expand Down Expand Up @@ -1295,15 +1296,14 @@ class CppStruct(dict):

Structs = []

def __init__(self, nameStack):
def __init__(self, nameStack, location):
if len(nameStack) >= 2:
self["type"] = nameStack[1]
else:
self["type"] = None
self["fields"] = []
set_location_info(self, location)
self.Structs.append(self)
global curLine
self["line_number"] = curLine


C99_NONSTANDARD = {
Expand Down Expand Up @@ -1797,7 +1797,7 @@ def finalize_vars(self):
else:
trace_print("-" * 80)
trace_print(var)
raise NotImplemented
raise NotImplementedError

## need full name space for classes in raw type ##
if var["raw_type"].startswith("::"):
Expand Down Expand Up @@ -1990,7 +1990,7 @@ def _evaluate_struct_stack(self):
"""Create a Struct out of the name stack (but not its parts)"""
# print( 'eval struct stack', self.nameStack )
# if self.braceDepth != len(self.nameSpaces): return
struct = CppStruct(self.nameStack)
struct = CppStruct(self.nameStack, self._get_location(self.nameStack))
struct["namespace"] = self.cur_namespace()
self.structs[struct["type"]] = struct
self.structs_order.append(struct)
Expand Down Expand Up @@ -2168,6 +2168,7 @@ def _evaluate_method_stack(self):
info,
self.curTemplate,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
klass = self.classes[info["class"]]
klass["methods"]["public"].append(newMethod)
Expand All @@ -2184,6 +2185,7 @@ def _evaluate_method_stack(self):
info,
self.curTemplate,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
klass = self.classes[self.curClass]
klass["methods"][self.curAccessSpecifier].append(newMethod)
Expand All @@ -2195,7 +2197,12 @@ def _evaluate_method_stack(self):
else: # non class functions
debug_print("FREE FUNCTION")
newMethod = CppMethod(
self.nameStack, None, info, self.curTemplate, self.lex.get_doxygen()
self.nameStack,
None,
info,
self.curTemplate,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
self.functions.append(newMethod)
global parseHistory
Expand Down Expand Up @@ -2318,7 +2325,11 @@ def _evaluate_property_stack(self, clearStack=True, addToVar=None):
)
return

newVar = CppVariable(self.nameStack, self.lex.get_doxygen())
newVar = CppVariable(
self.nameStack,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
newVar["namespace"] = self.current_namespace()
if self.curStruct:
self.curStruct["fields"].append(newVar)
Expand All @@ -2334,7 +2345,11 @@ def _evaluate_property_stack(self, clearStack=True, addToVar=None):
newVar.update(addToVar)
else:
debug_print("Found Global variable")
newVar = CppVariable(self.nameStack, self.lex.get_doxygen())
newVar = CppVariable(
self.nameStack,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
if addToVar:
newVar.update(addToVar)
self.variables.append(newVar)
Expand Down Expand Up @@ -2370,15 +2385,22 @@ def _evaluate_class_stack(self):
"curAccessSpecifier changed/defaulted to %s" % self.curAccessSpecifier
)
if self.nameStack[0] == "union":
newClass = CppUnion(self.nameStack, self.lex.get_doxygen())
newClass = CppUnion(
self.nameStack,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
if newClass["name"] == "union ":
self.anon_union_counter = [self.braceDepth, 2]
else:
self.anon_union_counter = [self.braceDepth, 1]
trace_print("NEW UNION", newClass["name"])
else:
newClass = CppClass(
self.nameStack, self.curTemplate, self.lex.get_doxygen()
self.nameStack,
self.curTemplate,
self.lex.get_doxygen(),
self._get_location(self.nameStack),
)
trace_print("NEW CLASS", newClass["name"])
newClass["declaration_method"] = self.nameStack[0]
Expand Down Expand Up @@ -2674,13 +2696,11 @@ def __init__(self, headerFileName, argType="file", encoding=None, **kwargs):

self.braceDepth = 0

lex = Lexer()
lex = Lexer(self.headerFileName)
lex.input(headerFileStr)
self.lex = lex

global curLine
curLine = 0

tok = None
try:
while True:
tok = lex.token()
Expand All @@ -2691,13 +2711,13 @@ def __init__(self, headerFileName, argType="file", encoding=None, **kwargs):
and self.anon_union_counter[1]
):
self.anon_union_counter[1] -= 1
tok.value = TagStr(tok.value, lineno=tok.lineno)
tok.value = TagStr(tok.value, location=lex.current_location())
# debug_print("TOK: %s"%tok)
if tok.type == "NAME" and tok.value in self.IGNORE_NAMES:
continue
if tok.type != "TEMPLATE_NAME":
self.stack.append(tok.value)
curLine = tok.lineno

if tok.type in ("PRECOMP_MACRO", "PRECOMP_MACRO_CONT"):
debug_print("PRECOMP: %s" % tok)
self._precomp_macro_buf.append(tok.value)
Expand Down Expand Up @@ -2880,12 +2900,23 @@ def __init__(self, headerFileName, argType="file", encoding=None, **kwargs):
self.stack = []
self.nameStack = []

except:
except Exception as e:
if debug:
raise
raise CppParseError(
'Not able to parse %s on line %d evaluating "%s"\nError around: %s'
% (self.headerFileName, tok.lineno, tok.value, " ".join(self.nameStack))
if tok:
filename, lineno = tok.value.location
msg = (
'Not able to parse %s on line %d evaluating "%s"\nError around: %s'
% (filename, lineno, tok.value, " ".join(self.nameStack))
)
else:
msg = "Error parsing %s\nError around: %s" % (
self.headerFileName,
" ".join(self.nameStack),
)

raise_exc(
CppParseError(msg), e,
)

self.finalize()
Expand Down Expand Up @@ -2918,6 +2949,14 @@ def __init__(self, headerFileName, argType="file", encoding=None, **kwargs):
]:
del self.__dict__[key]

def _get_location(self, stack):
if stack:
location = getattr(stack[0], "location", None)
if location is not None:
return location

return self.lex.current_location()

def _evaluate_stack(self, token=None):
"""Evaluates the current name stack"""

Expand Down Expand Up @@ -2988,11 +3027,15 @@ def _evaluate_stack(self, token=None):
# using foo = ns::bar
alias = self.nameStack[1]
ns, stack = _split_namespace(self.nameStack[3:])
atype = CppVariable(stack, self.lex.get_doxygen())
atype = CppVariable(
stack, self.lex.get_doxygen(), self._get_location(stack)
)
else:
# using foo::bar
ns, stack = _split_namespace(self.nameStack[1:])
atype = CppVariable(stack, self.lex.get_doxygen())
atype = CppVariable(
stack, self.lex.get_doxygen(), self._get_location(stack)
)
alias = atype["type"]

atype["namespace"] = ns
Expand Down Expand Up @@ -3094,7 +3137,9 @@ def _evaluate_stack(self, token=None):
def _evaluate_enum_stack(self):
"""Create an Enum out of the name stack"""
debug_print("evaluating enum")
newEnum = CppEnum(self.nameStack, self.lex.get_doxygen())
newEnum = CppEnum(
self.nameStack, self.lex.get_doxygen(), self._get_location(self.nameStack)
)
if len(list(newEnum.keys())):
if len(self.curClass):
newEnum["namespace"] = self.cur_namespace(False)
Expand Down
Loading