Skip to content

Commit b8faf88

Browse files
authored
Merge pull request #150 from robotpy/non-ptr-fn-arg
Add support for non-pointer function arguments
2 parents 61f4cec + 96d04e5 commit b8faf88

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

cxxheaderparser/parser.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,6 +1971,14 @@ def _parse_parameter(
19711971
if tok:
19721972
param_name = tok.value
19731973

1974+
# Function parameter declarations can use function declarator syntax,
1975+
# e.g. ``bool predicate(const T&)``. In parameter lists, function types
1976+
# are adjusted to pointers to functions, matching the explicit
1977+
# ``bool (*predicate)(const T&)`` spelling.
1978+
if param_name and self.lex.token_if("("):
1979+
fn_params, vararg, _ = self._parse_parameters(False, False)
1980+
dtype = Pointer(FunctionType(dtype, fn_params, vararg))
1981+
19741982
# optional array parameter
19751983
tok = self.lex.token_if("[")
19761984
if tok:

tests/test_fn.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,58 @@
3333
)
3434

3535

36+
def test_fn_parameter_named_function_declarator() -> None:
37+
content = """
38+
template <typename T> void RemoveIf(bool predicate(const T& key));
39+
"""
40+
data = parse_string(content, cleandoc=True)
41+
42+
assert data == ParsedData(
43+
namespace=NamespaceScope(
44+
functions=[
45+
Function(
46+
return_type=Type(
47+
typename=PQName(segments=[FundamentalSpecifier(name="void")])
48+
),
49+
name=PQName(segments=[NameSpecifier(name="RemoveIf")]),
50+
parameters=[
51+
Parameter(
52+
type=Pointer(
53+
ptr_to=FunctionType(
54+
return_type=Type(
55+
typename=PQName(
56+
segments=[FundamentalSpecifier(name="bool")]
57+
)
58+
),
59+
parameters=[
60+
Parameter(
61+
type=Reference(
62+
ref_to=Type(
63+
typename=PQName(
64+
segments=[
65+
NameSpecifier(name="T")
66+
]
67+
),
68+
const=True,
69+
)
70+
),
71+
name="key",
72+
)
73+
],
74+
)
75+
),
76+
name="predicate",
77+
)
78+
],
79+
template=TemplateDecl(
80+
params=[TemplateTypeParam(typekey="typename", name="T")]
81+
),
82+
)
83+
]
84+
)
85+
)
86+
87+
3688
def test_fn_returns_class() -> None:
3789
content = """
3890
class X *fn1();

0 commit comments

Comments
 (0)