import re import os import json from dataclasses import dataclass class Jsonify: def encode(self, value=None): if not value: value = self.__dict__ return value @dataclass class Flag(Jsonify): bit: int description: str @dataclass class Record(Jsonify): fourcc: str name: str flags: list[Flag] re_flags = re.compile(".*?(\d+?),.*?'(.*)'") def find_records(data, re_record, re_first): found_records = re_record.findall(data) seen = set() records = [] for record in found_records: s = record.split('\n') [first] = re_first.findall(s[0]) assert len(first) == 2, "Could not parse first line of record:\n{}".format(record) flags = [] for line in s[2:-1]: [f] = re_flags.findall(line) assert len(f) == 2, "Could not parse flag definition: {}".format(line) desc = f[1].replace("''", "'").replace("', '", "") flags += [Flag(int(f[0]), desc)] r = Record(first[0], first[1], flags) if r.fourcc not in seen: records += [r] seen.add(r.fourcc) return records def find_wbRecords(data): re_wbRecord = re.compile("wbRecord\(.*?\n.*?wbFlagsList\(\[\n(?:.*?\n)*?.*?\]") re_wbRecord_first = re.compile("wbRecord\((\w{4}).*?'(.+?)'.*?") return find_records(data, re_wbRecord, re_wbRecord_first) def find_stat(data): re_stat = re.compile("wbRecord\(STAT,.*?\n.*?\n(?:.*?\n)+?.*?]") lines = re_stat.findall(data)[0].split('\n') re_stat_first = re.compile("STAT, '(.*?)'") [name] = re_stat_first.findall(lines[0]) re_stat_flag = re.compile("'(.*?)'") flags = [] for i, line in enumerate(lines[2:-1]): [l] = re_stat_flag.findall(line) if l: flags += [Flag(i, l)] return Record("STAT", name, flags) def find_concrete_wbRefRecords(data): re_wbRefRecord = re.compile("wbRefRecord\(\w{4},.*?\n.*?wbFlagsList\(\[.*?\n(?:.*?\n)+?.*?\]") re_wbRefRecord_first = re.compile("wbRefRecord\((\w{4}).*?'(.+?)'.*?") return find_records(data, re_wbRefRecord, re_wbRefRecord_first) def find_ReferenceRecords(data): re_ReferenceRecordDef = re.compile("wbRefRecord\(aSignature, .*?\n(?:.*?\n)+?.*?]") re_ReferenceRecordDef_first = re.compile("wbRefRecord\((\w+?), (\w+?),") [d] = find_records(data, re_ReferenceRecordDef, re_ReferenceRecordDef_first) re_ReferenceRecord = re.compile("ReferenceRecord\((\w{4}), '(.*?)'\);") rr = re_ReferenceRecord.findall(data) records = [Record(r[0], r[1], d.flags) for r in rr] return records def find_wbRefRecords(data): records = find_concrete_wbRefRecords(data) records = find_ReferenceRecords(data) return records fdir = os.path.dirname(__file__) with open(os.path.join(fdir, "wbDefinitionsTES5.pas"), "r") as f: inp = f.read() records = find_wbRecords(inp) + [find_stat(inp)] + find_wbRefRecords(inp) records.sort(key = lambda x: x.fourcc) print(len(records)) class Encoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Jsonify): return obj.encode() else: return json.JSONEncoder.default(self, obj) with open(os.path.join(fdir, "flags.json"), "w") as f: json.dump(records, f, cls=Encoder, indent=4)