utf 8 — Как определить диапазоны Юникода по свойствам / идентификаторам в C ++ для PEGTL

С пег (https://github.com/taocpp/PEGTL), которая является библиотекой на основе заголовка C ++ 11 только для PEG библиотеки, я могу определить диапазоны для символов Unicode, например:

  • utf8 :: Диапазон<0x0, 0x10FF> // Все символы UTF8
  • utf8 :: Диапазон<0x41, 0x5A, 0x61, 0x7A> // UTF8 0x41-0x5A [A-Z] и 0x61-0x7A [a-z]

Теперь с UTF8 есть эта классификация свойств (https://en.wikipedia.org/wiki/Unicode_character_property#General_Category) с помощью которого я делаю облако, например, [: Lu:] или [: ID_Start:] и получаю набор / диапазон символов.

Теперь, так как я работаю с шаблонами c ++, мне нужны эти диапазоны во время компиляции. На мой взгляд, у меня есть следующие варианты:

  1. Узнайте, что у PEGTL есть возможность поиска [: ID_Start:] или [: Lu:]
  2. Найти библиотеку препроцессора С ++, которая позволяет такие запросы во время компиляции
  3. Получить приложение / онлайн-сервис, где я могу выполнять эти запросы и получать диапазоны (как показано выше), которые затем я могу вставить в свой код.

Это также представляет порядок решений, которые я предпочитаю.

1

Решение

PEGTL использует правила, чтобы соответствовать символам, а не возвращать наборы символов. Если вы хотите сопоставить символы с определенными свойствами символов Юникода, вы можете создать пользовательское правило и реализовать его с помощью некоторой библиотеки Unicode, например, ICU. Он предоставляет методы для проверки кодовых точек для различных свойств, см. эта ссылка.

Вот полный пример программы:

#include <iomanip>
#include <iostream>

#include <unicode/uchar.h>

#include <tao/pegtl.hpp>

using namespace tao::TAO_PEGTL_NAMESPACE;  // NOLINT

namespace test
{
template< UProperty P >
struct icu_has_binary_property
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;

template< typename Input >
static bool match( Input& in )
{
// this assumes the input is UTF8, adapt as necessary
const auto r = internal::peek_utf8::peek( in );
// if a code point is available, the size is >0
if( r.size != 0 ) {
// check the property
if( u_hasBinaryProperty( r.data, P ) ) {
// if it matches, consume the character
in.bump( r.size );
return true;
}
}
return false;
}
};

using icu_lower = icu_has_binary_property< UCHAR_LOWERCASE >;
using icu_upper = icu_has_binary_property< UCHAR_UPPERCASE >;

// clang-format off
struct grammar : seq< icu_upper, plus< icu_lower >, eof > {};
// clang-format on
}

int main( int argc, char** argv )
{
for( int i = 1; i < argc; ++i ) {
argv_input<> in( argv, i );
std::cout << argv[ i ] << " matches: " << std::boolalpha << parse< test::grammar >( in ) << std::endl;
}
}

Теперь я могу скомпилировать и запустить его:

$ g++ -std=c++11 -pedantic -Wall -Wextra -Werror -O3 -Ipegtl/include icu.cpp -licuuc -licudata -o icu
$ ./icu Ďánîel DánÎel
Ďánîel matches: true
DánÎel matches: false
$

РЕДАКТИРОВАТЬ: Я добавил Правила ICU (их много) в Пегтл. Поскольку они требуют ICU, внешней зависимости, я поместил их в contrib-раздел.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]