001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.cnd.api.lexer;
043:
044: import java.util.Collection;
045: import java.util.EnumSet;
046: import java.util.HashMap;
047: import java.util.Map;
048: import org.netbeans.api.lexer.InputAttributes;
049: import org.netbeans.api.lexer.Language;
050: import org.netbeans.api.lexer.LanguagePath;
051: import org.netbeans.api.lexer.PartType;
052: import org.netbeans.api.lexer.Token;
053: import org.netbeans.api.lexer.TokenId;
054: import org.netbeans.modules.cnd.lexer.CppLexer;
055: import org.netbeans.modules.cnd.lexer.PreprocLexer;
056: import org.netbeans.spi.lexer.LanguageEmbedding;
057: import org.netbeans.spi.lexer.LanguageHierarchy;
058: import org.netbeans.spi.lexer.Lexer;
059: import org.netbeans.spi.lexer.LexerRestartInfo;
060:
061: /**
062: * Token ids of C/C++ languages defined as enum.
063: *
064: * @author Vladimir Voskresensky
065: * @version 1.00
066: */
067: public enum CppTokenId implements TokenId {
068:
069: // make sure token category names are the same used in the string
070: // constants below
071:
072: ERROR(null, "error"), IDENTIFIER(null, "identifier"),
073:
074: // C/C++ keywords
075: ASM("asm", "keyword-directive"), // gcc and C++
076: AUTO("auto", "keyword"), BOOL("bool", "keyword"), // C++
077: BREAK("break", "keyword-directive"), CASE("case",
078: "keyword-directive"), CATCH("catch", "keyword-directive"), //C++
079: CHAR("char", "keyword"), CLASS("class", "keyword"), //C++
080: CONST("const", "keyword"), CONST_CAST("const_cast", "keyword"), // C++
081: CONTINUE("continue", "keyword-directive"), DEFAULT("default",
082: "keyword-directive"), DELETE("delete", "keyword"), // C++
083: DO("do", "keyword-directive"), DOUBLE("double", "keyword"), DYNAMIC_CAST(
084: "dynamic_cast", "keyword"), // C++
085: ELSE("else", "keyword-directive"), ENUM("enum", "keyword"), EXPLICIT(
086: "explicit", "keyword"), // C++
087: EXPORT("export", "keyword"), // C++
088: EXTERN("extern", "keyword"), FINALLY("finally", "keyword-directive"), //C++
089: FLOAT("float", "keyword"), FOR("for", "keyword-directive"), FRIEND(
090: "friend", "keyword"), // C++
091: GOTO("goto", "keyword-directive"), IF("if", "keyword-directive"), INLINE(
092: "inline", "keyword"), // now in C also
093: INT("int", "keyword"), LONG("long", "keyword"), MUTABLE("mutable",
094: "keyword"), // C++
095: NAMESPACE("namespace", "keyword"), //C++
096: NEW("new", "keyword"), //C++
097: OPERATOR("operator", "keyword"), // C++
098: PRIVATE("private", "keyword"), //C++
099: PROTECTED("protected", "keyword"), //C++
100: PUBLIC("public", "keyword"), // C++
101: REGISTER("register", "keyword"), REINTERPRET_CAST(
102: "reinterpret_cast", "keyword"), //C++
103: RESTRICT("restrict", "keyword"), // C
104: RETURN("return", "keyword-directive"), SHORT("short", "keyword"), SIZNED(
105: "signed", "keyword"), SIZEOF("sizeof", "keyword"), STATIC(
106: "static", "keyword"), STATIC_CAST("static_cast", "keyword"), // C++
107: STRUCT("struct", "keyword"), SWITCH("switch", "keyword-directive"), TEMPLATE(
108: "template", "keyword"), //C++
109: THIS("this", "keyword"), // C++
110: THROW("throw", "keyword-directive"), //C++
111: TRY("try", "keyword-directive"), // C++
112: TYPEDEF("typedef", "keyword"), TYPEID("typeid", "keyword"), //C++
113: TYPENAME("typename", "keyword"), //C++
114: TYPEOF("typeof", "keyword"), // gcc, C++
115: UNION("union", "keyword"), UNSIGNED("unsigned", "keyword"), USING(
116: "using", "keyword"), //C++
117: VIRTUAL("virtual", "keyword"), //C++
118: VOID("void", "keyword"), VOLATILE("volatile", "keyword"), WCHAR_T(
119: "wchar_t", "keyword"), // C++
120: WHILE("while", "keyword-directive"), _BOOL("_Bool", "keyword"), // C
121: _COMPLEX("_Complex", "keyword"), // C
122: _IMAGINARY("_Imaginary", "keyword"), // C
123:
124: INT_LITERAL(null, "number"), LONG_LITERAL(null, "number"), FLOAT_LITERAL(
125: null, "number"), DOUBLE_LITERAL(null, "number"), UNSIGNED_LITERAL(
126: null, "number"), CHAR_LITERAL(null, "character"), STRING_LITERAL(
127: null, "string"),
128:
129: TRUE("true", "literal"), // C++
130: FALSE("false", "literal"), // C++
131: NULL("null", "literal"),
132:
133: LPAREN("(", "separator"), RPAREN(")", "separator"), LBRACE("{",
134: "separator"), RBRACE("}", "separator"), LBRACKET("[",
135: "separator"), RBRACKET("]", "separator"), SEMICOLON(";",
136: "separator"), COMMA(",", "separator"), DOT(".", "separator"), DOTMBR(
137: ".*", "separator"), SCOPE("::", "separator"), ARROW("->",
138: "separator"), ARROWMBR("->*", "separator"),
139:
140: EQ("=", "operator"), GT(">", "operator"), LT("<", "operator"), NOT(
141: "!", "operator"), TILDE("~", "operator"), QUESTION("?",
142: "operator"), COLON(":", "operator"), EQEQ("==", "operator"), LTEQ(
143: "<=", "operator"), GTEQ(">=", "operator"), NOTEQ("!=",
144: "operator"), AMPAMP("&&", "operator"), BARBAR("||",
145: "operator"), PLUSPLUS("++", "operator"), MINUSMINUS("--",
146: "operator"), PLUS("+", "operator"), MINUS("-", "operator"), STAR(
147: "*", "operator"), SLASH("/", "operator"), AMP("&",
148: "operator"), BAR("|", "operator"), CARET("^", "operator"), PERCENT(
149: "%", "operator"), LTLT("<<", "operator"), GTGT(">>",
150: "operator"), PLUSEQ("+=", "operator"), MINUSEQ("-=",
151: "operator"), STAREQ("*=", "operator"), SLASHEQ("/=",
152: "operator"), AMPEQ("&=", "operator"), BAREQ("|=",
153: "operator"), CARETEQ("^=", "operator"), PERCENTEQ("%=",
154: "operator"), LTLTEQ("<<=", "operator"), GTGTEQ(">>=",
155: "operator"),
156:
157: ELLIPSIS("...", "special"), AT("@", "special"), DOLLAR("$",
158: "special"), SHARP("#", "special"), DBL_SHARP("##",
159: "special"), BACK_SLASH("\\", "special"),
160:
161: WHITESPACE(null, "whitespace"), // all spaces except new line
162: ESCAPED_LINE(null, "whitespace"), // line escape with \
163: NEW_LINE(null, "whitespace"), // new line \n or \r
164: LINE_COMMENT(null, "comment"), BLOCK_COMMENT(null, "comment"), DOXYGEN_COMMENT(
165: null, "comment"),
166:
167: // Prerpocessor
168: // - on top level
169: PREPROCESSOR_DIRECTIVE(null, "preprocessor"),
170: // - tokens
171: PREPROCESSOR_START("#", "preprocessor"), PREPROCESSOR_IF("if",
172: "preprocessor-keyword-directive"), PREPROCESSOR_IFDEF(
173: "ifdef", "preprocessor-keyword-directive"), PREPROCESSOR_IFNDEF(
174: "ifndef", "preprocessor-keyword-directive"), PREPROCESSOR_ELSE(
175: "else", "preprocessor-keyword-directive"), PREPROCESSOR_ELIF(
176: "elif", "preprocessor-keyword-directive"), PREPROCESSOR_ENDIF(
177: "endif", "preprocessor-keyword-directive"), PREPROCESSOR_DEFINE(
178: "define", "preprocessor-keyword-directive"), PREPROCESSOR_UNDEF(
179: "undef", "preprocessor-keyword-directive"), PREPROCESSOR_INCLUDE(
180: "include", "preprocessor-keyword-directive"), PREPROCESSOR_INCLUDE_NEXT(
181: "include_next", "preprocessor-keyword-directive"), PREPROCESSOR_LINE(
182: "line", "preprocessor-keyword-directive"), PREPROCESSOR_IDENT(
183: "ident", "preprocessor-keyword-directive"), PREPROCESSOR_PRAGMA(
184: "pragma", "preprocessor-keyword-directive"), PREPROCESSOR_WARNING(
185: "warning", "preprocessor-keyword-directive"), PREPROCESSOR_ERROR(
186: "error", "preprocessor-keyword-directive"), PREPROCESSOR_DEFINED(
187: "defined", "preprocessor-keyword"),
188:
189: PREPROCESSOR_USER_INCLUDE(null, "preprocessor-user-include-literal"), PREPROCESSOR_SYS_INCLUDE(
190: null, "preprocessor-system-include-literal"), PREPROCESSOR_IDENTIFIER(
191: null, "preprocessor-identifier"),
192:
193: // Errors
194: INVALID_COMMENT_END("*/", "error"), FLOAT_LITERAL_INVALID(null,
195: "number");
196:
197: // make sure string names are the same used in the tokenIds above
198: public static final String WHITESPACE_CATEGORY = "whitespace"; // NOI18N
199: public static final String COMMENT_CATEGORY = "comment"; // NOI18N
200: public static final String KEYWORD_CATEGORY = "keyword"; // NOI18N
201: public static final String KEYWORD_DIRECTIVE_CATEGORY = "keyword-directive"; // NOI18N
202: public static final String ERROR_CATEGORY = "error"; // NOI18N
203: public static final String NUMBER_CATEGORY = "number"; // NOI18N
204: public static final String LITERAL_CATEGORY = "literal"; // NOI18N
205: public static final String CHAR_CATEGORY = "character"; // NOI18N
206: public static final String STRING_CATEGORY = "string"; // NOI18N
207: public static final String SEPARATOR_CATEGORY = "separator"; // NOI18N
208: public static final String OPERATOR_CATEGORY = "operator"; // NOI18N
209: public static final String SPECIAL_CATEGORY = "special"; // NOI18N
210: public static final String PREPROCESSOR_CATEGORY = "preprocessor"; // NOI18N
211: public static final String PREPROCESSOR_KEYWORD_CATEGORY = "preprocessor-keyword"; // NOI18N
212: public static final String PREPROCESSOR_KEYWORD_DIRECTIVE_CATEGORY = "preprocessor-keyword-directive"; // NOI18N
213: public static final String PREPROCESSOR_IDENTIFIER_CATEGORY = "preprocessor-identifier"; // NOI18N
214: public static final String PREPROCESSOR_USER_INCLUDE_CATEGORY = "preprocessor-user-include-literal"; // NOI18N
215: public static final String PREPROCESSOR_SYS_INCLUDE_CATEGORY = "preprocessor-system-include-literal"; // NOI18N
216:
217: private final String fixedText;
218:
219: private final String primaryCategory;
220:
221: CppTokenId(String fixedText, String primaryCategory) {
222: this .fixedText = fixedText;
223: this .primaryCategory = primaryCategory;
224: }
225:
226: public String fixedText() {
227: return fixedText;
228: }
229:
230: public String primaryCategory() {
231: return primaryCategory;
232: }
233:
234: private static final Language<CppTokenId> languageC;
235: private static final Language<CppTokenId> languageCpp;
236: private static final Language<CppTokenId> languagePreproc;
237:
238: static {
239: languageC = CppHierarchy.createCLanguage();
240: languageCpp = CppHierarchy.createCppLanguage();
241: languagePreproc = CppHierarchy.createPreprocLanguage();
242: }
243:
244: public static Language<CppTokenId> languageC() {
245: return languageC;
246: }
247:
248: public static Language<CppTokenId> languageCpp() {
249: return languageCpp;
250: }
251:
252: public static Language<CppTokenId> languagePreproc() {
253: return languagePreproc;
254: }
255:
256: private static final class CppHierarchy extends
257: LanguageHierarchy<CppTokenId> {
258: private final boolean cpp;
259: private final boolean preproc;
260:
261: private CppHierarchy(boolean cpp, boolean preproc) {
262: this .cpp = cpp;
263: this .preproc = preproc;
264: }
265:
266: private static Language<CppTokenId> createCppLanguage() {
267: return new CppHierarchy(true, false).language();
268: }
269:
270: private static Language<CppTokenId> createCLanguage() {
271: return new CppHierarchy(false, false).language();
272: }
273:
274: private static Language<CppTokenId> createPreprocLanguage() {
275: return new CppHierarchy(false/*meaning less*/, true)
276: .language();
277: }
278:
279: @Override
280: protected String mimeType() {
281: if (this .preproc) {
282: return CndLexerUtilities.PREPROC_MIME_TYPE;
283: } else {
284: return this .cpp ? CndLexerUtilities.CPLUSPLUS_MIME_TYPE
285: : CndLexerUtilities.C_MIME_TYPE;
286: }
287: }
288:
289: @Override
290: protected Collection<CppTokenId> createTokenIds() {
291: return EnumSet.allOf(CppTokenId.class);
292: }
293:
294: @Override
295: protected Map<String, Collection<CppTokenId>> createTokenCategories() {
296: Map<String, Collection<CppTokenId>> cats = new HashMap<String, Collection<CppTokenId>>();
297: // Additional literals being a lexical error
298: cats.put(ERROR_CATEGORY, EnumSet
299: .of(CppTokenId.FLOAT_LITERAL_INVALID));
300: // Literals category
301: EnumSet<CppTokenId> l = EnumSet.of(CppTokenId.INT_LITERAL,
302: CppTokenId.LONG_LITERAL, CppTokenId.FLOAT_LITERAL,
303: CppTokenId.DOUBLE_LITERAL,
304: CppTokenId.UNSIGNED_LITERAL,
305: CppTokenId.CHAR_LITERAL, CppTokenId.STRING_LITERAL);
306: cats.put(LITERAL_CATEGORY, l);
307:
308: // Preprocessor category
309: // EnumSet<CppTokenId> p = EnumSet.of(
310: // CppTokenId.PREPROCESSOR_DEFINE,
311: // CppTokenId.PREPROCESSOR_DEFINED,
312: // CppTokenId.PREPROCESSOR_DIRECTIVE,
313: // CppTokenId.LONG_LITERAL,
314: // CppTokenId.FLOAT_LITERAL,
315: // CppTokenId.DOUBLE_LITERAL,
316: // CppTokenId.UNSIGNED_LITERAL,
317: // CppTokenId.CHAR_LITERAL,
318: // CppTokenId.STRING_LITERAL
319: // );
320: // cats.put("preprocessor", p);
321: return cats;
322: }
323:
324: @Override
325: protected Lexer<CppTokenId> createLexer(
326: LexerRestartInfo<CppTokenId> info) {
327: if (this .preproc) {
328: return new PreprocLexer(CndLexerUtilities
329: .getDefatultFilter(true), info);
330: } else {
331: return new CppLexer(CndLexerUtilities
332: .getDefatultFilter(this .cpp), info);
333: }
334: }
335:
336: @Override
337: protected LanguageEmbedding<?> embedding(
338: Token<CppTokenId> token, LanguagePath languagePath,
339: InputAttributes inputAttributes) {
340: // Test language embedding in the block comment and string literal
341: switch (token.id()) {
342: case DOXYGEN_COMMENT:
343: return LanguageEmbedding
344: .create(DoxygenTokenId.language(), 3, (token
345: .partType() == PartType.COMPLETE) ? 2
346: : 0);
347: case STRING_LITERAL:
348: return LanguageEmbedding
349: .create(
350: CppStringTokenId.languageDouble(),
351: 1,
352: (token.partType() == PartType.COMPLETE) ? 1
353: : 0);
354: case CHAR_LITERAL:
355: return LanguageEmbedding
356: .create(
357: CppStringTokenId.languageSingle(),
358: 1,
359: (token.partType() == PartType.COMPLETE) ? 1
360: : 0);
361: case PREPROCESSOR_DIRECTIVE:
362: return LanguageEmbedding.create(languagePreproc, 0, 0);
363: }
364: return null; // No embedding
365: }
366: }
367: }
|