目前,Flex只生成8位扫描器,这基本上限制了您使用UTF-8。因此,如果您有一个模式:
肖晗 { printf ("xiaohan\n"); }
如果模式和输入中的字节序列相同,它将像预期的那样工作。更困难的是字符类。如果要匹配字符"肖"或"晗",则不能编写以下内容:
[肖晗] { printf ("xiaohan/2\n"); }
因为这将匹配六个字节0xe8、0x82、0x96、0xe6、0x99和0x97,实际上这意味着如果您提供肖晗
作为输入,该模式将匹配六次。因此,在这种简单情况下,您必须将模式重写为(肖|晗)
。
对于范围,Hans Aberg编写了一个在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
这不太漂亮,但应该可以工作。
Flex不支持Unicode。但是,Flex支持“8位清洁”的二进制输入。因此,您可以编写匹配UTF-8的词法模式。您可以在输入语言的特定词法区域(例如标识符、注释或字符串文字)中使用这些模式。
这对于典型的编程语言来说很有效,其中您可以向实现的用户断言源语言是用ASCII / UTF-8编写的(而且不支持其他任何编码,期间)。
如果您的扫描仪必须处理可能以任何编码方式进行的文本,则此方法将无效。如果您需要在扫描仪本身中明确表示Unicode元素的词法规则,则此方法也不会很好地工作。即您需要Unicode字符和Unicode正则表达式。
思路是,您可以使用词法规则识别包含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}
U4 [\xf0-\xf7]
以实际容纳从11110000到11110111的所有可能性吗? - exayytext[]
空终止字符字符串需要通过适当的UTF-8解码器进行处理,该解码器详细处理所有这些情况。 - Kaz[肖晗]
。%option flex unicode
%%
[肖晗] { printf ("xiaohan/2\n"); }
%%
%option unicode
来启用Unicode,并使用%option flex
来指定Flex规范。可以使用本地修饰符(?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兼容性,因此您可以使用yytext
、yyleng
、ECHO
等。如果没有flex
选项,RE / flex会期望Lexer方法调用:text()
(或者str()
和wstr()
用于std::string
和std::wstring
),size()
(或wsize()
用于宽字符长度)和echo()
。个人认为,RE/flex方法调用更加简洁,包括宽字符操作。
hugs
而不是ghc
。 - xiaohan2012