Skip to content
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

Skip sections #65

Merged
merged 2 commits into from
Sep 10, 2023
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
2 changes: 1 addition & 1 deletion cxxheaderparser/gentest.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def gentest(
popt = ""

options = ParserOptions(verbose=verbose)
if options:
if pcpp:
options.preprocessor = make_pcpp_preprocessor()
maybe_options = "options = ParserOptions(preprocessor=make_pcpp_preprocessor())"
popt = ", options=options"
Expand Down
16 changes: 11 additions & 5 deletions cxxheaderparser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
Value,
Variable,
)
from .visitor import CxxVisitor
from .visitor import CxxVisitor, null_visitor

LexTokenList = typing.List[LexToken]
T = typing.TypeVar("T")
Expand Down Expand Up @@ -114,6 +114,7 @@ def debug_print(fmt: str, *args: typing.Any) -> None:

def _push_state(self, cls: typing.Type[ST], *args) -> ST:
state = cls(self.state, *args)
state._prior_visitor = self.visitor
if isinstance(state, NamespaceBlockState):
self.current_namespace = state.namespace
self.state = state
Expand All @@ -122,6 +123,7 @@ def _push_state(self, cls: typing.Type[ST], *args) -> ST:
def _pop_state(self) -> State:
prev_state = self.state
prev_state._finish(self.visitor)
self.visitor = prev_state._prior_visitor
state = prev_state.parent
if state is None:
raise CxxParseError("INTERNAL ERROR: unbalanced state")
Expand Down Expand Up @@ -454,7 +456,8 @@ def _parse_namespace(
ns = NamespaceDecl(names, inline, doxygen)
state = self._push_state(NamespaceBlockState, ns)
state.location = location
self.visitor.on_namespace_start(state)
if self.visitor.on_namespace_start(state) is False:
self.visitor = null_visitor

def _parse_extern(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
etok = self.lex.token_if("STRING_LITERAL", "template")
Expand All @@ -463,7 +466,8 @@ def _parse_extern(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
if self.lex.token_if("{"):
state = self._push_state(ExternBlockState, etok.value)
state.location = tok.location
self.visitor.on_extern_block_start(state)
if self.visitor.on_extern_block_start(state) is False:
self.visitor = null_visitor
return

# an extern variable/function with specific linkage
Expand Down Expand Up @@ -508,7 +512,8 @@ def _on_empty_block_start(
self, tok: LexToken, doxygen: typing.Optional[str]
) -> None:
state = self._push_state(EmptyBlockState)
self.visitor.on_empty_block_start(state)
if self.visitor.on_empty_block_start(state) is False:
self.visitor = null_visitor

def _on_block_end(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
old_state = self._pop_state()
Expand Down Expand Up @@ -1143,7 +1148,8 @@ def _parse_class_decl(
ClassBlockState, clsdecl, default_access, typedef, mods
)
state.location = location
self.visitor.on_class_start(state)
if self.visitor.on_class_start(state) is False:
self.visitor = null_visitor

def _finish_class_decl(self, state: ClassBlockState) -> None:
self._finish_class_or_enum(
Expand Down
3 changes: 3 additions & 0 deletions cxxheaderparser/parserstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class State(typing.Generic[T, PT]):
#: Approximate location that the parsed element was found at
location: Location

#: internal detail used by parser
_prior_visitor: "CxxVisitor"

def __init__(self, parent: typing.Optional["State[PT, typing.Any]"]) -> None:
self.parent = parent

Expand Down
12 changes: 8 additions & 4 deletions cxxheaderparser/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,22 +209,24 @@ def on_pragma(self, state: SState, content: Value) -> None:
def on_include(self, state: SState, filename: str) -> None:
self.data.includes.append(Include(filename))

def on_empty_block_start(self, state: SEmptyBlockState) -> None:
def on_empty_block_start(self, state: SEmptyBlockState) -> typing.Optional[bool]:
# this matters for some scope/resolving purposes, but you're
# probably going to want to use clang if you care about that
# level of detail
state.user_data = state.parent.user_data
return None

def on_empty_block_end(self, state: SEmptyBlockState) -> None:
pass

def on_extern_block_start(self, state: SExternBlockState) -> None:
def on_extern_block_start(self, state: SExternBlockState) -> typing.Optional[bool]:
state.user_data = state.parent.user_data
return None

def on_extern_block_end(self, state: SExternBlockState) -> None:
pass

def on_namespace_start(self, state: SNamespaceBlockState) -> None:
def on_namespace_start(self, state: SNamespaceBlockState) -> typing.Optional[bool]:
parent_ns = state.parent.user_data

ns = None
Expand All @@ -247,6 +249,7 @@ def on_namespace_start(self, state: SNamespaceBlockState) -> None:
ns.doxygen = state.namespace.doxygen

state.user_data = ns
return None

def on_namespace_end(self, state: SNamespaceBlockState) -> None:
pass
Expand Down Expand Up @@ -299,11 +302,12 @@ def on_enum(self, state: SState, enum: EnumDecl) -> None:
# Class/union/struct
#

def on_class_start(self, state: SClassBlockState) -> None:
def on_class_start(self, state: SClassBlockState) -> typing.Optional[bool]:
parent = state.parent.user_data
block = ClassScope(state.class_decl)
parent.classes.append(block)
state.user_data = block
return None

def on_class_field(self, state: SClassBlockState, f: Field) -> None:
state.user_data.fields.append(f)
Expand Down
103 changes: 99 additions & 4 deletions cxxheaderparser/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def on_include(self, state: State, filename: str) -> None:
Called once for each ``#include`` directive encountered
"""

def on_empty_block_start(self, state: EmptyBlockState) -> None:
def on_empty_block_start(self, state: EmptyBlockState) -> typing.Optional[bool]:
"""
Called when a ``{`` is encountered that isn't associated with or
consumed by other declarations.
Expand All @@ -62,31 +62,39 @@ def on_empty_block_start(self, state: EmptyBlockState) -> None:
{
// stuff
}

If this function returns False, the visitor will not be called for any
items inside this block (including on_empty_block_end)
"""

def on_empty_block_end(self, state: EmptyBlockState) -> None:
"""
Called when an empty block ends
"""

def on_extern_block_start(self, state: ExternBlockState) -> None:
def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
"""
.. code-block:: c++

extern "C" {

}

If this function returns False, the visitor will not be called for any
items inside this block (including on_extern_block_end)
"""

def on_extern_block_end(self, state: ExternBlockState) -> None:
"""
Called when an extern block ends
"""

def on_namespace_start(self, state: NamespaceBlockState) -> None:
def on_namespace_start(self, state: NamespaceBlockState) -> typing.Optional[bool]:
"""
Called when a ``namespace`` directive is encountered

If this function returns False, the visitor will not be called for any
items inside this namespace (including on_namespace_end)
"""

def on_namespace_end(self, state: NamespaceBlockState) -> None:
Expand Down Expand Up @@ -186,7 +194,7 @@ def on_enum(self, state: State, enum: EnumDecl) -> None:
# Class/union/struct
#

def on_class_start(self, state: ClassBlockState) -> None:
def on_class_start(self, state: ClassBlockState) -> typing.Optional[bool]:
"""
Called when a class/struct/union is encountered

Expand All @@ -199,6 +207,9 @@ def on_class_start(self, state: ClassBlockState) -> None:
This is called first, followed by on_typedef for each typedef instance
encountered. The compound type object is passed as the type to the
typedef.

If this function returns False, the visitor will not be called for any
items inside this class (including on_class_end)
"""

def on_class_field(self, state: ClassBlockState, f: Field) -> None:
Expand Down Expand Up @@ -231,3 +242,87 @@ def on_class_end(self, state: ClassBlockState) -> None:
Then ``on_class_start``, .. ``on_class_end`` are emitted, along with
``on_variable`` for each instance declared.
"""


class NullVisitor:
"""
This visitor does nothing
"""

def on_parse_start(self, state: NamespaceBlockState) -> None:
return None

def on_pragma(self, state: State, content: Value) -> None:
return None

def on_include(self, state: State, filename: str) -> None:
return None

def on_empty_block_start(self, state: EmptyBlockState) -> typing.Optional[bool]:
return None

def on_empty_block_end(self, state: EmptyBlockState) -> None:
return None

def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
return None

def on_extern_block_end(self, state: ExternBlockState) -> None:
return None

def on_namespace_start(self, state: NamespaceBlockState) -> typing.Optional[bool]:
return None

def on_namespace_end(self, state: NamespaceBlockState) -> None:
return None

def on_namespace_alias(self, state: State, alias: NamespaceAlias) -> None:
return None

def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
return None

def on_template_inst(self, state: State, inst: TemplateInst) -> None:
return None

def on_variable(self, state: State, v: Variable) -> None:
return None

def on_function(self, state: State, fn: Function) -> None:
return None

def on_method_impl(self, state: State, method: Method) -> None:
return None

def on_typedef(self, state: State, typedef: Typedef) -> None:
return None

def on_using_namespace(self, state: State, namespace: typing.List[str]) -> None:
return None

def on_using_alias(self, state: State, using: UsingAlias) -> None:
return None

def on_using_declaration(self, state: State, using: UsingDecl) -> None:
return None

def on_enum(self, state: State, enum: EnumDecl) -> None:
return None

def on_class_start(self, state: ClassBlockState) -> typing.Optional[bool]:
return None

def on_class_field(self, state: ClassBlockState, f: Field) -> None:
return None

def on_class_friend(self, state: ClassBlockState, friend: FriendDecl) -> None:
return None

def on_class_method(self, state: ClassBlockState, method: Method) -> None:
return None

def on_class_end(self, state: ClassBlockState) -> None:
return None


null_visitor = NullVisitor()
Loading