From b611b9189aa03490521aab2ca0c659bed3ac2cef Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Fri, 26 Nov 2021 00:28:54 -0500 Subject: [PATCH] Allow using 'final' as a name in some contexts - Strictly speaking, this fix will allow 'final' in some contexts where it isn't actually allowed. However, cxxheaderparser "will not reject all invalid C++ headers!" so this is ok - Fixes #14 --- cxxheaderparser/parser.py | 13 ++++++-- tests/test_misc.py | 68 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/cxxheaderparser/parser.py b/cxxheaderparser/parser.py index 6f4d833..ee40c7b 100644 --- a/cxxheaderparser/parser.py +++ b/cxxheaderparser/parser.py @@ -1250,7 +1250,16 @@ class CxxParser: return parts _pqname_start_tokens = ( - {"auto", "decltype", "NAME", "operator", "template", "typename", "DBL_COLON"} + { + "auto", + "decltype", + "NAME", + "operator", + "template", + "typename", + "DBL_COLON", + "final", + } | _name_compound_start | _fundamentals ) @@ -1463,7 +1472,7 @@ class CxxParser: self.lex.return_tokens(toks[1:-1]) # optional name - tok = self.lex.token_if("NAME") + tok = self.lex.token_if("NAME", "final") if tok: param_name = tok.value diff --git a/tests/test_misc.py b/tests/test_misc.py index dfbc143..a9dd0d2 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,15 +1,20 @@ # Note: testcases generated via `python -m cxxheaderparser.gentest` from cxxheaderparser.types import ( + BaseClass, + ClassDecl, Function, FundamentalSpecifier, NameSpecifier, PQName, Parameter, + Token, Type, + Value, Variable, ) from cxxheaderparser.simple import ( + ClassScope, Include, NamespaceScope, Pragma, @@ -168,3 +173,66 @@ def test_comment_eof(): assert data == ParsedData( namespace=NamespaceScope(namespaces={"a": NamespaceScope(name="a")}) ) + + +def test_final(): + content = """ + // ok here + int fn(const int final); + + // ok here + int final = 2; + + // but it's a keyword here + struct B final : A {}; + """ + data = parse_string(content, cleandoc=True) + + assert data == ParsedData( + namespace=NamespaceScope( + classes=[ + ClassScope( + class_decl=ClassDecl( + typename=PQName( + segments=[NameSpecifier(name="B")], classkey="struct" + ), + bases=[ + BaseClass( + access="public", + typename=PQName(segments=[NameSpecifier(name="A")]), + ) + ], + final=True, + ) + ) + ], + functions=[ + Function( + return_type=Type( + typename=PQName(segments=[FundamentalSpecifier(name="int")]) + ), + name=PQName(segments=[NameSpecifier(name="fn")]), + parameters=[ + Parameter( + type=Type( + typename=PQName( + segments=[FundamentalSpecifier(name="int")] + ), + const=True, + ), + name="final", + ) + ], + ) + ], + variables=[ + Variable( + name=PQName(segments=[NameSpecifier(name="final")]), + type=Type( + typename=PQName(segments=[FundamentalSpecifier(name="int")]) + ), + value=Value(tokens=[Token(value="2")]), + ) + ], + ) + )