JFlex规则错误-匹配了错误的规则



我正在编写一个(简单的?)JFlex标记器,其目标是提取一个字符串,并将中文(或者更确切地说,使用汉文)中的块和拉丁文中的部分进行梳理。标记符应用于品牌名称,在我的用例中,品牌名称可能同时包含拉丁语和中文名称,例如"联想联想".

品牌名称还可以包含数字(7up)、连字符(Hewlett-Packard)、和号(p&G)等。我的标记器主要起作用,除非中文和非中文名称写在一起,没有任何空格或分隔。具体来说,以下是成功和不成功解析的例子:

  • "卡尔文·克莱因卡尔文.克莱"-成功拆分为"卡尔文·克莱因"one_answers"卡尔文.克莱",并且他们被标记为具有预期的脚本(拉丁语和汉族)

  • "圣威廉圣威廉"-错误地分裂成"圣威廉SAINT"(标记为汉字)和"WILLIAM"(标为拉丁文)。

  • "史努比SNOOPY"-被错误地认为是单个Han代币。

我认为我的规则非常明确,但结果似乎表明情况并非如此。这是我的规则集:

digit      = [0-9]
whitespace = [ trn] | rn
latin = [u0041-u005au0061-u007au00c0-u00d6u00d8-u00f6u00f8-u01bfu01c4-u024f]
han   = [u3400-u9fffuf900-ufaffu2f800-u2fa1f]
// Punctuation in the middle or end of string sequences in a particular script
latin_middle  = [&.-'`‘]
latin_end     = [.]
han_middle    = [.]
// A basic Latin token contains a mixture of Latin characters and possibly digits.
basic_latin_tok    = ({latin} | {digit})+
compound_latin_tok = {basic_latin_tok} (({whitespace}+ | {latin_middle}) {basic_latin_tok})*{latin_end}?
basic_han_tok     = {han}({han} | {digit})* 
                  | ({han} | {digit})*{han}
compound_han_tok  = {basic_han_tok}({han_middle}{basic_han_tok})*
%%
{compound_latin_tok}             { return "Latin"; }
{compound_han_tok}               { return "Han"; }
.                                { /* skip everything else */ }

我做错了什么?

谢谢!!

编辑

我问了SourceForge JFlex邮件列表上的人,其中一人回答说JFlex 1.4.*无法处理不能用16位表示的Unicode字符。由于我在上面为Han字符指定的一些字符范围超过了16位值,JFlex会感到困惑。从正则表达式中删除这些使其工作得很好。

供参考:http://jflex.de/manual.html#SECTION000101000000000000000

我问了SourceForge JFlex邮件列表上的人,其中一人回答我——事实证明JFlex 1.4.*不能处理不能用16位表示的Unicode字符。

哦,但它可以处理这些。

首先,让我对\u2f800-\u2fa1f进行更正。最后一个值确实不能用16位表示,但这只是因为UNICODE块定义停止在\u2fa1d,因此即使在32位表示上,该值也是UNICODE无效的

现在,说服JFlex处理好您遇到问题的[\u2f800-\u2fa1d]范围的诀窍是:Java代码(和字符串文字)使用某种UTF16编码,因此一个16位的"代理"(较高的UTF16字)后面跟着其他16位的成对字符。

对于您需要的范围,您很幸运:第一个16位代理在整个范围内保持不变,即\uD87E,而较低的16位在[\uDC00-\uDE1D]范围内变化。所以,你的han宏变成了

han   = [u3400-u9fffuf900-ufaff] | uD87E[uDC00-uDE1D]

在我懒惰地将32位wchars转换为UTF16/8编码的过程中,我发现这是一种有用的资源:http://www.fileformat.info.例如。http://www.fileformat.info/info/unicode/char/2fa1d/index.htm并向下滚动到"UTF-16(十六进制)"或"C/C++/Java源代码"。

最新更新