]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/tests/translit/src/com/ibm/icu/dev/test/util/Tokenizer.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / tests / translit / src / com / ibm / icu / dev / test / util / Tokenizer.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2002-2009, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.dev.test.util;\r
8 \r
9 import java.text.ParsePosition;\r
10 import java.util.HashMap;\r
11 import java.util.HashSet;\r
12 import java.util.Map;\r
13 import java.util.Set;\r
14 \r
15 import com.ibm.icu.lang.UCharacter;\r
16 import com.ibm.icu.text.SymbolTable;\r
17 import com.ibm.icu.text.UTF16;\r
18 import com.ibm.icu.text.UnicodeMatcher;\r
19 import com.ibm.icu.text.UnicodeSet;\r
20 \r
21 public class Tokenizer {\r
22     protected String source;\r
23     \r
24     protected StringBuffer buffer = new StringBuffer();\r
25     protected long number;\r
26     protected UnicodeSet unicodeSet = null;\r
27     protected int index;\r
28     boolean backedup = false;\r
29     protected int lastIndex = -1;\r
30     protected int nextIndex;\r
31     int lastValue = BACKEDUP_TOO_FAR;\r
32     TokenSymbolTable symbolTable = new TokenSymbolTable();\r
33 \r
34     private static final char\r
35         QUOTE = '\'',\r
36         BSLASH = '\\';\r
37     private static final UnicodeSet QUOTERS = new UnicodeSet().add(QUOTE).add(BSLASH);\r
38     private static final UnicodeSet WHITESPACE = new UnicodeSet("[" +\r
39         "\\u0009-\\u000D\\u0020\\u0085\\u200E\\u200F\\u2028\\u2029" +\r
40         "]");\r
41     private static final UnicodeSet SYNTAX = new UnicodeSet("[" +\r
42         "\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E" +\r
43         "\\u00A1-\\u00A7\\u00A9\\u00AB-\\u00AC\\u00AE" +\r
44         "\\u00B0-\\u00B1\\u00B6\\u00B7\\u00BB\\u00BF\\u00D7\\u00F7" +\r
45         "\\u2010-\\u2027\\u2030-\\u205E\\u2190-\\u2BFF" +\r
46         "\\u3001\\u3003\\u3008-\\u3020\\u3030" +\r
47         "\\uFD3E\\uFD3F\\uFE45\\uFE46" +\r
48         "]").removeAll(QUOTERS).remove('$');\r
49     private static final UnicodeSet NEWLINE = new UnicodeSet("[\\u000A\\u000D\\u0085\\u2028\\u2029]");\r
50     //private static final UnicodeSet DECIMAL = new UnicodeSet("[:Nd:]");\r
51     private static final UnicodeSet NON_STRING = new UnicodeSet()\r
52         .addAll(WHITESPACE)\r
53         .addAll(SYNTAX);\r
54            \r
55     protected UnicodeSet whiteSpace = WHITESPACE;\r
56     protected UnicodeSet syntax = SYNTAX;\r
57     private UnicodeSet non_string = NON_STRING;\r
58 \r
59     private void fixSets() {\r
60         if (syntax.containsSome(QUOTERS) || syntax.containsSome(whiteSpace)) {\r
61             syntax = ((UnicodeSet)syntax.clone()).removeAll(QUOTERS).removeAll(whiteSpace);\r
62         }\r
63         if (whiteSpace.containsSome(QUOTERS)) {\r
64             whiteSpace = ((UnicodeSet)whiteSpace.clone()).removeAll(QUOTERS);\r
65         }\r
66         non_string = new UnicodeSet(syntax)\r
67             .addAll(whiteSpace);\r
68     }\r
69     \r
70     public Tokenizer setSource(String source) {\r
71         this.source = source;\r
72         this.index = 0;\r
73         return this; // for chaining\r
74     }\r
75     \r
76     public Tokenizer setIndex(int index) {\r
77         this.index = index;\r
78         return this; // for chaining\r
79     }\r
80     \r
81     public static final int \r
82         DONE = -1, \r
83         NUMBER = -2, \r
84         STRING = -3, \r
85         UNICODESET = -4, \r
86         UNTERMINATED_QUOTE = -5,\r
87         BACKEDUP_TOO_FAR = -6;\r
88         \r
89     private static final int\r
90         //FIRST = 0,\r
91         //IN_NUMBER = 1,\r
92         //IN_SPACE = 2,\r
93         AFTER_QUOTE = 3,    // warning: order is important for switch statement\r
94         IN_STRING = 4, \r
95         AFTER_BSLASH = 5, \r
96         IN_QUOTE = 6;\r
97    \r
98     public String toString(int type, boolean backedupBefore) {\r
99         String s = backedup ? "@" : "*";\r
100         switch(type) {\r
101             case DONE: \r
102                 return s+"Done"+s;\r
103             case BACKEDUP_TOO_FAR:\r
104                 return s+"Illegal Backup"+s;\r
105             case UNTERMINATED_QUOTE: \r
106                 return s+"Unterminated Quote=" + getString() + s;\r
107             case STRING:\r
108                 return s+"s=" + getString() + s;\r
109             case NUMBER:\r
110                 return s+"n=" + getNumber() + s;\r
111             case UNICODESET:\r
112                 return s+"n=" + getUnicodeSet() + s;           \r
113             default:\r
114                 return s+"c=" + usf.getName(type,true) + s;\r
115         }\r
116     }\r
117     \r
118     private static final BagFormatter usf = new BagFormatter();\r
119     \r
120     public void backup() {\r
121         if (backedup) throw new IllegalArgumentException("backup too far");\r
122         backedup = true;\r
123         nextIndex = index;\r
124         index = lastIndex;\r
125     }\r
126     \r
127     /*\r
128     public int next2() {\r
129         boolean backedupBefore = backedup;\r
130         int result = next();\r
131         System.out.println(toString(result, backedupBefore));\r
132         return result;\r
133     }    \r
134     */\r
135     \r
136     public int next() {\r
137         if (backedup) {\r
138             backedup = false;\r
139             index = nextIndex;\r
140             return lastValue;\r
141         }\r
142         int cp = 0;\r
143         boolean inComment = false;\r
144         // clean off any leading whitespace or comments\r
145         while (true) {\r
146             if (index >= source.length()) return lastValue = DONE;\r
147             cp = nextChar();\r
148             if (inComment) {\r
149                 if (NEWLINE.contains(cp)) inComment = false;\r
150             } else {\r
151                 if (cp == '#') inComment = true;\r
152                 else if (!whiteSpace.contains(cp)) break;\r
153             }\r
154         }\r
155         // record the last index in case we have to backup\r
156         lastIndex = index;\r
157         \r
158         if (cp == '[') {\r
159             ParsePosition pos = new ParsePosition(index-1);\r
160             unicodeSet = new UnicodeSet(source,pos,symbolTable);\r
161             index = pos.getIndex();\r
162             return lastValue = UNICODESET;\r
163         }\r
164         // get syntax character\r
165         if (syntax.contains(cp)) return lastValue = cp;\r
166         \r
167         // get number, if there is one\r
168         if (UCharacter.getType(cp) == Character.DECIMAL_DIGIT_NUMBER) {\r
169             number = UCharacter.getNumericValue(cp);\r
170             while (index < source.length()) {\r
171                 cp = nextChar();\r
172                 if (UCharacter.getType(cp) != Character.DECIMAL_DIGIT_NUMBER) {\r
173                     index -= UTF16.getCharCount(cp); // BACKUP!\r
174                     break;\r
175                 }\r
176                 number *= 10;\r
177                 number += UCharacter.getNumericValue(cp);\r
178             }\r
179             return lastValue =  NUMBER;\r
180         }\r
181         buffer.setLength(0);\r
182         int status = IN_STRING;\r
183         main:\r
184         while (true) {\r
185             switch (status) {\r
186                 case AFTER_QUOTE: // check for double ''?\r
187                     if (cp == QUOTE) {\r
188                         UTF16.append(buffer, QUOTE);\r
189                         status = IN_QUOTE;\r
190                         break;\r
191                     }\r
192                     // OTHERWISE FALL THROUGH!!!\r
193                 case IN_STRING: \r
194                     if (cp == QUOTE) status = IN_QUOTE;\r
195                     else if (cp == BSLASH) status = AFTER_BSLASH;\r
196                     else if (non_string.contains(cp)) {\r
197                         index -= UTF16.getCharCount(cp); // BACKUP!\r
198                         break main;\r
199                     } else UTF16.append(buffer,cp);\r
200                     break;\r
201                 case IN_QUOTE:\r
202                     if (cp == QUOTE) status = AFTER_QUOTE;\r
203                     else UTF16.append(buffer,cp);\r
204                     break;\r
205                 case AFTER_BSLASH:\r
206                     switch(cp) {\r
207                         case 'n': cp = '\n'; break;\r
208                         case 'r': cp = '\r'; break;\r
209                         case 't': cp = '\t'; break;\r
210                     }\r
211                     UTF16.append(buffer,cp);\r
212                     status = IN_STRING;\r
213                     break;\r
214                 default: throw new IllegalArgumentException("Internal Error");\r
215             }\r
216             if (index >= source.length()) break;\r
217             cp = nextChar();\r
218         }\r
219         if (status > IN_STRING) return lastValue = UNTERMINATED_QUOTE;\r
220         return lastValue =  STRING;\r
221     }\r
222     \r
223     public String getString() {\r
224         return buffer.toString();\r
225     }\r
226     \r
227     public String toString() {\r
228         return source.substring(0,index) + "$$$" + source.substring(index);\r
229     }\r
230     \r
231     public long getNumber() {\r
232         return number;\r
233     }\r
234     \r
235     public UnicodeSet getUnicodeSet() {\r
236         return unicodeSet;\r
237     }\r
238     \r
239     private int nextChar() {\r
240         int cp = UTF16.charAt(source,index);\r
241         index += UTF16.getCharCount(cp);\r
242         return cp;\r
243     }\r
244     public int getIndex() {\r
245         return index;\r
246     }\r
247     public String getSource() {\r
248         return source;\r
249     }\r
250     public UnicodeSet getSyntax() {\r
251         return syntax;\r
252     }\r
253     public UnicodeSet getWhiteSpace() {\r
254         return whiteSpace;\r
255     }\r
256     public void setSyntax(UnicodeSet set) {\r
257         syntax = set;\r
258         fixSets();\r
259     }\r
260     public void setWhiteSpace(UnicodeSet set) {\r
261         whiteSpace = set;\r
262         fixSets();\r
263     }\r
264     \r
265     public Set getLookedUpItems() {\r
266         return symbolTable.itemsLookedUp;\r
267     }\r
268     \r
269     public void addSymbol(String var, String value, int start, int limit) {\r
270         // the limit is after the ';', so remove it\r
271         --limit;\r
272         char[] body = new char[limit - start];\r
273         value.getChars(start, limit, body, 0);\r
274         symbolTable.add(var, body);\r
275     }\r
276     \r
277     public class TokenSymbolTable implements SymbolTable {\r
278         Map contents = new HashMap();\r
279         Set itemsLookedUp = new HashSet();\r
280             \r
281         public void add(String var, char[] body) {\r
282             // start from 1 to avoid the $\r
283             contents.put(var.substring(1), body);\r
284         }\r
285             \r
286         /* (non-Javadoc)\r
287          * @see com.ibm.icu.text.SymbolTable#lookup(java.lang.String)\r
288          */\r
289         public char[] lookup(String s) {\r
290             itemsLookedUp.add('$' + s);\r
291             return (char[])contents.get(s);\r
292         }\r
293     \r
294         /* (non-Javadoc)\r
295          * @see com.ibm.icu.text.SymbolTable#lookupMatcher(int)\r
296          */\r
297         public UnicodeMatcher lookupMatcher(int ch) {\r
298             // TODO Auto-generated method stub\r
299             return null;\r
300         }\r
301     \r
302         /* (non-Javadoc)\r
303          * @see com.ibm.icu.text.SymbolTable#parseReference(java.lang.String, java.text.ParsePosition, int)\r
304          */\r
305         public String parseReference(String text, ParsePosition pos, int limit) {\r
306             int cp;\r
307             int start = pos.getIndex();\r
308             int i;\r
309             for (i = start; i < limit; i += UTF16.getCharCount(cp)) {\r
310                 cp = UTF16.charAt(text, i);\r
311                 if (!com.ibm.icu.lang.UCharacter.isUnicodeIdentifierPart(cp)) {\r
312                     break;\r
313                 }\r
314             }\r
315             pos.setIndex(i);\r
316             return text.substring(start,i);\r
317         }\r
318         \r
319     }\r
320 }\r