core: fully keep track of parse path
This commit is contained in:
parent
e71cacb8f7
commit
ea61dbf1e3
|
@ -25,13 +25,15 @@ class Params:
|
|||
s.reset()
|
||||
|
||||
|
||||
PathElement = U[str, int]
|
||||
PathElement = U[None, str, int]
|
||||
PathEntry = Tuple[PathElement, 'Type']
|
||||
|
||||
def format_path(path: Iterable[PathElement]) -> str:
|
||||
s = ''
|
||||
first = True
|
||||
for p in path:
|
||||
if p is None:
|
||||
continue
|
||||
sep = '.'
|
||||
if isinstance(p, int):
|
||||
p = '[' + str(p) + ']'
|
||||
|
|
|
@ -13,19 +13,29 @@ class Wrapper(G[T], Type[T]):
|
|||
self.child = child
|
||||
|
||||
def parse(self, context: Context, stream: Stream) -> T:
|
||||
return context.parse(to_type(self.child), stream)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
return context.parse(child, stream)
|
||||
|
||||
def dump(self, context: Context, stream: Stream, value: O[T]) -> None:
|
||||
context.dump(to_type(self.child), stream, value)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
context.dump(child, stream, value)
|
||||
|
||||
def sizeof(self, context: Context, value: O[T]) -> O[int]:
|
||||
return context.sizeof(to_type(self.child), value)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
return context.sizeof(child, value)
|
||||
|
||||
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[int]:
|
||||
return context.offsetof(to_type(self.child), path, value)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
return context.offsetof(child, path, value)
|
||||
|
||||
def default(self, context: Context) -> T:
|
||||
return context.default(to_type(self.child))
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
return context.default(child)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(to_type(self.child))
|
||||
|
@ -64,27 +74,37 @@ class Generic(G[T], Type[T], BaseExpr[T]):
|
|||
def parse(self, context: Context, stream: Stream) -> T:
|
||||
if not self.stack:
|
||||
raise Error(context, 'unresolved generic')
|
||||
return context.parse(to_type(self.stack[-1]), stream)
|
||||
child = to_type(self.stack[-1])
|
||||
with context.enter(None, child):
|
||||
return context.parse(child, stream)
|
||||
|
||||
def dump(self, context: Context, stream: Stream, value: T) -> None:
|
||||
if not self.stack:
|
||||
raise Error(context, 'unresolved generic')
|
||||
context.dump(to_type(self.stack[-1]), stream, value)
|
||||
child = to_type(self.stack[-1])
|
||||
with context.enter(None, child):
|
||||
context.dump(child, stream, value)
|
||||
|
||||
def sizeof(self, context: Context, value: O[T]) -> O[int]:
|
||||
if not self.stack:
|
||||
return None
|
||||
return context.sizeof(to_type(self.stack[-1]), value)
|
||||
child = to_type(self.stack[-1])
|
||||
with context.enter(None, child):
|
||||
return context.sizeof(child, value)
|
||||
|
||||
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[int]:
|
||||
if not self.stack:
|
||||
return None
|
||||
return context.offsetof(to_type(self.stack[-1]), path, value)
|
||||
child = to_type(self.stack[-1])
|
||||
with context.enter(None, child):
|
||||
return context.offsetof(child, path, value)
|
||||
|
||||
def default(self, context: Context) -> T:
|
||||
if not self.stack:
|
||||
raise Error(context, 'unresolved generic')
|
||||
return context.default(to_type(self.stack[-1]))
|
||||
child = to_type(self.stack[-1])
|
||||
with context.enter(None, child):
|
||||
return context.default(child)
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.stack:
|
||||
|
|
|
@ -30,22 +30,32 @@ class Switch(G[T, V], Type[T]):
|
|||
return to_type(options[selector])
|
||||
|
||||
def parse(self, context: Context, stream: Stream) -> T:
|
||||
return context.parse(self.get_value(context), stream)
|
||||
child = self.get_value(context)
|
||||
with context.enter(None, child):
|
||||
return context.parse(child, stream)
|
||||
|
||||
def dump(self, context: Context, stream: Stream, value: T) -> None:
|
||||
context.dump(self.get_value(context), stream, value)
|
||||
child = self.get_value(context)
|
||||
with context.enter(None, child):
|
||||
context.dump(child, stream, value)
|
||||
|
||||
def sizeof(self, context: Context, value: O[T]) -> O[Pos]:
|
||||
return context.sizeof(self.get_value(context, peek=True), value)
|
||||
child = self.get_value(context, peek=True)
|
||||
with context.enter(None, child):
|
||||
return context.sizeof(child, value)
|
||||
|
||||
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[Pos]:
|
||||
return context.offsetof(self.get_value(context, peek=True), path, value)
|
||||
child = self.get_value(context, peek=True)
|
||||
with context.enter(None, child):
|
||||
return context.offsetof(child, path, value)
|
||||
|
||||
def default(self, context: Context) -> T:
|
||||
return context.default(self.get_value(context, peek=True))
|
||||
child = self.get_value(context, peek=True)
|
||||
with context.enter(None, child):
|
||||
return context.default(ChildProcessError)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'{format_value(self.options)}[{self.selector}]'
|
||||
return f'{format_value(self.options, str)}[{self.selector}]'
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'{__name__}.Switch({self.options!r}, selector={self.selector!r}, default={self.default_key!r}, fallback={self.default_val!r})'
|
||||
|
@ -58,33 +68,43 @@ class If(G[T,V], Type[U[T, V]]):
|
|||
|
||||
def parse(self, context: Context, stream: Stream) -> U[T, V]:
|
||||
if context.get(self.cond):
|
||||
return context.parse(to_type(self.true), stream)
|
||||
child = to_type(self.true)
|
||||
else:
|
||||
return context.parse(to_type(self.false), stream)
|
||||
child = to_type(self.false)
|
||||
with context.enter(None, child):
|
||||
return context.parse(child, stream)
|
||||
|
||||
def dump(self, context: Context, stream: Stream, value: U[T, V]) -> None:
|
||||
if context.get(self.cond):
|
||||
context.dump(to_type(self.true), stream, value)
|
||||
child = to_type(self.true)
|
||||
else:
|
||||
context.dump(to_type(self.false), stream, value)
|
||||
child = to_type(self.false)
|
||||
with context.enter(None, child):
|
||||
return context.dump(child, stream, value)
|
||||
|
||||
def sizeof(self, context: Context, value: O[U[T, V]]) -> O[Pos]:
|
||||
if context.peek(self.cond):
|
||||
return context.sizeof(to_type(self.true), value)
|
||||
child = to_type(self.true)
|
||||
else:
|
||||
return context.sizeof(to_type(self.false), value)
|
||||
child = to_type(self.false)
|
||||
with context.enter(None, child):
|
||||
return context.sizeof(child, value)
|
||||
|
||||
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[U[T, V]]) -> O[Pos]:
|
||||
if context.peek(self.cond):
|
||||
return context.offsetof(to_type(self.true), path, value)
|
||||
child = to_type(self.true)
|
||||
else:
|
||||
return context.offsetof(to_type(self.false), path, value)
|
||||
child = to_type(self.false)
|
||||
with context.enter(None, child):
|
||||
return context.offsetof(child, path, value)
|
||||
|
||||
def default(self, context: Context) -> U[T, V]:
|
||||
if context.peek(self.cond):
|
||||
return context.default(to_type(self.true))
|
||||
child = to_type(self.true)
|
||||
else:
|
||||
return context.default(to_type(self.false))
|
||||
child = to_type(self.false)
|
||||
with context.enter(None, child):
|
||||
return context.default(self.child)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'({self.cond} ? {self.true} : {self.false})'
|
||||
|
|
|
@ -29,25 +29,35 @@ class Transform(G[T, V], Type[V]):
|
|||
self.on_repr = repr or str
|
||||
|
||||
def parse(self, context: Context, stream: Stream) -> V:
|
||||
value = context.parse(to_type(self.child), stream)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
value = context.parse(child, stream)
|
||||
return self.on_parse(value, context) if self.context else self.on_parse(value)
|
||||
|
||||
def dump(self, context: Context, stream: Stream, value: V) -> None:
|
||||
value = self.on_dump(value, context) if self.context else self.on_dump(value)
|
||||
context.dump(to_type(self.child), stream, value)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
context.dump(child, stream, value)
|
||||
|
||||
def sizeof(self, context: Context, value: O[V]) -> O[int]:
|
||||
if value is not None:
|
||||
value = self.on_dump(value, context) if self.context else self.on_dump(value)
|
||||
return context.sizeof(to_type(self.child), value)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
return context.sizeof(child, value)
|
||||
|
||||
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[V]) -> O[int]:
|
||||
if value is not None:
|
||||
value = self.on_dump(value, context) if self.context else self.on_dump(value)
|
||||
return context.offsetof(to_type(self.child), path, value)
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
return context.offsetof(child, path, value)
|
||||
|
||||
def default(self, context: Context) -> V:
|
||||
value = context.default(to_type(self.child))
|
||||
child = to_type(self.child)
|
||||
with context.enter(None, child):
|
||||
value = context.default(child)
|
||||
return self.on_parse(value, context) if self.context else self.on_parse(value)
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
|
Loading…
Reference in New Issue