Flex(词法分析器)支持unicode

xia*_*012 21 unicode flex-lexer

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

如果是这样,如何使用模式匹配汉字?

更多: 使用正则表达式匹配utf-8编码中的任何中文字符

Tim*_*idt 18

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

??   { printf ("xiaohan\n"); }
Run Code Online (Sandbox Code Playgroud)

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

[??]   { printf ("xiaohan/2\n"); }
Run Code Online (Sandbox Code Playgroud)

因为这将匹配六个字节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
Run Code Online (Sandbox Code Playgroud)

这不是很好,但它应该工作.

  • 抱歉突然,我使用了错误的工具.我应该使用`hugs`而不是`ghc` (3认同)

Kaz*_*Kaz 18

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}
Run Code Online (Sandbox Code Playgroud)

如您所见,我们可以定义模式以匹配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数据编写扫描仪,请注意!


Dr.*_* RE 5

\n

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

\n

如果可以的话,如何使用模式来匹配汉字呢?

\n
\n

要使用兼容 Flex 的词法分析器将模式与中文字符和其他 Unicode 代码点进行匹配,可以使用适用于 C++ 的RE/flex 词法分析器

\n

RE/flex安全地支持完整的 Unicode 标准,并接受 UTF-8、UTF-16 和 UTF-32 输入文件,而不需要 UTF-8 hack(甚至不能支持 UTF-16/32 输入和处理 UTF BOM)。 )

\n

另外,使用 Flex 的 UTF-8 hack 不允许您编写 Unicode 正则表达式,例如[\xe8\x82\x96\xe6\x99\x97]RE/flex 中完全支持的正则表达式。

\n

它与 Bison 无缝协作来构建词法分析器和解析器。

\n

事实上,通过 RE/flex,我们可以在词法分析器.l规范中将任何 Unicode 模式编写为基于 UTF-8 的正则表达式,例如:

\n
%option flex unicode\n%%\n[\xe8\x82\x96\xe6\x99\x97]   { printf ("xiaohan/2\\n"); }\n%%\n
Run Code Online (Sandbox Code Playgroud)\n

这会生成一个自动扫描 UTF-8、UTF-16 和 UTF-32 文件的词法分析器。根据 UTF 标准化,对于 UTF-16/32 输入,输入中应包含 UTF BOM,而 UTF-8 BOM 是可选的。

\n

我们可以使用 global%option unicode来启用 Unicode 并%option flex指定 Flex 规范。本地修饰符(?u:)可用于将 Unicode 限制为单一模式(因此其他所有内容仍然是 ASCII/8 位,如 Flex 中一样):

\n
%option flex\n%%\n(?u:[\xe8\x82\x96\xe6\x99\x97])   { printf ("xiaohan/2\\n"); }\n(?u:\\p{Han})  { printf ("Han character %s\\n", yytext); }\n.             { printf ("8-bit character %d\\n", yytext[0]); }\n%%\n
Run Code Online (Sandbox Code Playgroud)\n

选项flex启用 Flex 兼容性,因此您可以使用yytextyylengECHO等。如果没有flex选项 RE/flex 则需要 Lexer 方法调用:text()(or str()and wstr()for std::stringand std::wstring), size()(or wsize()for Wide char length), and echo()。RE/flex 方法调用更干净,恕我直言,并且包括宽字符操作。

\n