如何通过c ++中的属性/标识符为PEGTL定义unicode范围
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过c ++中的属性/标识符为PEGTL定义unicode范围相关的知识,希望对你有一定的参考价值。
使用PEGTL(https://github.com/taocpp/PEGTL),这是一个基于模板的C ++ 11仅头文件的PEG库,我可以定义unicode字符的范围,如下所示:
- utf8 :: range <0x0,0x10FF> //所有UTF8字符
- utf8 :: range <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 ++模板,所以我需要在编译时使用这些范围。在我看来,我有以下选择:
- 发现PEGTL本身有可能查找[:ID_Start:]或[:Lu:]
- 找到一个c ++预处理器库,它允许在编译时进行此类查询
- 获取应用程序/在线服务,我可以在其中执行这些查询并获取范围(如上所示),然后我可以将其粘贴到我的代码中。
这也代表了我喜欢的解决方案的顺序。
答案
PEGTL使用规则来匹配字符,而不是返回字符集。如果您想要将字符与某些Unicode字符属性匹配,您可以创建一个custom rule并在某些Unicode库的帮助下实现它,例如: ICU。它提供了测试各种属性的代码点的方法,请参阅this link。
这是一个完整的示例程序:
#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 rules(很多)添加到PEGTL中。因为他们需要ICU,一个外部依赖,我把它们放在contrib
部分。
以上是关于如何通过c ++中的属性/标识符为PEGTL定义unicode范围的主要内容,如果未能解决你的问题,请参考以下文章