Files
RustPython/scripts/generate_sre_constants.py
Terry Tianlin Luan 8977c39b60 Updated the re library + test (#6648)
* Updated re library + test

* Copied over generate_sre_constants from cpython/Tools

* Customized `generate_sre_constants.py` + ran to update `constants.rs`

* Clarified `dump_enum` docstring in `generate_sre_constants.py`
2026-01-05 13:55:07 +09:00

140 lines
3.9 KiB
Python

#! /usr/bin/env python3
# This script generates crates/sre_engine/src/constants.rs from Lib/re/_constants.py.
SCRIPT_NAME = "scripts/generate_sre_constants.py"
def update_file(file, content):
try:
with open(file, "r") as fobj:
if fobj.read() == content:
return False
except (OSError, ValueError):
pass
with open(file, "w") as fobj:
fobj.write(content)
return True
sre_constants_header = f"""\
/*
* Secret Labs' Regular Expression Engine
*
* regular expression matching engine
*
* Auto-generated by {SCRIPT_NAME} from
* Lib/re/_constants.py.
*
* Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved.
*
* See the sre.c file for information on usage and redistribution.
*/
"""
def dump_enum(d, enum_name, derives, strip_prefix=""):
"""Generate Rust enum definitions from a Python dictionary.
Args:
d (list): The list containing the enum variants.
enum_name (str): The name of the enum to generate.
derives (str): The derive attributes to include.
strip_prefix (str, optional): A prefix to strip from the variant names. Defaults to "".
Returns:
list: A list of strings representing the enum definition.
"""
items = sorted(d)
print(f"items is {items}")
content = [f"{derives}\n"]
content.append("#[repr(u32)]\n")
content.append("#[allow(non_camel_case_types, clippy::upper_case_acronyms)]\n")
content.append(f"pub enum {enum_name} {{\n")
for i, item in enumerate(items):
name = str(item).removeprefix(strip_prefix)
content.append(f" {name} = {i},\n")
content.append("}\n\n")
return content
def dump_bitflags(d, prefix, derives, struct_name, int_t):
"""Generate Rust bitflags definitions from a Python dictionary.
Args:
d (dict): The dictionary containing the bitflag variants.
prefix (str): The prefix to strip from the variant names.
derives (str): The derive attributes to include.
struct_name (str): The name of the struct to generate.
int_t (str): The integer type to use for the bitflags.
Returns:
list: A list of strings representing the bitflags definition.
"""
items = [(value, name) for name, value in d.items() if name.startswith(prefix)]
content = ["bitflags! {\n"]
content.append(f"{derives}\n") if derives else None
content.append(f" pub struct {struct_name}: {int_t} {{\n")
for value, name in sorted(items):
name = str(name).removeprefix(prefix)
content.append(f" const {name} = {value};\n")
content.append(" }\n")
content.append("}\n\n")
return content
def main(
infile="Lib/re/_constants.py",
outfile_constants="crates/sre_engine/src/constants.rs",
):
ns = {}
with open(infile) as fp:
code = fp.read()
exec(code, ns)
content = [sre_constants_header]
content.append("use bitflags::bitflags;\n\n")
content.append(f"pub const SRE_MAGIC: usize = {ns['MAGIC']};\n")
content.extend(
dump_enum(
ns["OPCODES"],
"SreOpcode",
"#[derive(num_enum::TryFromPrimitive, Debug, PartialEq, Eq)]",
)
)
content.extend(
dump_enum(
ns["ATCODES"],
"SreAtCode",
"#[derive(num_enum::TryFromPrimitive, Debug, PartialEq, Eq)]",
"AT_",
)
)
content.extend(
dump_enum(
ns["CHCODES"],
"SreCatCode",
"#[derive(num_enum::TryFromPrimitive, Debug)]",
"CATEGORY_",
)
)
content.extend(
dump_bitflags(
ns,
"SRE_FLAG_",
"#[derive(Debug, PartialEq, Eq, Clone, Copy)]",
"SreFlag",
"u16",
)
)
content.extend(dump_bitflags(ns, "SRE_INFO_", "", "SreInfo", "u32"))
update_file(outfile_constants, "".join(content))
if __name__ == "__main__":
import sys
main(*sys.argv[1:])