#!/usr/bin/env python3 """Generate the C++ punctuation contract from policy.json.""" import argparse import json from pathlib import Path ROOT = Path(__file__).resolve().parent SPEC = json.loads((ROOT / "policy.json").read_text(encoding="utf-8")) simple = SPEC["simple"] alternating = SPEC["alternating"] nested = SPEC["nested"] inputs = [entry["input"] for entry in simple + alternating] + [nested["openingInput"], nested["closingInput"]] if (SPEC["contractVersion"] != 1 or any(len(value) != 1 or not 32 <= ord(value) < 127 for value in inputs) or len(set(inputs)) != len(inputs)): raise SystemExit("Invalid punctuation contract") def char_literal(value): return "'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'" lines = [ "// Generated by contracts/punctuation/generate.py; edit policy.json instead.", "#pragma once", "#include ", "#include ", "", "namespace metasequoia::punctuation_contract", "{", f"inline constexpr int version = {SPEC['contractVersion']};", "struct Mapping", "{", " char input;", " const char *output;", "};", "struct AlternatingMapping", "{", " char input;", " const char *opening;", " const char *closing;", "};", f"inline constexpr std::array simple = {{{{", ] lines += [f" {{{char_literal(entry['input'])}, {json.dumps(entry['output'], ensure_ascii=False)}}}," for entry in simple] lines += [ "}};", f"inline constexpr std::array alternating = {{{{", ] lines += [ f" {{{char_literal(entry['input'])}, {json.dumps(entry['opening'], ensure_ascii=False)}, {json.dumps(entry['closing'], ensure_ascii=False)}}}," for entry in alternating ] lines += [ "}};", f"inline constexpr char nested_opening_input = {char_literal(nested['openingInput'])};", f"inline constexpr char nested_closing_input = {char_literal(nested['closingInput'])};", f"inline constexpr char nested_opening[] = {json.dumps(nested['opening'], ensure_ascii=False)};", f"inline constexpr char nested_opening_inner[] = {json.dumps(nested['nestedOpening'], ensure_ascii=False)};", f"inline constexpr char nested_closing[] = {json.dumps(nested['closing'], ensure_ascii=False)};", f"inline constexpr char nested_closing_inner[] = {json.dumps(nested['nestedClosing'], ensure_ascii=False)};", "constexpr bool is_supported(char input)", "{", " for (const auto &mapping : simple)", " if (mapping.input == input) return true;", " for (const auto &mapping : alternating)", " if (mapping.input == input) return true;", " return input == nested_opening_input || input == nested_closing_input;", "}", "constexpr const char *simple_output(char input)", "{", " for (const auto &mapping : simple)", " if (mapping.input == input) return mapping.output;", " return nullptr;", "}", "constexpr const AlternatingMapping *alternating_mapping(char input)", "{", " for (const auto &mapping : alternating)", " if (mapping.input == input) return &mapping;", " return nullptr;", "}", "} // namespace metasequoia::punctuation_contract", "", ] expected = "\n".join(lines) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--check", action="store_true") args = parser.parse_args() target = ROOT / "policy.h" if args.check: if not target.exists() or target.read_text(encoding="utf-8") != expected: raise SystemExit("Punctuation contract header is stale; run contracts/punctuation/generate.py") else: target.write_text(expected, encoding="utf-8")