Merge pull request #44 from robotpy/ns-alias
Parse namespace alias and emit it
This commit is contained in:
commit
01c93956b5
@ -35,6 +35,7 @@ from .types import (
|
|||||||
Method,
|
Method,
|
||||||
MoveReference,
|
MoveReference,
|
||||||
NameSpecifier,
|
NameSpecifier,
|
||||||
|
NamespaceAlias,
|
||||||
NamespaceDecl,
|
NamespaceDecl,
|
||||||
Operator,
|
Operator,
|
||||||
PQNameSegment,
|
PQNameSegment,
|
||||||
@ -404,13 +405,26 @@ class CxxParser:
|
|||||||
|
|
||||||
names = []
|
names = []
|
||||||
location = tok.location
|
location = tok.location
|
||||||
|
ns_alias: typing.Union[typing.Literal[False], LexToken] = False
|
||||||
|
|
||||||
tok = self._next_token_must_be("NAME", "{")
|
tok = self._next_token_must_be("NAME", "{")
|
||||||
if tok.type != "{":
|
if tok.type != "{":
|
||||||
|
endtok = "{"
|
||||||
|
# Check for namespace alias here
|
||||||
|
etok = self.lex.token_if("=")
|
||||||
|
if etok:
|
||||||
|
ns_alias = tok
|
||||||
|
endtok = ";"
|
||||||
|
# They can start with ::
|
||||||
|
maybe_tok = self.lex.token_if("DBL_COLON")
|
||||||
|
if maybe_tok:
|
||||||
|
names.append(maybe_tok.value)
|
||||||
|
tok = self._next_token_must_be("NAME")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
names.append(tok.value)
|
names.append(tok.value)
|
||||||
tok = self._next_token_must_be("DBL_COLON", "{")
|
tok = self._next_token_must_be("DBL_COLON", endtok)
|
||||||
if tok.type == "{":
|
if tok.type == endtok:
|
||||||
break
|
break
|
||||||
|
|
||||||
tok = self._next_token_must_be("NAME")
|
tok = self._next_token_must_be("NAME")
|
||||||
@ -418,7 +432,10 @@ class CxxParser:
|
|||||||
if inline and len(names) > 1:
|
if inline and len(names) > 1:
|
||||||
raise CxxParseError("a nested namespace definition cannot be inline")
|
raise CxxParseError("a nested namespace definition cannot be inline")
|
||||||
|
|
||||||
# TODO: namespace_alias_definition
|
if ns_alias:
|
||||||
|
alias = NamespaceAlias(ns_alias.value, names)
|
||||||
|
self.visitor.on_namespace_alias(self.state, alias)
|
||||||
|
return
|
||||||
|
|
||||||
ns = NamespaceDecl(names, inline, doxygen)
|
ns = NamespaceDecl(names, inline, doxygen)
|
||||||
state = self._push_state(NamespaceBlockState, ns)
|
state = self._push_state(NamespaceBlockState, ns)
|
||||||
|
@ -39,6 +39,7 @@ from .types import (
|
|||||||
FriendDecl,
|
FriendDecl,
|
||||||
Function,
|
Function,
|
||||||
Method,
|
Method,
|
||||||
|
NamespaceAlias,
|
||||||
TemplateInst,
|
TemplateInst,
|
||||||
Typedef,
|
Typedef,
|
||||||
UsingAlias,
|
UsingAlias,
|
||||||
@ -110,6 +111,7 @@ class NamespaceScope:
|
|||||||
using: typing.List[UsingDecl] = field(default_factory=list)
|
using: typing.List[UsingDecl] = field(default_factory=list)
|
||||||
using_ns: typing.List["UsingNamespace"] = field(default_factory=list)
|
using_ns: typing.List["UsingNamespace"] = field(default_factory=list)
|
||||||
using_alias: typing.List[UsingAlias] = field(default_factory=list)
|
using_alias: typing.List[UsingAlias] = field(default_factory=list)
|
||||||
|
ns_alias: typing.List[NamespaceAlias] = field(default_factory=list)
|
||||||
|
|
||||||
#: Explicit template instantiations
|
#: Explicit template instantiations
|
||||||
template_insts: typing.List[TemplateInst] = field(default_factory=list)
|
template_insts: typing.List[TemplateInst] = field(default_factory=list)
|
||||||
@ -261,6 +263,10 @@ class SimpleCxxVisitor:
|
|||||||
self.block = self.block_stack.pop()
|
self.block = self.block_stack.pop()
|
||||||
self.namespace = self.ns_stack.pop()
|
self.namespace = self.ns_stack.pop()
|
||||||
|
|
||||||
|
def on_namespace_alias(self, state: State, alias: NamespaceAlias) -> None:
|
||||||
|
assert isinstance(self.block, NamespaceScope)
|
||||||
|
self.block.ns_alias.append(alias)
|
||||||
|
|
||||||
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
||||||
self.block.forward_decls.append(fdecl)
|
self.block.forward_decls.append(fdecl)
|
||||||
|
|
||||||
|
@ -38,6 +38,26 @@ class Value:
|
|||||||
tokens: typing.List[Token]
|
tokens: typing.List[Token]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class NamespaceAlias:
|
||||||
|
"""
|
||||||
|
A namespace alias
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
namespace ANS = my::ns;
|
||||||
|
~~~ ~~~~~~
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias: str
|
||||||
|
|
||||||
|
#: These are the names (split by ::) for the namespace that this alias
|
||||||
|
#: refers to, but does not include any parent namespace names. It may
|
||||||
|
#: include a leading "::", but does not include a following :: string.
|
||||||
|
names: typing.List[str]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class NamespaceDecl:
|
class NamespaceDecl:
|
||||||
"""
|
"""
|
||||||
|
@ -14,6 +14,7 @@ from .types import (
|
|||||||
FriendDecl,
|
FriendDecl,
|
||||||
Function,
|
Function,
|
||||||
Method,
|
Method,
|
||||||
|
NamespaceAlias,
|
||||||
TemplateInst,
|
TemplateInst,
|
||||||
Typedef,
|
Typedef,
|
||||||
UsingAlias,
|
UsingAlias,
|
||||||
@ -94,6 +95,11 @@ class CxxVisitor(Protocol):
|
|||||||
Called at the end of a ``namespace`` block
|
Called at the end of a ``namespace`` block
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def on_namespace_alias(self, state: State, alias: NamespaceAlias) -> None:
|
||||||
|
"""
|
||||||
|
Called when a ``namespace`` alias is encountered
|
||||||
|
"""
|
||||||
|
|
||||||
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
||||||
"""
|
"""
|
||||||
Called when a forward declaration is encountered
|
Called when a forward declaration is encountered
|
||||||
|
@ -4,6 +4,7 @@ from cxxheaderparser.errors import CxxParseError
|
|||||||
from cxxheaderparser.types import (
|
from cxxheaderparser.types import (
|
||||||
ForwardDecl,
|
ForwardDecl,
|
||||||
FundamentalSpecifier,
|
FundamentalSpecifier,
|
||||||
|
NamespaceAlias,
|
||||||
NameSpecifier,
|
NameSpecifier,
|
||||||
PQName,
|
PQName,
|
||||||
Token,
|
Token,
|
||||||
@ -168,3 +169,29 @@ def test_invalid_inline_namespace() -> None:
|
|||||||
err = "<str>:1: parse error evaluating 'inline': a nested namespace definition cannot be inline"
|
err = "<str>:1: parse error evaluating 'inline': a nested namespace definition cannot be inline"
|
||||||
with pytest.raises(CxxParseError, match=re.escape(err)):
|
with pytest.raises(CxxParseError, match=re.escape(err)):
|
||||||
parse_string(content, cleandoc=True)
|
parse_string(content, cleandoc=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ns_alias() -> None:
|
||||||
|
content = """
|
||||||
|
namespace ANS = my::ns;
|
||||||
|
"""
|
||||||
|
data = parse_string(content, cleandoc=True)
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
ns_alias=[NamespaceAlias(alias="ANS", names=["my", "ns"])]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ns_alias_global() -> None:
|
||||||
|
content = """
|
||||||
|
namespace ANS = ::my::ns;
|
||||||
|
"""
|
||||||
|
data = parse_string(content, cleandoc=True)
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
ns_alias=[NamespaceAlias(alias="ANS", names=["::", "my", "ns"])]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user