2012-03-08 104 views

回答

14

目前,Flex仅产生8位扫描仪基本上限制了你使用UTF-8。因此,如果你有一个模式:

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

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

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

,因为这将匹配所有六个字节0xe8,为0x82,0x96,0xe6,0x99和0x97,其中在实践手段如果您提供肖晗作为输入,模式将匹配六次。因此,在这种简单的情况下,您必须将模式重写为(肖|晗)

对于范围,汉斯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 

这是不漂亮,但它应该工作。

+0

解决方法的更多提示? – xiaohan2012 2012-03-08 02:34:24

+0

我将我的回复从邮件列表复制到答案。 – 2012-03-08 18:28:56

+0

谢谢。似乎激励了我很多! – xiaohan2012 2012-03-11 12:38:42

15

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

对于典型的编程语言,这可以很好地工作,在那里你可以向你的实现的用户声明源语言是用ASCII/UTF-8编写的(并且没有其他编码被支持,句号)。

如果您的扫描仪必须处理可以采用任何编码的文本,则此方法无效。如果你需要专门为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 characte rs以及UTF-8的开始和继续字节。 UTF-8是一个词法符号,这是一个词法分析器生成器,所以......没问题!

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

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

+0

想知道,U4的定义不应该是这样的: 'U4 [\ xf0- \ xf7]' 实际上容纳从11110000到11110111的所有可能性吗? – exa 2016-10-09 11:31:27

+0

@exa注意细节!该字节的全部范围将使我们的代码点达到'U + 3FFFFF'。 'F4'限制为'U + 10FFFF'。 – Kaz 2016-10-09 14:18:06

+0

我想知道所提出的方法是否安全。这些TRX模式包括无效的U + D800-U + DFFF范围(UTF016替代品一半是无效的Unicode)和U4 U UU UU超出了Unicode上限U + 10FFFF,最后一个代码点应该是'\ xf4 [\ x80- \ x8f] [\ x80- \ xbf] [\ x80- \ xbf]'\ xf4 [\ x80- \ xbf] x80- \ XBF]'。 – 2017-03-24 18:02:01

1

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

如果是这样,怎样才能使用模式匹配汉字?

,以配合中国的字符和其他的Unicode码点和Flex-像词法分析器模式,你可以使用RE/flex lexical analyzer对于C++是使用Flex向后兼容。 RE/flex支持Unicode,并与Bison合作构建词法分析器和分析器。

你可以写在RE /柔性规格统一模式(和UTF-8正则表达式),如:

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

使用全局%option unicode启用统一。您也可以使用本地修改(?u:)限制统一到一个单一的模式(所以一切仍是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 /柔性预计词法方法调用:text()(或str()wstr()std::stringstd::wstring),size()(或wsize()为宽字符长度),和echo()。 RE/flex方法调用更清洁恕我直言,并包括宽字符操作。