debug variant parsing

This commit is contained in:
jgcodes2020 2024-12-24 09:49:53 -05:00
parent be667a2b9c
commit 96c5760eaf
3 changed files with 52 additions and 3 deletions

View file

@ -28,6 +28,10 @@ from .gobject_object import Object
from .types import TypeName
from .variant import VarContent
import gi
gi.require_version("GLib", "2.0")
from gi.repository import GLib
class Translated(AstNode):
grammar = AnyOf(
@ -373,8 +377,17 @@ class IdentLiteral(AstNode):
return None
class VariantValue(AstNode):
grammar = ["variant", "<", UseQuoted("type"), ">", "(", VarContent, ")"]
grammar = [
"variant",
"<",
UseQuoted("type"),
">",
"(",
Err(VarContent, "Invalid variant content!"),
")",
]
@property
def var_type(self) -> str:
@ -407,6 +420,24 @@ class VariantValue(AstNode):
raise CompileError(f"Cannot convert variant into {expected_type.full_name}")
pass
@validate("type")
def validate_type(self):
if not GLib.VariantType.string_is_valid(self.var_type):
raise CompileError(f"`{self.var_type}` is not a valid variant type")
@validate()
def validate_content(self):
if not GLib.VariantType.string_is_valid(self.var_type):
return
try:
var_ty = GLib.VariantType.new(self.var_type)
var_val = GLib.Variant.parse(var_ty, self.var_value)
except GLib.GError as error:
raise CompileError(f"Variant did not match specified type: {error}")
pass
class Literal(AstNode):
grammar = AnyOf(

View file

@ -38,7 +38,7 @@ class VarContentString(AstNode):
@property
def content(self) -> str:
return self.tokens["value"]
return utils.escape_quote(self.tokens["value"])
class VarContentNumber(AstNode):
@ -80,7 +80,10 @@ class VarContentDict(AstNode):
@property
def content(self) -> str:
inner = ", ".join(child.content for child in self.children)
inner = ", ".join(
f"{key.content}: {value.content}"
for (key, value) in utils.iter_batched(self.children, 2, strict=True)
)
return f"{{{inner}}}"

View file

@ -19,6 +19,7 @@
import typing as T
from dataclasses import dataclass
import itertools
class Colors:
@ -154,3 +155,17 @@ def unescape_quote(string: str) -> str:
i += 1
return result
def iter_batched(iterable, n, *, strict=False):
"""
Replacement for `itertools.batched()` since the testing infrastructure
uses Python 3.9 at the moment. Copied directly off of the Python docs.
"""
# batched('ABCDEFG', 3) → ABC DEF G
if n < 1:
raise ValueError('n must be at least one')
iterator = iter(iterable)
while batch := tuple(itertools.islice(iterator, n)):
if strict and len(batch) != n:
raise ValueError('batched(): incomplete batch')
yield batch