add completion detection to DirtyJson parser

Track parsing depth via _pop_stack() helper. Exposes a 'completed' flag that signals when the root JSON structure is fully closed, allowing stream consumers to break early instead of waiting for irrelevant tokens.

Alessandro committed Apr 3, 2026 at 15:45 UTC ec80702b80949e3460add407b1f8e9f6643d40c2
1 file changed +16 -6
helpers/dirty_json.py
+16 -6
@@ -25,6 +25,14 @@ class DirtyJson:
25 self.current_char = None
26 self.result = None
27 self.stack = []
28 + self.completed = False
29 + self._parsing_started = False
30 +
31 + def _pop_stack(self):
32 + """Pop from the parsing stack and mark completed if root structure is closed."""
33 + self.stack.pop()
34 + if self._parsing_started and not self.stack:
35 + self.completed = True
36
37 @staticmethod
38 def parse_string(json_string):
@@ -153,6 +161,7 @@ class DirtyJson:
161 obj = {}
162 self._advance() # Skip opening brace
163 self.stack.append(obj)
164 + self._parsing_started = True
165 self._parse_object_content()
166 return obj
167
@@ -164,10 +173,10 @@ class DirtyJson:
173 self._advance(2)
174 else:
175 self._advance()
167 - self.stack.pop()
176 + self._pop_stack()
177 return
178 if self.current_char is None:
170 - self.stack.pop()
179 + self._pop_stack()
180 return # End of input reached while parsing object
181
182 key = self._parse_key()
@@ -190,7 +199,7 @@ class DirtyJson:
199 continue
200 elif self.current_char != "}":
201 if self.current_char is None:
193 - self.stack.pop()
202 + self._pop_stack()
203 return # End of input reached after value
204 continue
205
@@ -216,6 +225,7 @@ class DirtyJson:
225 arr = []
226 self._advance() # Skip opening bracket
227 self.stack.append(arr)
228 + self._parsing_started = True
229 self._parse_array_content()
230 return arr
231
@@ -224,7 +234,7 @@ class DirtyJson:
234 self._skip_whitespace()
235 if self.current_char == "]":
236 self._advance()
227 - self.stack.pop()
237 + self._pop_stack()
238 return
239 value = self._parse_value()
240 self.stack[-1].append(value)
@@ -236,10 +246,10 @@ class DirtyJson:
246 if self.current_char is None or self.current_char == "]":
247 if self.current_char == "]":
248 self._advance()
239 - self.stack.pop()
249 + self._pop_stack()
250 return
251 elif self.current_char != "]":
242 - self.stack.pop()
252 + self._pop_stack()
253 return
254
255 def _parse_string(self):