2

私は (単純な?) JFlex トークナイザーを作成しています。その目的は、文字列を取得し、中国語のチャンク (またはハンスクリプトを使用) とラテンスクリプトの部分を分解することです。トークナイザーはブランド名に適用されます。私の使用例では、ブランド名にラテン語と中国語の名前の両方が含まれる場合があります (例: "Lenovo 联想")。

ブランド名には、さらに数字 (7up)、ハイフン (Hewlett-Packard)、アンパサンド (P&G) などを含めることができます。中国語と非中国語の名前がスペースや区切りなしで一緒に書かれている場合を除いて、私のトークナイザーはほとんど機能します。具体的には、成功した解析と失敗した解析の例を次に示します。

  • "Calvin Klein卡尔文.克莱" - "Calvin Klein" と "卡尔文.克莱" に正常に分割され、期待されるスクリプト (ラテン語とハン語) を持つものとしてタグ付けされます。

  • "圣威廉SAINT WILLIAM" - "圣威廉SAINT" (Han chars としてマーク) と "WILLIAM" (Latin としてマーク) に誤って分割されます。

  • 「史努力比SNOOPY」 - 誤って単一の漢トークンと見なされます。

私のルールはかなり明白だと思っていましたが、結果はそうではないことを示しているようです. これが私のルールセットです:

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 メーリング リストのメンバーに尋ねたところ、そのうちの 1 人から返信がありました。JFlex 1.4.* は、16 ビットで表現できない Unicode 文字を処理できないことがわかりました。上記で指定した漢字の文字範囲の一部は 16 ビット値を超えるため、JFlex は混乱します。それらを正規表現から削除すると、すべてうまく機能しました。

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

4

1 に答える 1

1

SourceForge JFlex メーリング リストのメンバーに尋ねたところ、そのうちの 1 人から返信がありました。JFlex 1.4.* は、16 ビットで表現できない Unicode 文字を処理できないことがわかりました。

ああ、しかしそれはそれらを処理できます。

まず、\u2f800-\u2fa1f に訂正をさせてください。最後の値は実際には 16 ビットでは表現できませんが、UNICODE ブロック定義が \u2fa1d で停止するため、32 ビット表現でも UNICODE は無効です。

さて、問題のある [\u2f800-\u2fa1d] 範囲を処理するように JFlex を説得するための秘訣: Java コード (および文字列リテラル) は、UTF16 エンコーディングの一種を使用するため、16 ビットの「サロゲート」 (上位の UTF16 ワード)その後に、他の 16 ビットのペア文字が続きます。

必要な範囲については、幸運です。最初の 16 ビットのサロゲートは範囲全体で同じままです。つまり \uD87E ですが、下位 16 ビットは [\uDC00-\uDE1D] の範囲で変化します。したがって、ハンマクロは次のようになります

han   = [\u3400-\u9fff\uf900-\ufaff] | \uD87E[\uDC00-\uDE1D]

32 ビットの wchars を UTF16/8 エンコーディングに変換するのが面倒だったので、役に立つリソース: http://www.fileformat.info。たとえば、 http ://www.fileformat.info/info/unicode/char/2fa1d/index.htmで、「UTF-16 (hex)」または「C/C++/Java ソース コード」までスクロールします。

于 2014-02-18T19:17:11.470 に答える