KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.List JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Comparator JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.Map JavaDoc;
29 import org.netbeans.spi.lexer.util.LexerUtilities;
30 import org.netbeans.modules.lexer.gen.util.LexerGenUtilities;
31
32 /**
33  * Information about the language necessary for generating
34  * language class source. It's obtained by parsing a XML description
35  * and it can optionally be modified.
36  * <BR>There is also possibility to generate xml description
37  * describing the token ids. The generated description
38  * can then be edited and extended by e.g. adding sample text(s)
39  * or assigning token ids into token categories.
40  * The language xml description then serves
41  * as a source of extended information for the generation of the language.
42  *
43  * @author Miloslav Metelka
44  * @version 1.00
45  */

46
47 public class LanguageData {
48     
49     public static final Comparator JavaDoc IDS_FIELD_NAME_COMPARATOR = new IdsFieldNameComparator();
50     
51     public static final Comparator JavaDoc IDS_INT_ID_COMPARATOR = new IdsIntIdComparator();
52     
53     private TokenTypes tokenTypes;
54     
55     private String JavaDoc languageClassName;
56     
57     private String JavaDoc lexerClassName;
58     
59     private List JavaDoc ids;
60     
61     private List JavaDoc unmodifiableIds;
62     
63     private int uniqueIntId;
64     
65     public LanguageData() {
66         /* Start with 1 to ensure the 0 is free
67          * for yacc-like tools that use 0 for EOF.
68          */

69         uniqueIntId = 1;
70         ids = new ArrayList JavaDoc();
71         unmodifiableIds = Collections.unmodifiableList(ids);
72     }
73     
74     /**
75      * Get the token-types registered with this language data.
76      */

77     public final TokenTypes getTokenTypes() {
78         return tokenTypes;
79     }
80     
81     /**
82      * Register the token-types into this language data
83      * and apply them to this language data.
84      */

85     public void registerTokenTypes(TokenTypes tokenTypes) {
86         this.tokenTypes = tokenTypes;
87         
88         // Let the token types update this data
89
tokenTypes.updateData(this);
90     }
91
92     /**
93      * @return class name of the generated language class without package.
94      */

95     public String JavaDoc getLanguageClassName() {
96         return languageClassName;
97     }
98     
99     public void setLanguageClassName(String JavaDoc languageClassName) {
100         this.languageClassName = languageClassName;
101     }
102
103     /**
104      * @return full classname of the generated lexer class (including package).
105      */

106     public String JavaDoc getLexerClassName() {
107         return lexerClassName;
108     }
109     
110     public void setLexerClassName(String JavaDoc lexerClassName) {
111         this.lexerClassName = lexerClassName;
112     }
113     
114     /**
115      * @return unmodifiable list of tokenIds planned to be generated.
116      * To create a new mutable tokenId the {@link #newId(String)}
117      * can be used.
118      */

119     public List JavaDoc getIds() {
120         return unmodifiableIds;
121     }
122     
123     /**
124      * Get copy of ids list sorted by a specified comparator.
125      * @param c comparator to be used. {@link #IDS_FIELD_NAME_COMPARATOR}
126      * or {@link #IDS_INT_ID_COMPARATOR} can be used among others.
127      * @return copy of ids list sorted by a specified comparator.
128      */

129     public List JavaDoc getSortedIds(Comparator JavaDoc c) {
130         List JavaDoc idsCopy = new ArrayList JavaDoc(ids);
131         Collections.sort(idsCopy, c);
132         return idsCopy;
133     }
134
135     /**
136      * Create new mutable token id and add it to the list of the current ids.
137      * @return created and added mutable token id.
138      */

139     public MutableTokenId newId(String JavaDoc name) {
140         if (findId(name) != null) {
141             throw new IllegalArgumentException JavaDoc("Id named " + name + " already exists.");
142         }
143
144         MutableTokenId id = createId(name);
145         ids.add(id);
146         
147         return id;
148     }
149     
150     /**
151      * Remove the given id from the list of the token ids.
152      */

153     public void remove(MutableTokenId id) {
154         for (Iterator JavaDoc it = ids.iterator(); it.hasNext();) {
155             if (id == it.next()) {
156                 it.remove();
157                 return;
158             }
159         }
160         throw new IllegalArgumentException JavaDoc("id=" + id + " not found");
161     }
162
163     /**
164      * Find the mutable tokenId with the given name.
165      * @return mutable token id with the given name.
166      */

167     public MutableTokenId findId(String JavaDoc name) {
168         for (Iterator JavaDoc it = getIds().iterator(); it.hasNext();) {
169             MutableTokenId id = (MutableTokenId)it.next();
170             if (name.equals(id.getName())) {
171                 return id;
172             }
173         }
174         return null;
175     }
176     
177     /**
178      * Find the mutable tokenId by its integer identification.
179      * @param intId integer identification of the tokenId.
180      * @return mutable tokenId with given integer identification.
181      */

182     public MutableTokenId findId(int intId) {
183         List JavaDoc ids = getIds();
184         int cnt = ids.size();
185         for (int i = 0; i < cnt; i++) {
186             MutableTokenId id = (MutableTokenId)ids.get(i);
187             if (id.getIntId() == intId) {
188                 return id;
189             }
190         }
191         return null;
192     }
193
194     /**
195      * Find the mutable tokenId by its token type name returned
196      * by {@link MutableTokenId#getTokenTypeName()}.
197      * @param tokenTypeName name of the field in the token-types class.
198      * @return mutable tokenId with the given tokenTypeName.
199      */

200     public MutableTokenId findIdByTokenTypeName(String JavaDoc tokenTypeName) {
201         List JavaDoc ids = getIds();
202         int cnt = ids.size();
203         for (int i = 0; i < cnt; i++) {
204             MutableTokenId id = (MutableTokenId)ids.get(i);
205             if (tokenTypeName.equals(id.getTokenTypeName())) {
206                 return id;
207             }
208         }
209         return null;
210     }
211
212     /**
213      * @return maximum intId among all the tokenIds.
214      * <BR><B>Note:</B>It's necessary that all the tokenIds
215      * have the non-numeric tokenIds resolved to numbers
216      * prior invocation of this method.<B>
217      * The {@link #findNonNumericIntIds()} can be used to find those.
218      * The non-numeric intIds are silently ignored by the method.
219      */

220     public int findMaxIntId() {
221         List JavaDoc ids = getIds();
222         int cnt = ids.size();
223         int maxIntId = 0;
224         for (int i = 0; i < cnt; i++) {
225             MutableTokenId id = (MutableTokenId)ids.get(i);
226             maxIntId = Math.max(maxIntId, id.getIntId());
227         }
228             
229         return maxIntId;
230     }
231
232     /**
233      * @return unique intId not yet used for other intIds.
234      */

235     public int uniqueIntId() {
236         return uniqueIntId++;
237     }
238     
239     /**
240      * Skip the given intId (and all intIds that are lower than it)
241      * so they will not be returned by {@link #uniqueIntId()}.
242      * @param intId id to skip.
243      */

244     public void skipIntId(int intId) {
245         uniqueIntId = Math.max(uniqueIntId, ++intId);
246     }
247
248     /**
249      * @return newly created mutable tokenId instance.
250      * <BR>Subclasses may override this method to return
251      * subclass of {@link MutableTokenId).
252      */

253     protected MutableTokenId createId(String JavaDoc name) {
254         return new MutableTokenId(this, name);
255     }
256
257     /**
258      * Generate unique intIds for the tokenIds that have
259      * intId set to implicit value -1.
260      * <BR>The {@link #uniqueIntId()} is used to obtain
261      * the intIds.
262      */

263     public void updateUnassignedIntIds() {
264         for (Iterator JavaDoc it = getIds().iterator(); it.hasNext();) {
265             MutableTokenId id = (MutableTokenId)it.next();
266             if (id.getIntId() == -1) {
267                 id.assignUniqueIntId();
268             }
269         }
270     }
271     
272     /**
273      * Check whether this language data object is in a consistent state.
274      * The test includes checking for duplicate intIds.
275      */

276     public void check() {
277         Map JavaDoc info = new HashMap JavaDoc();
278         
279         for (Iterator JavaDoc it = getIds().iterator(); it.hasNext();) {
280             MutableTokenId id = (MutableTokenId)it.next();
281             int intId = id.getIntId();
282             if (intId < 0) {
283                 throw new IllegalStateException JavaDoc(
284                     "Id " + id.getName()
285                     + " has invalid intId=" + intId
286                     + "\nLanguage data dump follows:\n"
287                     + toString()
288
289                 );
290             }
291             
292             MutableTokenId dupIntId = (MutableTokenId)info.put(new Integer JavaDoc(intId), id);
293             if (dupIntId != null) {
294                 throw new IllegalStateException JavaDoc("Ids " + id.getName()
295                     + " and " + dupIntId.getName()
296                     + " have the same intId=" + intId
297                     + "\nLanguage data dump follows:\n"
298                     + toString());
299             }
300         }
301     }
302     
303     public String JavaDoc toString() {
304         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
305         List JavaDoc mtids = getIds();
306         int mtidsCount = mtids.size();
307         for (int i = 0; i < mtidsCount; i++) {
308             sb.append(mtids.get(i));
309             sb.append('\n');
310         }
311         
312         return sb.toString();
313     }
314         
315     
316     /**
317      * Produce textual xml description for the integer token constants fields
318      * found in the token constants class file.
319      * <BR>This description can be used as a skeleton for the future
320      * xml description file.
321      */

322     public String JavaDoc createDescription() {
323
324         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
325         appendDescriptionStart(sb);
326         
327         for (Iterator JavaDoc idsIterator = getIds().iterator();
328              idsIterator.hasNext();) {
329
330             MutableTokenId id = (MutableTokenId)idsIterator.next();
331             String JavaDoc idName = id.getName();
332             if (idName != null) {
333                 LexerGenUtilities.appendSpaces(sb, 4);
334                 sb.append("<TokenId name=\"");
335                 sb.append(LexerGenUtilities.idToLowerCase(idName));
336                 sb.append("\">\n");
337                 LexerGenUtilities.appendSpaces(sb, 4);
338                 sb.append("</TokenId>\n");
339             }
340         }
341
342         appendDescriptionEnd(sb);
343
344         return sb.toString();
345     }
346
347     protected void appendDescriptionStart(StringBuffer JavaDoc sb) {
348         sb.append("<?xml version=\"1.0\"?>\n");
349         sb.append("<!DOCTYPE Language SYSTEM ");
350         sb.append("\"???/src/org/netbeans/lexer/language.dtd\">\n");
351         sb.append("<Language>\n");
352     }
353
354     protected void appendDescriptionEnd(StringBuffer JavaDoc sb) {
355         sb.append("</Language>\n");
356     }
357
358     private static final class IdsFieldNameComparator implements Comparator JavaDoc {
359         
360         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
361             MutableTokenId id1 = (MutableTokenId)o1;
362             MutableTokenId id2 = (MutableTokenId)o2;
363             return id1.getFieldName().compareTo(id2.getFieldName());
364         }
365
366     }
367     
368     private static final class IdsIntIdComparator implements Comparator JavaDoc {
369         
370         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
371             MutableTokenId id1 = (MutableTokenId)o1;
372             MutableTokenId id2 = (MutableTokenId)o2;
373             return id1.getIntId() - id2.getIntId();
374         }
375
376     }
377     
378 }
379
380
Popular Tags