10
10
from .options import ParserOptions
11
11
from .parserstate import (
12
12
ClassBlockState ,
13
- EmptyBlockState ,
14
13
ExternBlockState ,
15
14
NamespaceBlockState ,
15
+ NonClassBlockState ,
16
16
ParsedTypeModifiers ,
17
17
State ,
18
18
)
62
62
LexTokenList = typing .List [LexToken ]
63
63
T = typing .TypeVar ("T" )
64
64
65
- ST = typing .TypeVar ("ST" , bound = State )
66
65
PT = typing .TypeVar ("PT" , Parameter , TemplateNonTypeParam )
67
66
68
67
@@ -90,7 +89,9 @@ def __init__(
90
89
global_ns = NamespaceDecl ([], False )
91
90
self .current_namespace = global_ns
92
91
93
- self .state : State = NamespaceBlockState (None , global_ns )
92
+ self .state : State = NamespaceBlockState (
93
+ None , self .lex .current_location (), global_ns
94
+ )
94
95
self .anon_id = 0
95
96
96
97
self .verbose = True if self .options .verbose else False
@@ -111,13 +112,9 @@ def debug_print(fmt: str, *args: typing.Any) -> None:
111
112
# State management
112
113
#
113
114
114
- def _push_state (self , cls : typing .Type [ST ], * args ) -> ST :
115
- state = cls (self .state , * args )
115
+ def _setup_state (self , state : State ):
116
116
state ._prior_visitor = self .visitor
117
- if isinstance (state , NamespaceBlockState ):
118
- self .current_namespace = state .namespace
119
117
self .state = state
120
- return state
121
118
122
119
def _pop_state (self ) -> State :
123
120
prev_state = self .state
@@ -447,24 +444,37 @@ def _parse_namespace(
447
444
if inline and len (names ) > 1 :
448
445
raise CxxParseError ("a nested namespace definition cannot be inline" )
449
446
447
+ state = self .state
448
+ if not isinstance (state , (NamespaceBlockState , ExternBlockState )):
449
+ raise CxxParseError ("namespace cannot be defined in a class" )
450
+
450
451
if ns_alias :
451
452
alias = NamespaceAlias (ns_alias .value , names )
452
- self .visitor .on_namespace_alias (self . state , alias )
453
+ self .visitor .on_namespace_alias (state , alias )
453
454
return
454
455
455
456
ns = NamespaceDecl (names , inline , doxygen )
456
- state = self ._push_state (NamespaceBlockState , ns )
457
- state .location = location
457
+
458
+ state = NamespaceBlockState (state , location , ns )
459
+ self ._setup_state (state )
460
+ self .current_namespace = state .namespace
461
+
458
462
if self .visitor .on_namespace_start (state ) is False :
459
463
self .visitor = null_visitor
460
464
461
465
def _parse_extern (self , tok : LexToken , doxygen : typing .Optional [str ]) -> None :
462
466
etok = self .lex .token_if ("STRING_LITERAL" , "template" )
463
467
if etok :
468
+ # classes cannot contain extern blocks/templates
469
+ state = self .state
470
+ if isinstance (state , ClassBlockState ):
471
+ raise self ._parse_error (tok )
472
+
464
473
if etok .type == "STRING_LITERAL" :
465
474
if self .lex .token_if ("{" ):
466
- state = self ._push_state (ExternBlockState , etok .value )
467
- state .location = tok .location
475
+ state = ExternBlockState (state , tok .location , etok .value )
476
+ self ._setup_state (state )
477
+
468
478
if self .visitor .on_extern_block_start (state ) is False :
469
479
self .visitor = null_visitor
470
480
return
@@ -510,9 +520,7 @@ def _consume_static_assert(
510
520
def _on_empty_block_start (
511
521
self , tok : LexToken , doxygen : typing .Optional [str ]
512
522
) -> None :
513
- state = self ._push_state (EmptyBlockState )
514
- if self .visitor .on_empty_block_start (state ) is False :
515
- self .visitor = null_visitor
523
+ raise self ._parse_error (tok )
516
524
517
525
def _on_block_end (self , tok : LexToken , doxygen : typing .Optional [str ]) -> None :
518
526
old_state = self ._pop_state ()
@@ -822,7 +830,7 @@ def _consume_attribute_specifier_seq(
822
830
# Using directive/declaration/typealias
823
831
#
824
832
825
- def _parse_using_directive (self ) -> None :
833
+ def _parse_using_directive (self , state : NonClassBlockState ) -> None :
826
834
"""
827
835
using_directive: [attribute_specifier_seq] "using" "namespace" ["::"] [nested_name_specifier] IDENTIFIER ";"
828
836
"""
@@ -841,7 +849,7 @@ def _parse_using_directive(self) -> None:
841
849
if not names :
842
850
raise self ._parse_error (None , "NAME" )
843
851
844
- self .visitor .on_using_namespace (self . state , names )
852
+ self .visitor .on_using_namespace (state , names )
845
853
846
854
def _parse_using_declaration (self , tok : LexToken ) -> None :
847
855
"""
@@ -893,10 +901,11 @@ def _parse_using(
893
901
raise CxxParseError (
894
902
"unexpected using-directive when parsing alias-declaration" , tok
895
903
)
896
- if isinstance (self .state , ClassBlockState ):
904
+ state = self .state
905
+ if not isinstance (state , (NamespaceBlockState , ExternBlockState )):
897
906
raise self ._parse_error (tok )
898
907
899
- self ._parse_using_directive ()
908
+ self ._parse_using_directive (state )
900
909
elif tok .type in ("DBL_COLON" , "typename" ) or not self .lex .token_if ("=" ):
901
910
if template :
902
911
raise CxxParseError (
@@ -1143,10 +1152,11 @@ def _parse_class_decl(
1143
1152
clsdecl = ClassDecl (
1144
1153
typename , bases , template , explicit , final , doxygen , self ._current_access
1145
1154
)
1146
- state = self . _push_state (
1147
- ClassBlockState , clsdecl , default_access , typedef , mods
1155
+ state : ClassBlockState = ClassBlockState (
1156
+ self . state , location , clsdecl , default_access , typedef , mods
1148
1157
)
1149
- state .location = location
1158
+ self ._setup_state (state )
1159
+
1150
1160
if self .visitor .on_class_start (state ) is False :
1151
1161
self .visitor = null_visitor
1152
1162
@@ -1853,6 +1863,7 @@ def _parse_function(
1853
1863
1854
1864
self .visitor .on_class_method (state , method )
1855
1865
else :
1866
+ assert isinstance (state , (ExternBlockState , NamespaceBlockState ))
1856
1867
if not method .has_body :
1857
1868
raise self ._parse_error (None , expected = "Method body" )
1858
1869
self .visitor .on_method_impl (state , method )
@@ -1912,6 +1923,9 @@ def _parse_function(
1912
1923
self .visitor .on_typedef (state , typedef )
1913
1924
return False
1914
1925
else :
1926
+ if not isinstance (state , (ExternBlockState , NamespaceBlockState )):
1927
+ raise CxxParseError ("internal error" )
1928
+
1915
1929
self .visitor .on_function (state , fn )
1916
1930
return fn .has_body or fn .has_trailing_return
1917
1931
0 commit comments