From 4ea8f44569a009b013638263f3a4d845adbe5e21 Mon Sep 17 00:00:00 2001 From: Lila Date: Sun, 22 Sep 2024 17:32:06 +0100 Subject: [PATCH] improve and fix main parser --- fast64_internal/sm64/animation/classes.py | 39 ++++++++++----------- fast64_internal/sm64/animation/importing.py | 27 ++++++++++++-- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/fast64_internal/sm64/animation/classes.py b/fast64_internal/sm64/animation/classes.py index 530581b1e..a20f25ab5 100644 --- a/fast64_internal/sm64/animation/classes.py +++ b/fast64_internal/sm64/animation/classes.py @@ -25,7 +25,7 @@ class CArrayDeclaration: name: str = "" path: os.PathLike = "" file_name: str = "" - values: list[str] = dataclasses.field(default_factory=str) + values: list[str] | dict[str, str] = dataclasses.field(default_factory=str) @dataclasses.dataclass @@ -408,26 +408,25 @@ def read_c( header.file_name = header_decl.file_name # Place the values into a dictionary, handles designated initialization - var_defs = [ - "flags", - "animYTransDivisor", - "startFrame", - "loopStart", - "loopEnd", - "unusedBoneCount", - "values", - "index", - "length", - ] - designated = {} - for i, value in enumerate(header_decl.values): - var_value_split: list[str] = value.split("=") - value = var_value_split[-1].strip() - if len(var_value_split) == 2: - var = var_value_split[0].replace(".", "", 1).strip() + if isinstance(header_decl.values, list): + designated = {} + for value, var in zip( + header_decl.values, + [ + "flags", + "animYTransDivisor", + "startFrame", + "loopStart", + "loopEnd", + "unusedBoneCount", + "values", + "index", + "length", + ], + ): designated[var] = value - else: - designated[var_defs[i]] = value + else: + designated = header_decl.values # Read from the dict header.flags = SM64_AnimFlags.evaluate(designated["flags"]) diff --git a/fast64_internal/sm64/animation/importing.py b/fast64_internal/sm64/animation/importing.py index 40912fe6d..32557ad72 100644 --- a/fast64_internal/sm64/animation/importing.py +++ b/fast64_internal/sm64/animation/importing.py @@ -472,16 +472,37 @@ def import_tables( DECL_PATTERN = re.compile( - r"(static\s+const\s+struct\s+Animation|static\s+const\s+u16|static\s+const\s+s16)\s+(\w+)\s*?(?:\[.*?\])?\s*?=\s*?\{(.*?)\};", + r"(static\s+const\s+struct\s+Animation|static\s+const\s+u16|static\s+const\s+s16)\s+" + r"(\w+)\s*?(?:\[.*?\])?\s*?=\s*?\{(.*?)\};", re.DOTALL, ) -VALUE_SPLIT_PATTERN = re.compile(r"\s*([^,\s]+)\s*(?:,|$)") +VALUE_SPLIT_PATTERN = re.compile(r"\s*(?:(?:\.(?P\w+)|\[\s*(?P.*?)\s*\])\s*=\s*)?(?P.+?)(?:,|\Z)") def find_decls(c_data: str, path: Path, decl_list: dict[str, list[CArrayDeclaration]]): matches = DECL_PATTERN.findall(c_data) for decl_type, name, value_text in matches: - values = VALUE_SPLIT_PATTERN.findall(value_text) + values = [] + for match in VALUE_SPLIT_PATTERN.finditer(value_text): + var, designator, val = match.group("var"), match.group("designator"), match.group("val") + assert val is not None + if designator is not None: + if isinstance(values, dict): + raise PluginError("Invalid mix of designated initializers") + designator = math_eval(designator, object()) + first_val = values[0] if values else "0" + values.extend([first_val] * (len(values) - designator)) + values[designator] = val + elif var is not None: + if not values: + values = {} + elif isinstance(values, list): + raise PluginError("Mix of designated and positional variable assignment") + values[var] = val + else: + if isinstance(values, dict): + raise PluginError("Mix of designated and positional variable assignment") + values.append(val) decl_list[decl_type].append(CArrayDeclaration(name, path, path.name, values))