Flex(词法分析器)支持unicode

时间:2012-03-08 01:21:33

标签: unicode flex-lexer

我想知道最新版本的flex是否支持unicode?

如果是这样,如何使用模式匹配中文字符?

更多: Use regular expression to match ANY Chinese character in utf-8 encoding

3 个答案:

答案 0 :(得分:18)

目前,flex仅生成8位扫描仪,基本上限制您使用UTF-8。所以如果你有一个模式:

肖晗   { printf ("xiaohan\n"); }

它将按预期工作,因为模式和输入中的字节序列将是相同的。更难的是角色类。如果你想匹配角色肖或晗,你不能写:

[肖晗]   { printf ("xiaohan/2\n"); }

因为这将匹配六个字节0xe8,0x82,0x96,0xe6,0x99和0x97中的每一个,这实际上意味着如果提供肖晗作为输入,则模式将匹配六次。因此,在这种简单的情况下,您必须将模式重写为(肖|晗)

对于范围,Hans Aberg编写了一个tool in Haskell,将这些转换为8位模式:

Unicode> urToRegU8 0 0xFFFF
[\0-\x7F]|[\xC2-\xDF][\x80-\xBF]|(\xE0[\xA0-\xBF]|[\xE1-\xEF][\x80-\xBF])[\x80-\xBF]
Unicode> urToRegU32 0x00010000 0x001FFFFF
\0[\x01-\x1F][\0-\xFF][\0-\xFF]
Unicode> urToRegU32L 0x00010000 0x001FFFFF
[\x01-\x1F][\0-\xFF][\0-\xFF]\0

这不太好,但它应该有效。

答案 1 :(得分:18)

Flex不支持Unicode。但是,Flex支持“8位清理”二进制输入。因此,您可以编写与UTF-8匹配的词法模式。您可以在输入语言的特定词汇区域中使用这些模式,例如标识符,注释或字符串文字。

这对于典型的编程语言非常有用,在这些语言中,您可以向实现的用户断言源语言是用ASCII / UTF-8编写的(并且不支持其他编码,句点)。 / p>

如果您的扫描仪必须处理可以采用任何编码的文本,则此方法无效。如果您需要专门针对Unicode元素表达词法规则,它也不会(非常好)。即您需要扫描仪本身的Unicode字符和Unicode正则表达式。

这个想法是你可以使用lex规则识别包含UTF-8字节的模式(然后可能使用yytext,并将其转换为UTF-8或至少验证它。)

有关工作示例,请参阅TXR语言的源代码,尤其是此文件:http://www.kylheku.com/cgit/txr/tree/parser.l

向下滚动到此部分:

ASC     [\x00-\x7f]
ASCN    [\x00-\t\v-\x7f]
U       [\x80-\xbf]
U2      [\xc2-\xdf]
U3      [\xe0-\xef]
U4      [\xf0-\xf4]

UANY    {ASC}|{U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}
UANYN   {ASCN}|{U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} 
UONLY   {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}

如您所见,我们可以定义模式以匹配ASCII字符以及UTF-8开始和连续字节。 UTF-8是一种词法符号,这是一个词法分析器生成器,所以......没问题!

一些解释:UANY表示匹配任何字符,单字节ASCII或多字节UTF-8。 UANYN表示UANY,但与换行符不匹配。这对于不会跨越行的标记很有用,例如从#到包含国际文本的行末尾的注释。 UONLY表示仅匹配UTF-8扩展字符,而不是ASCII字符。这对于编写一个需要排除某些特定ASCII字符(不仅仅是换行符)的lex规则很有用,但所有扩展字符都可以。

  

免责声明:请注意,扫描程序的规则使用名为utf8_dup_from的函数将yytext转换为包含Unicode代码点的宽字符串。这个功能很强大;它可以检测超长序列和无效字节等问题并正确处理它们。即这个程序不依赖于这些lex规则来做验证和转换,只是为了做基本的词汇识别。这些规则将识别超长形式(如使用几个字节编码的ASCII代码)作为有效语法,但转换函数将正确处理它们。在任何情况下,我都不希望程序源代码中存在与UTF-8相关的安全问题,因为您无论如何都必须信任源代码才能运行它(但程序处理的数据可能不受信任!)如果你是为不受信任的UTF-8数据编写扫描仪,请小心!

答案 2 :(得分:2)

  

我想知道最新版本的flex是否支持unicode?      

如果是这样,如何使用模式匹配中文字符?

要将带有中文字符和其他Unicode代码点的模式与类似Flex的词法分析器匹配,您可以将RE/flex lexical analyzer用于向后兼容Flex的C ++。 RE / flex支持Unicode,并与Bison一起构建词法分析器和解析器。

您可以在RE / flex规范中编写Unicode模式(和UTF-8正则表达式),例如:

%option flex unicode
%%
[肖晗]   { printf ("xiaohan/2\n"); }
%%

使用全局%option unicode启用Unicode。您还可以使用局部修饰符(?u:)将Unicode限制为单个模式(因此其他所有内容仍为ASCII / 8位,如Flex中所示):

%option flex
%%
(?u:[肖晗])   { printf ("xiaohan/2\n"); }
(?u:\p{Han})  { printf ("Han character %s\n", yytext); }
.             { printf ("8-bit character %d\n", yytext[0]); }
%%

选项flex支持Flex兼容性,因此您可以使用yytextyylengECHO等。如果没有flex选项,RE / flex期望Lexer方法调用:text()(或str()wstr() std::stringstd::wstring),{{ 1}}(或size()表示宽字符长度)和wsize()。 RE / flex方法调用是更清晰的恕我直言,并包括宽字符操作。