我在写(简单?)JFlex标记器,其目标是取一个字符串,并将中文(或者更确切地说是使用汉字)的块和拉丁文中的部分拆开。标记器应用于品牌名称,在我的用例中,品牌名称可能同时包含拉丁语和中文名称。“联想联想”。
品牌名称还可以包含数字(7up)、连字符(惠普)、符号(P&G)等。我的标识器主要起作用,除了中文名称和非中文名称没有空格或分隔的情况外。具体而言,这些是成功和不成功分析的例子:
我认为我的规则是相当明确的,但结果似乎表明并非如此。这是我的规则:
digit = [0-9]
whitespace = [ \t\r\n] | \r\n
latin = [\u0041-\u005a\u0061-\u007a\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u01bf\u01c4-\u024f]
han = [\u3400-\u9fff\uf900-\ufaff\u2f800-\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字符。由于我前面为汉字指定的一些字符范围超过了16位值,所以JFlex会感到困惑。将这些从regex中移除使其工作得很好。
参考:http://jflex.de/manual.html#SECTION000101000000000000000
发布于 2014-02-18 19:17:11
我询问了SourceForge JFlex邮件列表上的人员,其中一位回复了我--原来是JFlex 1.4。*无法处理不能以16位表示的Unicode字符。
但它能处理好这些。
首先,让我修正一下\u2f800-u2fa1f。最后一个值确实不能在16位上表示,只是因为UNICODE块定义在\u2fa1d处停止,因此该值即使在其32位表示形式上也是无效的。
现在,说服JFlex处理问题\u2f800-\u2fa1d范围的诀窍是: Java代码(和字符串文本)使用UTF16编码的排序,因此16位“代理”(较高的UTF16单词)后面跟着其他16位配对字符。
对于您需要的范围,您是幸运的:前16位代理项在整个范围内保持不变,即\uD87E,而较低的16位在\uDC00-\uDE1D范围内变化。所以,你的韩宏变成
han = [\u3400-\u9fff\uf900-\ufaff] | \uD87E[\uDC00-\uDE1D]在我懒惰地将32位wchars转换为UTF16 16/8编码时,我发现了一个有用的资源:http://www.fileformat.info。例如,http://www.fileformat.info/info/unicode/char/2fa1d/index.htm和滚动到"UTF-16 (十六进制)“或"C/C++/Java源代码”。
https://stackoverflow.com/questions/18520420
复制相似问题