1- from typing import Any , Callable , Dict , Set , Tuple , Iterable , Union
1+ from typing import Any , Callable , Dict , Set , Tuple , Iterable , Union , List , Optional
22from .types import FileId
33from .page import Page
44from . import n
55
66
7+ class FileIdStack :
8+ """A stack which tracks file inclusion history, allowing a postprocessor
9+ pass to know at any point both the page where processing started, as well
10+ as what file is currently being processed."""
11+
12+ __slots__ = ("_stack" ,)
13+
14+ def __init__ (self , initial_stack : Optional [List [FileId ]] = None ) -> None :
15+ self ._stack : List [FileId ] = initial_stack if initial_stack is not None else []
16+
17+ def pop (self ) -> None :
18+ self ._stack .pop ()
19+
20+ def append (self , fileid : FileId ) -> None :
21+ self ._stack .append (fileid )
22+
23+ def clear (self ) -> None :
24+ self ._stack .clear ()
25+
26+ @property
27+ def root (self ) -> FileId :
28+ return self ._stack [0 ]
29+
30+ @property
31+ def current (self ) -> FileId :
32+ return self ._stack [- 1 ]
33+
34+
735class EventListeners :
836 """Manage the listener functions associated with an event-based parse operation"""
937
@@ -30,16 +58,16 @@ def get_event_listeners(self, event: str) -> Set[Callable[..., Any]]:
3058 def fire (
3159 self ,
3260 event : str ,
33- filename : FileId ,
61+ fileid : FileIdStack ,
3462 * args : Union [n .Node , Page ],
3563 ** kwargs : Union [n .Node , Page ],
3664 ) -> None :
3765 """Iterate through all universal listeners and all listeners of the specified type and call them"""
3866 for listener in self .get_event_listeners (event ):
39- listener (filename , * args , ** kwargs )
67+ listener (fileid , * args , ** kwargs )
4068
4169 for listener in self ._universal_listeners :
42- listener (filename , * args , ** kwargs )
70+ listener (fileid , * args , ** kwargs )
4371
4472
4573class EventParser (EventListeners ):
@@ -52,6 +80,7 @@ class EventParser(EventListeners):
5280
5381 def __init__ (self ) -> None :
5482 super (EventParser , self ).__init__ ()
83+ self .fileid_stack = FileIdStack ()
5584
5685 def consume (self , d : Iterable [Tuple [FileId , Page ]]) -> None :
5786 """Initializes a parse on the provided key-value map of pages"""
@@ -60,8 +89,14 @@ def consume(self, d: Iterable[Tuple[FileId, Page]]) -> None:
6089 self ._iterate (page .ast , filename )
6190 self ._on_page_exit_event (page , filename )
6291
92+ self .fileid_stack .clear ()
93+
6394 def _iterate (self , d : n .Node , filename : FileId ) -> None :
95+ if isinstance (d , n .Root ):
96+ self .fileid_stack .append (d .fileid )
97+
6498 self ._on_object_enter_event (d , filename )
99+
65100 if isinstance (d , n .Parent ):
66101 if isinstance (d , n .DefinitionListItem ):
67102 for child in d .term :
@@ -73,20 +108,24 @@ def _iterate(self, d: n.Node, filename: FileId) -> None:
73108
74109 for child in d .children :
75110 self ._iterate (child , filename )
111+
76112 self ._on_object_exit_event (d , filename )
77113
114+ if isinstance (d , n .Root ):
115+ self .fileid_stack .pop ()
116+
78117 def _on_page_enter_event (self , page : Page , filename : FileId ) -> None :
79118 """Called when an array is first encountered in tree"""
80- self .fire (self .PAGE_START_EVENT , filename , page = page )
119+ self .fire (self .PAGE_START_EVENT , FileIdStack ([ filename ]) , page = page )
81120
82121 def _on_page_exit_event (self , page : Page , filename : FileId ) -> None :
83122 """Called when an array is first encountered in tree"""
84- self .fire (self .PAGE_END_EVENT , filename , page = page )
123+ self .fire (self .PAGE_END_EVENT , FileIdStack ([ filename ]) , page = page )
85124
86125 def _on_object_enter_event (self , node : n .Node , filename : FileId ) -> None :
87126 """Called when an object is first encountered in tree"""
88- self .fire (self .OBJECT_START_EVENT , filename , node = node )
127+ self .fire (self .OBJECT_START_EVENT , self . fileid_stack , node = node )
89128
90129 def _on_object_exit_event (self , node : n .Node , filename : FileId ) -> None :
91130 """Called when an object is first encountered in tree"""
92- self .fire (self .OBJECT_END_EVENT , filename , node = node )
131+ self .fire (self .OBJECT_END_EVENT , self . fileid_stack , node = node )
0 commit comments