KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > i18n > regexp > Generator


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 package org.netbeans.modules.i18n.regexp;
22
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27
28 /**
29  * Generator of JDK regular expressions from syntax trees.
30  * It accepts a syntax tree of a regular expression and generates a regular
31  * expression according to syntax rules of JDK's class
32  * {@link java.util.regex.Pattern Pattern}.
33  *
34  * @author Marian Petras
35  */

36 class Generator {
37
38     /** buffer where the regular expression is being built */
39     private StringBuffer JavaDoc buf = new StringBuffer JavaDoc(20);
40
41     /** string to put in place of tokens */
42     private Map JavaDoc tokenReplacements;
43
44     /** */
45     private boolean generatingSetOfChars = false;
46
47
48     /**
49      * Generates a regular expression from a syntax tree.
50      *
51      * @param parseTree root of a syntax tree to create a regular expression
52      * from
53      * @return generated regular expression;
54      * or <code>null</code> if the argument was <code>null</code>
55      */

56     public static String JavaDoc generateRegexp(TreeNode parseTree) {
57         return generateRegexp(parseTree, null);
58     }
59
60
61     /**
62      * Generates a regular expression from a syntax tree.
63      *
64      * @param parseTree root of a syntax tree to create a regular expression
65      * from
66      * @param tokenReplacements maps token names to strings to be put in place
67      * of them, or <code>null</code> to ignore tokens
68      * @return generated regular expression;
69      * or <code>null</code> if the argument was <code>null</code>
70      */

71     public static String JavaDoc generateRegexp(TreeNode parseTree, Map JavaDoc tokenReplacements) {
72         if (parseTree == null) {
73             return null;
74         }
75
76         Generator g = new Generator();
77         g.setTokenReplacements(tokenReplacements);
78         g.generate(parseTree);
79         return g.buf.toString();
80     }
81
82
83     /** */
84     private static String JavaDoc quoteString(String JavaDoc string) {
85         if (string.length() == 0) {
86             return string;
87         }
88
89         StringBuffer JavaDoc buf;
90
91         int startIndex = 0;
92         int endIndex = string.indexOf('\\'); //NOI18N
93

94         if (endIndex == -1) {
95             buf = new StringBuffer JavaDoc(string.length() + 4);
96             buf.append("\\Q").append(string).append("\\E"); //NOI18N
97
} else {
98             buf = new StringBuffer JavaDoc(string.length() + 16);
99             do {
100                 if (endIndex != startIndex) {
101                     buf.append("\\Q"); //NOI18N
102
buf.append(string.substring(startIndex, endIndex));
103                     buf.append("\\E"); //NOI18N
104
}
105                 buf.append('\\').append('\\'); //NOI18N
106
startIndex = endIndex + 1;
107                 endIndex = string.indexOf('\\', startIndex); //NOI18N
108
} while (endIndex != -1);
109             if (startIndex != string.length()) {
110                 buf.append("\\Q"); //NOI18N
111
buf.append(string.substring(startIndex));
112                 buf.append("\\E"); //NOI18N
113
}
114         }
115         return buf.toString();
116     }
117
118
119     /** */
120     private void setTokenReplacements(Map JavaDoc tokenReplacements) {
121         if ((tokenReplacements != null) && tokenReplacements.isEmpty()) {
122             tokenReplacements = null;
123         }
124         this.tokenReplacements = tokenReplacements;
125
126         if (tokenReplacements != null) {
127             quoteTokenReplacements();
128         }
129     }
130
131
132     /** */
133     private void quoteTokenReplacements() {
134         if (tokenReplacements == null || tokenReplacements.isEmpty()) {
135             return;
136         }
137
138         Set JavaDoc replacementEntries = tokenReplacements.entrySet();
139         for (Iterator JavaDoc i = replacementEntries.iterator(); i.hasNext();) {
140             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
141             entry.setValue(quoteString((String JavaDoc) entry.getValue()));
142         }
143     }
144
145
146     /** */
147     private void generate(TreeNode treeNode) {
148         List JavaDoc children = treeNode.getChildren();
149         int tokenType = treeNode.getTokenType();
150         Object JavaDoc attribs = treeNode.getAttribs();
151         char charType;
152         switch (tokenType) {
153             case TreeNode.CHAR:
154                 char ch = ((Character JavaDoc) attribs).charValue();
155                 switch (ch) {
156                     case '\t':
157                         buf.append('\\').append('t');
158                         break;
159
160                     case '\n':
161                         buf.append('\\').append('n');
162                         break;
163
164                     case '\r':
165                         buf.append('\\').append('r');
166                         break;
167
168                     case '\f':
169                         buf.append('\\').append('f');
170                         break;
171
172                     case '\\':
173                         buf.append('\\').append('\\');
174                         break;
175
176                     default:
177                         if (!generatingSetOfChars
178                                && ("^$|*+?.()[]{}".indexOf(ch) != -1)) {//NOI18N
179
buf.append('\\');
180                         }
181                         buf.append(ch);
182                         break;
183                 }
184                 break;
185
186             case TreeNode.METACHAR:
187                 charType = ((Character JavaDoc) attribs).charValue();
188                 if (charType == '.') {
189                     buf.append('.');
190                 } else {
191                     buf.append('\\').append(charType); // \b or \B
192
}
193                 break;
194
195             case TreeNode.QUANTIFIER:
196                 if (attribs instanceof Character JavaDoc) {
197                     charType = ((Character JavaDoc) attribs).charValue();
198                     buf.append(charType);
199                 } else {
200                     String JavaDoc type = (String JavaDoc) attribs;
201                     buf.append('{');
202                     generate((TreeNode) children.get(0)); //Integer - low limit
203
if (type.length() > 3) { //"{n,}" or "{n,n}"
204
buf.append(',');
205                         if (type.length() == 5) { //"{n,n}"
206
generate((TreeNode) children.get(1)); //- high limit
207
}
208                     }
209                     buf.append('}');
210                 }
211                 break;
212
213             case TreeNode.Q_REGEXP:
214                 generate((TreeNode) children.get(0));
215                 if (children.size() == 2) {
216                     generate((TreeNode) children.get(1));
217                 }
218                 break;
219
220             case TreeNode.RANGE:
221                 generate((TreeNode) children.get(0));
222                 buf.append('-');
223                 generate((TreeNode) children.get(1));
224                 break;
225
226             case TreeNode.SET:
227                 buf.append('[');
228                 if (attribs != null) {
229                     buf.append((String JavaDoc) attribs);
230                 }
231                 if (children != null) {
232                     generatingSetOfChars = true;
233                     if (children.size() == 1) {
234                         generate((TreeNode) children.get(0));
235                     } else {
236                         for (Iterator JavaDoc i = children.iterator(); i.hasNext(); ) {
237                             generate((TreeNode) i.next());
238                         }
239                     }
240                     generatingSetOfChars = false;
241                 }
242                 buf.append(']');
243                 break;
244
245             case TreeNode.SIMPLE_REGEXP:
246                 if (children != null) {
247                     if (children.size() == 1) {
248                         generate((TreeNode) children.get(0));
249                     } else {
250                         for (Iterator JavaDoc i = children.iterator(); i.hasNext(); ) {
251                             generate((TreeNode) i.next());
252                         }
253                     }
254                 }
255                 break;
256
257             case TreeNode.SUBEXPR:
258                 buf.append('(').append('?').append(':');
259                 generate((TreeNode) children.get(0));
260                 buf.append(')');
261                 break;
262
263             case TreeNode.MULTI_REGEXP:
264                 generate((TreeNode) children.get(0));
265                 if (children.size() > 1) {
266                     Iterator JavaDoc i = children.iterator();
267                     i.next(); //skip the first one
268
do {
269                         buf.append('|');
270                         generate((TreeNode) i.next());
271                     } while (i.hasNext());
272                 }
273                 break;
274
275             case TreeNode.NUMBER:
276                 buf.append(attribs.toString());
277                 break;
278
279             case TreeNode.UNICODE_CHAR:
280                 int code = ((Integer JavaDoc) attribs).intValue();
281                 buf.append((char) code);
282                 break;
283
284             case TreeNode.POSIX_SET:
285                 buf.append('\\').append('p');
286                 buf.append('{');
287                 String JavaDoc className = (String JavaDoc) attribs;
288                 if (className.equals("ascii")) { //NOI18N
289
buf.append("ASCII"); //NOI18N
290
} else if (className.equals("xdigit")) { //NOI18N
291
buf.append("XDigit"); //NOI18N
292
} else {
293                     buf.append(Character.toUpperCase(className.charAt(0)));
294                     buf.append(className.substring(1));
295                 }
296                 buf.append('}');
297                 break;
298
299             case TreeNode.REGEXP:
300                 String JavaDoc attrString = (String JavaDoc) attribs;
301                 if (attrString != null && attrString.charAt(0) == '^') {
302                     buf.append('^');
303                 }
304                 if (children != null) {
305                     generate((TreeNode) children.get(0));
306                 }
307                 if (attrString != null && (attrString.length() == 2
308                                            || attrString.charAt(0) == '$')) {
309                     buf.append('$');
310                 }
311                 break;
312
313             case TreeNode.TOKEN:
314                 String JavaDoc tokenName = (String JavaDoc) attribs;
315                 Object JavaDoc replacement = tokenReplacements != null
316                                      ? tokenReplacements.get(tokenName)
317                                      : null;
318                 if (replacement != null) {
319                     buf.append('(').append('?').append(':');
320                     buf.append(replacement.toString());
321                     buf.append(')');
322                 } else {
323                     buf.append('{').append(tokenName).append('}');
324                 }
325                 break;
326
327             default:
328                 assert false;
329                 break;
330         }
331     }
332
333 }
334
Popular Tags