99import re
1010from dataclasses import dataclass
1111from functools import reduce , wraps
12- from typing import Any , Callable , FrozenSet , Generic , Optional , TypeVar , Union
12+ from typing import Any , Callable , FrozenSet , Generator , Generic , Optional , TypeVar , Union
1313
1414
1515from .version import __version__ # noqa: F401
@@ -359,11 +359,25 @@ def __lshift__(self: Parser[OUT1], other: Parser) -> Parser[OUT1]:
359359 return self .skip (other )
360360
361361
362- # combinator syntax
363- def generate (fn ):
362+ # TODO:
363+ # I think @generate is unfixable. It's not surprising, because
364+ # we are doing something genuninely unusual with generator functions.
365+
366+ # The return value of a `@generate` parser is now OK.
367+
368+ # But we have no type checking within a user's @generate function.
369+
370+ # The big issue is that each `val = yield parser` inside a @generate parser has
371+ # a different type, and we'd like those to be typed checked. But the
372+ # `Generator[...]` expects a homogeneous stream of yield and send types,
373+ # whereas we have pairs of yield/send types which need to match within the
374+ # pair, but each pair can be completely different from the next in the stream
375+
376+
377+ def generate (fn : Callable [[], Generator [Parser [Any ], Any , OUT ]]) -> Parser [OUT ]:
364378 @Parser
365379 @wraps (fn )
366- def generated (stream , index ) :
380+ def generated (stream : str , index : int ) -> Result [ OUT ] :
367381 # start up the generator
368382 iterator = fn ()
369383
@@ -379,9 +393,6 @@ def generated(stream, index):
379393 index = result .index
380394 except StopIteration as stop :
381395 returnVal = stop .value
382- if isinstance (returnVal , Parser ):
383- return returnVal (stream , index ).aggregate (result )
384-
385396 return Result .success (index , returnVal ).aggregate (result )
386397
387398 return generated
0 commit comments