]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/tools/misc/src/com/ibm/icu/dev/tool/charsetdet/sbcs/NGramParser.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / tools / misc / src / com / ibm / icu / dev / tool / charsetdet / sbcs / NGramParser.java
1 /*\r
2  ***********************************************************************\r
3  * Copyright (C) 2005, International Business Machines Corporation and *\r
4  * others. All Rights Reserved.                                        *\r
5  ***********************************************************************\r
6  *\r
7  */\r
8 \r
9 package com.ibm.icu.dev.tool.charsetdet.sbcs;\r
10 \r
11 import com.ibm.icu.text.UnicodeSet;\r
12 \r
13 /**\r
14  * @author emader\r
15  *\r
16  * TODO To change the template for this generated type comment go to\r
17  * Window - Preferences - Java - Code Style - Code Templates\r
18  */\r
19 public class NGramParser\r
20 {\r
21 \r
22     public interface NGramParserClient\r
23     {\r
24         char nextChar();\r
25         void handleNGram(String key);\r
26     }\r
27     \r
28     private static final int A_NULL = 0;\r
29     private static final int A_ADDC = 1;\r
30     private static final int A_ADDS = 2;\r
31     \r
32     /*\r
33      * Character classes\r
34      */\r
35     public static final int C_IGNORE = 0;\r
36     public static final int C_LETTER = 1;\r
37     public static final int C_PUNCT  = 2;\r
38     \r
39     private static final int S_START  = 0;\r
40     private static final int S_LETTER = 1;\r
41     private static final int S_PUNCT  = 2;\r
42 \r
43     static final class StateEntry\r
44     {\r
45         private int newState;\r
46         private int action;\r
47         \r
48         StateEntry(int theState, int theAction)\r
49         {\r
50             newState = theState;\r
51             action   = theAction;\r
52         }\r
53         \r
54         public int getNewState()\r
55         {\r
56             return newState;\r
57         }\r
58         \r
59         public int getAction()\r
60         {\r
61             return action;\r
62         }\r
63     }\r
64     \r
65     private StateEntry[][] stateTable = {\r
66             {new StateEntry(S_START,  A_NULL), new StateEntry(S_LETTER, A_ADDC), new StateEntry(S_PUNCT,  A_ADDS)},\r
67             {new StateEntry(S_LETTER, A_NULL), new StateEntry(S_LETTER, A_ADDC), new StateEntry(S_PUNCT,  A_ADDS)},\r
68             {new StateEntry(S_PUNCT,  A_NULL), new StateEntry(S_LETTER, A_ADDC), new StateEntry(S_PUNCT,  A_NULL)}\r
69     };\r
70 \r
71     protected final int N_GRAM_SIZE = 3;\r
72     \r
73     private char[] letters = new char[N_GRAM_SIZE];\r
74     private int letterCount;\r
75     \r
76     private static UnicodeSet letterSet = new UnicodeSet("[:letter:]");\r
77 \r
78     private NGramParserClient client;\r
79 \r
80     /**\r
81      * \r
82      */\r
83     public NGramParser(NGramParserClient theClient)\r
84     {\r
85         client = theClient;\r
86         letterCount = 0;\r
87     }\r
88     \r
89     public void setClient(NGramParserClient theClient)\r
90     {\r
91         client = theClient;\r
92     }\r
93     \r
94     // TODO Is this good enough, or are there other C_IGNORE characters?\r
95     // TODO Could this make Latin letters C_PUNCT for non-Latin scripts?\r
96     public static int getCharClass(char ch)\r
97     {\r
98         if (ch == '\'' || ch == '\uFEFF') {\r
99             return C_IGNORE;\r
100         }\r
101         \r
102         if (letterSet.contains(ch)) {\r
103             return C_LETTER;\r
104         }\r
105         \r
106         return C_PUNCT;\r
107     }\r
108     \r
109     public void reset()\r
110     {\r
111         letterCount = 0;\r
112     }\r
113     \r
114     public void addLetter(char letter)\r
115     {\r
116         // somewhat clever stuff goes here...        \r
117         letters[letterCount++] = letter;\r
118         \r
119         if (letterCount >= N_GRAM_SIZE) {\r
120             String key = new String(letters);\r
121             \r
122             client.handleNGram(key);\r
123             \r
124             letterCount = N_GRAM_SIZE - 1;\r
125             for (int i = 0; i < letterCount; i += 1) {\r
126                 letters[i] = letters[i + 1];\r
127             }\r
128         }\r
129     }\r
130     \r
131     public void parse()\r
132     {\r
133         char ch;\r
134         int state = 0;\r
135 \r
136         // this is where the clever stuff goes...\r
137         while ((ch = client.nextChar()) != 0) {\r
138             int charClass = getCharClass(ch);\r
139             StateEntry entry = stateTable[state][charClass];\r
140             \r
141             state = entry.getNewState();\r
142             \r
143             switch (entry.getAction())\r
144             {\r
145             case A_ADDC:\r
146                 addLetter(Character.toLowerCase(ch));\r
147                 break;\r
148                 \r
149             case A_ADDS:\r
150                 addLetter(' ');\r
151                 break;\r
152  \r
153             case A_NULL:\r
154             default:\r
155                 break;\r
156             }\r
157         }\r
158         \r
159         addLetter(' ');\r
160     }\r
161 }\r