core: allow debug tracing of parse for visualisations
This commit is contained in:
parent
ea61dbf1e3
commit
8bf9b77505
|
@ -11,16 +11,40 @@ from .util import seeking
|
|||
from .io import Segment, Stream, Pos
|
||||
|
||||
|
||||
class Params:
|
||||
__slots__ = ('segments', 'default_segment', 'user')
|
||||
T = TypeVar('T')
|
||||
|
||||
def __init__(self, segments: Sequence[Segment] = None, user: Mapping[str, Any] = {}):
|
||||
class DebugTreeNode(Generic[T]):
|
||||
__slots__ = ('type', 'pos', 'end', 'value', 'children')
|
||||
|
||||
def __init__(self, type: 'Type[T]', pos: Pos = None) -> None:
|
||||
self.type = type
|
||||
self.pos = pos
|
||||
self.value = None
|
||||
self.end = None
|
||||
self.children = []
|
||||
|
||||
def finalize(self, value: T, end: Pos) -> None:
|
||||
self.value = value
|
||||
self.end = end
|
||||
|
||||
def add_child(self, ident, node: 'DebugTreeNode') -> None:
|
||||
self.children.append((ident, node))
|
||||
|
||||
|
||||
class Params:
|
||||
__slots__ = ('segments', 'default_segment', 'user', 'debug_path', 'debug_root')
|
||||
|
||||
def __init__(self, segments: Sequence[Segment] = None, user: Mapping[str, Any] = {}, debug: bool = False):
|
||||
default = segments[0] if segments else Segment('default')
|
||||
self.segments = {s.name: s for s in (segments or [default, Segment('refs', [default])])}
|
||||
self.default_segment = default
|
||||
self.user = SimpleNamespace(**user)
|
||||
self.debug_path: O[List[DebugTreeNode]] = [] if debug else None
|
||||
self.debug_root: O[DebugTreeNode] = None
|
||||
|
||||
def reset(self):
|
||||
self.debug_root = None
|
||||
self.debug_path = [] if self.debug_path is not None else None
|
||||
for s in self.segments.values():
|
||||
s.reset()
|
||||
|
||||
|
@ -45,10 +69,8 @@ def format_path(path: Iterable[PathElement]) -> str:
|
|||
return s
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
PT = TypeVar('PT')
|
||||
|
||||
|
||||
class PossibleDynamic(Generic[T]):
|
||||
pass
|
||||
|
||||
|
@ -62,6 +84,8 @@ class Context:
|
|||
self.path: List[PathEntry] = []
|
||||
self.segment_path: List[Segment] = []
|
||||
|
||||
self.params.reset()
|
||||
|
||||
def copy(self) -> 'Context':
|
||||
c = self.__class__(root=self.root, value=self.value, params=self.params)
|
||||
c.path = self.path.copy()
|
||||
|
@ -144,7 +168,21 @@ class Context:
|
|||
|
||||
|
||||
def parse(self, type: 'Type[PT]', stream: Stream) -> PT:
|
||||
return type.parse(self, stream)
|
||||
if self.params.debug_path is not None:
|
||||
node = DebugTreeNode(type, stream.root.tell())
|
||||
if self.params.debug_path:
|
||||
self.params.debug_path[-1].add_child(self.path[-1][0], node)
|
||||
else:
|
||||
self.params.debug_root = node
|
||||
self.params.debug_path.append(node)
|
||||
value = None
|
||||
try:
|
||||
value = type.parse(self, stream)
|
||||
return value
|
||||
finally:
|
||||
if self.params.debug_path is not None:
|
||||
node.finalize(value, stream.root.tell())
|
||||
self.params.debug_path.pop()
|
||||
|
||||
def dump(self, type: 'Type[PT]', stream: Stream, value: PT) -> None:
|
||||
return type.dump(self, stream, value)
|
||||
|
|
Loading…
Reference in New Issue