KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > lexer > gen > LanguageGenerator


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.lexer.gen;
21
22 import java.lang.reflect.Field JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.List JavaDoc;
30
31 import org.netbeans.api.lexer.TokenId;
32 import org.netbeans.spi.lexer.util.LexerUtilities;
33 import java.util.Iterator JavaDoc;
34 import org.netbeans.modules.lexer.gen.util.LexerGenUtilities;
35
36 /**
37  * Generates Language class source by using xml file
38  * with the language description. Descendants of this class
39  * typically read some portion of the information
40  * (e.g. integer token identifications) from the classes
41  * generated by particular lexer.
42  *
43  * @author Miloslav Metelka
44  * @version 1.00
45  */

46
47 public class LanguageGenerator {
48     
49     /** Map containing collected imports */
50     private Map JavaDoc imports;
51
52     public LanguageGenerator() {
53         this.imports = new HashMap JavaDoc();
54     }
55
56     public String JavaDoc createSource(LanguageData data) {
57         // Check consistency of language data
58
data.check();
59
60         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
61         
62         // Class header
63
appendClassDeclaration(sb, data);
64         
65         // Class start
66
appendClassStart(sb, data);
67
68         addToImports("org.netbeans.api.lexer.TokenId");
69
70         // TokenId intIds declarations
71
for (Iterator JavaDoc idsIterator = data.getSortedIds(
72             LanguageData.IDS_INT_ID_COMPARATOR).iterator();
73             idsIterator.hasNext();
74         ) {
75             MutableTokenId id = (MutableTokenId)idsIterator.next();
76             LexerGenUtilities.appendSpaces(sb, 4);
77             sb.append("public static final int ");
78             sb.append(id.getIntIdFieldName());
79             sb.append(" = ");
80             sb.append(id.getIntId());
81             sb.append(";\n");
82         }
83         
84         sb.append("\n\n");
85         
86         
87         for (Iterator JavaDoc idsIterator = data.getSortedIds(
88             LanguageData.IDS_FIELD_NAME_COMPARATOR).iterator();
89             idsIterator.hasNext();
90         ) {
91             MutableTokenId id = (MutableTokenId)idsIterator.next();
92             LexerGenUtilities.appendSpaces(sb, 4);
93             sb.append("public static final TokenId ");
94             sb.append(id.getFieldName());
95             sb.append(" = new TokenId(\"");
96             LexerUtilities.appendToSource(sb, id.getName());
97             sb.append("\", ");
98             sb.append(id.getIntIdFieldName());
99          
100             // Append categories
101
List JavaDoc catList = id.getCategoryNames();
102             int catCnt = catList.size();
103             if (catCnt > 0) {
104                 sb.append(", new String[]{\"");
105                 for (int j = 0; j < catCnt; j++) {
106                     if (j > 0) {
107                         sb.append(", \"");
108                     }
109                     LexerUtilities.appendToSource(sb, (String JavaDoc)catList.get(j));
110                     sb.append('"');
111                 }
112                 sb.append('}');
113             }
114             
115             // Append texts
116
List JavaDoc sampleTexts = id.getSampleTexts();
117             int sampleTextsLength = sampleTexts.size();
118             if (sampleTextsLength > 0) {
119                 if (catCnt == 0) { // need to appen null instead of cats
120
sb.append(", null");
121                 }
122
123                 addToImports("org.netbeans.spi.lexer.MatcherFactory");
124                 sb.append(", MatcherFactory.create");
125                 String JavaDoc sampleTextCheck = id.getSampleTextCheck();
126                 if (sampleTextsLength == 1) { // exactly one sample text
127
if ("none".equals(sampleTextCheck)) {
128                         sb.append("NoCheckMatcher");
129                     } else if ("length".equals(sampleTextCheck)) {
130                         sb.append("LengthCheckMatcher");
131                     } else {
132                         sb.append("TextCheckMatcher");
133                     }
134                     
135                     sb.append("(\"");
136                     LexerUtilities.appendToSource(sb, (String JavaDoc)sampleTexts.get(0));
137                     sb.append('"');
138                     
139                 } else { // more than one sample text
140
sb.append("MultiMatcher(new String[] {");
141                     
142                     for (Iterator JavaDoc it = sampleTexts.iterator(); it.hasNext();) {
143                         sb.append('"');
144                         LexerUtilities.appendToSource(sb, (String JavaDoc)it.next());
145                         sb.append('"');
146                         if (it.hasNext()) {
147                             sb.append(", ");
148                         }
149                     }
150                     sb.append("}");
151                 }
152                 sb.append(")");
153
154             }
155             
156             sb.append(");");
157             
158             String JavaDoc comment = id.getComment();
159             if (comment != null) {
160                 sb.append(" // ");
161                 sb.append(comment);
162             }
163             
164             sb.append('\n');
165         }
166         
167         // Constructor
168
sb.append('\n');
169         appendClassConstructor(sb, data);
170         
171         // Lexer creation
172
LexerGenUtilities.appendSpaces(sb, 4);
173         sb.append("public ");
174         sb.append(addToImports("org.netbeans.api.lexer.Lexer"));
175         sb.append(" createLexer() {\n");
176         
177         appendLexerMethodBody(sb, data);
178         LexerGenUtilities.appendSpaces(sb, 4);
179         sb.append("}\n");
180         
181         // Class end
182
appendClassEnd(sb, data);
183         
184         sb.append("\n}\n");
185
186
187         // Now header containing package stmt and imports is generated
188
StringBuffer JavaDoc hsb = new StringBuffer JavaDoc();
189         // [PENDING] ? License
190
// Possible package stmt
191
String JavaDoc langClassPkgName = getLanguageClassPkgName(data);
192         if (!"".equals(langClassPkgName)) {
193             hsb.append("\npackage ").append(langClassPkgName).append(";\n");
194         }
195             
196         // Add imports
197
hsb.append('\n');
198         appendImports(hsb, data);
199         hsb.append('\n');
200
201         // Insert package and imports to begining of the generated class
202
sb.insert(0, hsb.toString());
203
204         return sb.toString();
205     }
206     
207     private String JavaDoc getLanguageClassNameWithoutPkg(LanguageData data) {
208         return addToImports(data.getLanguageClassName());
209     }
210
211     private String JavaDoc getLanguageClassPkgName(LanguageData data) {
212         return LexerGenUtilities.splitClassName(data.getLanguageClassName())[0];
213     }
214
215     protected void appendClassDeclaration(StringBuffer JavaDoc sb, LanguageData data) {
216         sb.append("public class ");
217         sb.append(getLanguageClassNameWithoutPkg(data));
218         sb.append(" extends ");
219         sb.append(addToImports("org.netbeans.spi.lexer.AbstractLanguage"));
220         sb.append(" {\n\n");
221     }
222
223     protected void appendClassStart(StringBuffer JavaDoc sb, LanguageData data) {
224
225         // Append static get() method
226
String JavaDoc langClassNameWithoutPkg = getLanguageClassNameWithoutPkg(data);
227         LexerGenUtilities.appendSpaces(sb, 4);
228         sb.append("/** Lazily initialized singleton instance of this language. */\n");
229         LexerGenUtilities.appendSpaces(sb, 4);
230         sb.append("private static ").append(langClassNameWithoutPkg);
231         sb.append(" INSTANCE;\n\n");
232         LexerGenUtilities.appendSpaces(sb, 4);
233         sb.append("/** @return singleton instance of this language. */\n");
234         LexerGenUtilities.appendSpaces(sb, 4);
235         sb.append("public static synchronized ").append(langClassNameWithoutPkg);
236         sb.append(" get() {\n");
237         LexerGenUtilities.appendSpaces(sb, 8);
238         sb.append("if (INSTANCE == null)\n");
239         LexerGenUtilities.appendSpaces(sb, 12);
240         sb.append("INSTANCE = new ").append(langClassNameWithoutPkg);
241         sb.append("();\n\n");
242         LexerGenUtilities.appendSpaces(sb, 8);
243         sb.append("return INSTANCE;\n");
244         LexerGenUtilities.appendSpaces(sb, 4);
245         sb.append("}\n\n");
246     }
247     
248     protected void appendClassConstructor(StringBuffer JavaDoc sb, LanguageData data) {
249         LexerGenUtilities.appendSpaces(sb, 4);
250         sb.append(getLanguageClassNameWithoutPkg(data));
251         sb.append("() {\n");
252         LexerGenUtilities.appendSpaces(sb, 4);
253         sb.append("}\n\n");
254     }
255
256     protected void appendClassEnd(StringBuffer JavaDoc sb, LanguageData data) {
257     }
258     
259     protected void appendLexerMethodBody(StringBuffer JavaDoc sb, LanguageData data) {
260         String JavaDoc lexerClassName = data.getLexerClassName();
261         addToImports(lexerClassName);
262         LexerGenUtilities.appendSpaces(sb, 8);
263         sb.append("return new ");
264         sb.append(addToImports(lexerClassName));
265         sb.append("();\n");
266     }
267     
268     /**
269      * Add the class to imports section. This method can be used
270      * anytime even during the class source generation
271      * because the imports are added to the generated source
272      * at the end of the whole process.
273      * @param className full name of the class including package name.
274      * @return the short name of the class name (without package).
275      */

276     protected final String JavaDoc addToImports(String JavaDoc className) {
277         String JavaDoc[] pkgCls = (String JavaDoc[])imports.get(className);
278         if (pkgCls == null) {
279             pkgCls = LexerGenUtilities.splitClassName(className);
280             imports.put(className, pkgCls);
281         }
282         return pkgCls[1];
283     }
284
285     private void appendImports(StringBuffer JavaDoc sb, LanguageData data) {
286         String JavaDoc langClassPkgName = getLanguageClassPkgName(data);
287         Set JavaDoc iSet = imports.keySet();
288         String JavaDoc[] importClasses = new String JavaDoc[iSet.size()];
289         iSet.toArray(importClasses);
290         Arrays.sort(importClasses);
291         for (int i = 0; i < importClasses.length; i++) {
292             String JavaDoc className = importClasses[i];
293             String JavaDoc[] pkgCls = (String JavaDoc[])imports.get(className);
294             if (!"".equals(pkgCls[0]) && !"java.lang".equals(pkgCls[0])
295                 && !pkgCls[0].equals(langClassPkgName) // differs from package stmt
296
) {
297                 sb.append("import ").append(className).append(";\n");
298             }
299         }
300     }
301     
302 }
303
304
Popular Tags