2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 16:32:13 +00:00
Files
parser/misc/generate_case_fold_tests.py
2024-01-04 02:40:33 -06:00

114 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2024 T. Zachary Laine
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
# Get the latest version of the data file at:
# https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt
import itertools
f = open('CaseFolding.txt')
lines = f.readlines()
lines = filter(
lambda x: False if (x.startswith('#') or x == '\n' or ' T;' in x or ' S;' in x) else True,
lines)
lines = list(map(lambda x: x.split(';')[:-1], lines))
f_line_indices = list(filter(lambda i: ' F;' in lines[i], range(len(lines))))
# Remove all C; lines that come before a F; line that applies to the same code
# point.
for f_idx in reversed(f_line_indices):
prev = f_idx - 1
if 0 <= prev:
if lines[f_idx][0] == lines[prev][0]:
lines = lines[:prev] + lines[prev + 1:]
max_mapping_len = 1
for line in lines:
mappings = line[2].strip().split(' ')
max_mapping_len = max(len(mappings), max_mapping_len)
def print_cps():
print('// Initial code points from CaseFolding.txt')
print('char32_t const cps[] = {')
str_ = ''
idx = 0
max_per_line = 8
for cp in map(lambda x: '0x' + x[0], lines):
str_ += cp + ', '
idx += 1
if (idx % max_per_line) == 0:
print(' ' + str_)
str_ = ''
if idx % max_per_line:
print(' ' + str_)
print('};\n')
print(f'char32_t const max_test_cp = 0x{lines[-1][0]} + 100;\n')
array_t = f'std::array<uint32_t, {max_mapping_len} + 1>'
def print_test(line):
num_mapping_cps = len(line[2].strip().split(' '))
mapping = ', '.join(map(lambda x: '0x' + x, line[2].strip().split(' ')))
trailing = ', 0' * (max_mapping_len + 1 - num_mapping_cps)
zeros = ', 0' * (max_mapping_len)
print(f''' {{
{array_t} const expected = {{ {mapping}{trailing} }};
{array_t} result = {{ 0{zeros} }};
boost::parser::detail::case_fold(0x{line[0]}, result.begin());
EXPECT_EQ(result, expected);
}}''')
def print_tests():
idx = 0
max_per_TEST = 50
print(f'TEST(case_folding, hits_{int(idx / max_per_TEST)}) {{')
for line in lines:
idx += 1
if (idx % max_per_TEST) == 0:
print(f'''}}
TEST(case_folding, test_{int(idx / max_per_TEST)}) {{''')
print_test(line)
print('}\n')
print('''// Copyright (c) 2024 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Warning: This header is auto-generated (see misc/generate_case_fold_tests.py).
#include <boost/parser/parser.hpp>
#include <gtest/gtest.h>
''')
print_cps()
print_tests()
print(f'''TEST(case_folding, misses) {{
char32_t next_cp = 0;
for (char32_t const * it = cps; it != std::end(cps); ++it) {{
for (char32_t cp = next_cp; cp < *it; ++cp) {{
{array_t} const expected = {{ cp, 0 }};
{array_t} result = {{ 0 }};
auto const first = result.data();
auto const last = boost::parser::detail::case_fold(cp, first);
EXPECT_TRUE(std::equal(first, last, expected.begin()));
EXPECT_EQ(result, expected);
}}
next_cp = *it + 1;
}}
}}''')