| #!/usr/bin/python3 -i |
| # |
| # Copyright 2013-2021 The Khronos Group Inc. |
| # |
| # SPDX-License-Identifier: Apache-2.0 |
| """Utilities for working with attributes of the XML registry.""" |
| |
| import re |
| |
| _PARAM_REF_NAME_RE = re.compile( |
| r"(?P<name>[\w]+)(?P<brackets>\[\])?(?P<delim>\.|::|->)?") |
| |
| |
| def _split_param_ref(val): |
| return [name for name, _, _ in _PARAM_REF_NAME_RE.findall(val)] |
| |
| |
| def _human_readable_deref(val, make_param_name=None): |
| """Turn the "name[].member[]" notation into plain English.""" |
| parts = [] |
| matches = _PARAM_REF_NAME_RE.findall(val) |
| for name, brackets, delim in reversed(matches): |
| if make_param_name: |
| name = make_param_name(name) |
| if delim: |
| parts.append('member of') |
| if brackets: |
| parts.append('each element of') |
| parts.append('the') |
| parts.append(name) |
| parts.append('parameter') |
| return ' '.join(parts) |
| |
| |
| class LengthEntry: |
| """An entry in a (comma-separated) len attribute""" |
| NULL_TERMINATED_STRING = 'null-terminated' |
| MATH_STRING = 'latexmath:' |
| |
| def __init__(self, val): |
| self.full_reference = val |
| self.other_param_name = None |
| self.null_terminated = False |
| self.number = None |
| self.math = None |
| self.param_ref_parts = None |
| if val == LengthEntry.NULL_TERMINATED_STRING: |
| self.null_terminated = True |
| return |
| |
| if val.startswith(LengthEntry.MATH_STRING): |
| self.math = val.replace(LengthEntry.MATH_STRING, '')[1:-1] |
| return |
| |
| if val.isdigit(): |
| self.number = int(val) |
| return |
| |
| # Must be another param name. |
| self.param_ref_parts = _split_param_ref(val) |
| self.other_param_name = self.param_ref_parts[0] |
| |
| def __str__(self): |
| return self.full_reference |
| |
| def get_human_readable(self, make_param_name=None): |
| assert(self.other_param_name) |
| return _human_readable_deref(self.full_reference, make_param_name=make_param_name) |
| |
| def __repr__(self): |
| "Formats an object for repr(), debugger display, etc." |
| return 'spec_tools.attributes.LengthEntry("{}")'.format(self.full_reference) |
| |
| @staticmethod |
| def parse_len_from_param(param): |
| """Get a list of LengthEntry.""" |
| len_str = param.get('len') |
| if len_str is None: |
| return None |
| return [LengthEntry(elt) for elt in len_str.split(',')] |
| |
| |
| class ExternSyncEntry: |
| """An entry in a (comma-separated) externsync attribute""" |
| |
| TRUE_STRING = 'true' |
| TRUE_WITH_CHILDREN_STRING = 'true_with_children' |
| |
| def __init__(self, val): |
| self.full_reference = val |
| self.entirely_extern_sync = (val in (ExternSyncEntry.TRUE_STRING, ExternSyncEntry.TRUE_WITH_CHILDREN_STRING)) |
| self.children_extern_sync = (val == ExternSyncEntry.TRUE_WITH_CHILDREN_STRING) |
| if self.entirely_extern_sync: |
| return |
| |
| self.param_ref_parts = _split_param_ref(val) |
| self.member = self.param_ref_parts[0] |
| |
| def get_human_readable(self, make_param_name=None): |
| assert(not self.entirely_extern_sync) |
| return _human_readable_deref(self.full_reference, make_param_name=make_param_name) |
| |
| @staticmethod |
| def parse_externsync_from_param(param): |
| """Get a list of ExternSyncEntry.""" |
| sync_str = param.get('externsync') |
| if sync_str is None: |
| return None |
| return [ExternSyncEntry(elt) for elt in sync_str.split(',')] |
| |
| def __repr__(self): |
| "Formats an object for repr(), debugger display, etc." |
| return 'spec_tools.attributes.ExternSyncEntry("{}")'.format(self.full_reference) |
| |