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