001: package net.xoetrope.builder.editor.syntaxhighlight;
002:
003: /*
004: * CTokenMarker.java - C token marker
005: * Copyright (C) 1998, 1999 Slava Pestov
006: *
007: * You may use and modify this package for any purpose. Redistribution is
008: * permitted, in both source and binary form, provided that this notice
009: * remains intact in all source distributions of this package.
010: */
011:
012: import javax.swing.text.Segment;
013:
014: /**
015: * C token marker.
016: *
017: * @author Slava Pestov
018: * @version $Id: CTokenMarker.java,v 1.22 2005/01/05 17:20:48 luano Exp $
019: */
020: public class CTokenMarker extends TokenMarker {
021: public CTokenMarker() {
022: this (true, getKeywords());
023: }
024:
025: public CTokenMarker(boolean cpp, KeywordMap keywords) {
026: this .cpp = cpp;
027: this .keywords = keywords;
028: }
029:
030: public byte markTokensImpl(byte token, Segment line, int lineIndex) {
031: char[] array = line.array;
032: int offset = line.offset;
033: lastOffset = offset;
034: lastKeyword = offset;
035: int length = line.count + offset;
036: boolean backslash = false;
037:
038: loop: for (int i = offset; i < length; i++) {
039: int i1 = (i + 1);
040:
041: char c = array[i];
042: if (c == '\\') {
043: backslash = !backslash;
044: continue;
045: }
046:
047: switch (token) {
048: case Token.NULL:
049: switch (c) {
050: case '#':
051: if (backslash)
052: backslash = false;
053: else if (cpp) {
054: if (doKeyword(line, i, c))
055: break;
056: addToken(i - lastOffset, token);
057: addToken(length - i, Token.KEYWORD2);
058: lastOffset = lastKeyword = length;
059: break loop;
060: }
061: break;
062: case '"':
063: doKeyword(line, i, c);
064: if (backslash)
065: backslash = false;
066: else {
067: addToken(i - lastOffset, token);
068: token = Token.LITERAL1;
069: lastOffset = lastKeyword = i;
070: }
071: break;
072: case '\'':
073: doKeyword(line, i, c);
074: if (backslash)
075: backslash = false;
076: else {
077: addToken(i - lastOffset, token);
078: token = Token.LITERAL2;
079: lastOffset = lastKeyword = i;
080: }
081: break;
082: case ':':
083: if (lastKeyword == offset) {
084: if (doKeyword(line, i, c))
085: break;
086: backslash = false;
087: addToken(i1 - lastOffset, Token.LABEL);
088: lastOffset = lastKeyword = i1;
089: } else if (doKeyword(line, i, c))
090: break;
091: break;
092: case '/':
093: backslash = false;
094: doKeyword(line, i, c);
095: if (length - i > 1) {
096: switch (array[i1]) {
097: case '*':
098: addToken(i - lastOffset, token);
099: lastOffset = lastKeyword = i;
100: if (length - i > 2 && array[i + 2] == '*')
101: token = Token.COMMENT2;
102: else
103: token = Token.COMMENT1;
104: break;
105: case '/':
106: addToken(i - lastOffset, token);
107: addToken(length - i, Token.COMMENT1);
108: lastOffset = lastKeyword = length;
109: break loop;
110: }
111: }
112: break;
113: default:
114: backslash = false;
115: if (!Character.isLetterOrDigit(c) && c != '_')
116: doKeyword(line, i, c);
117: break;
118: }
119: break;
120: case Token.COMMENT1:
121: case Token.COMMENT2:
122: backslash = false;
123: if (c == '*' && length - i > 1) {
124: if (array[i1] == '/') {
125: i++;
126: addToken((i + 1) - lastOffset, token);
127: token = Token.NULL;
128: lastOffset = lastKeyword = i + 1;
129: }
130: }
131: break;
132: case Token.LITERAL1:
133: if (backslash)
134: backslash = false;
135: else if (c == '"') {
136: addToken(i1 - lastOffset, token);
137: token = Token.NULL;
138: lastOffset = lastKeyword = i1;
139: }
140: break;
141: case Token.LITERAL2:
142: if (backslash)
143: backslash = false;
144: else if (c == '\'') {
145: addToken(i1 - lastOffset, Token.LITERAL1);
146: token = Token.NULL;
147: lastOffset = lastKeyword = i1;
148: }
149: break;
150: default:
151: throw new InternalError("Invalid state: " + token);
152: }
153: }
154:
155: if (token == Token.NULL)
156: doKeyword(line, length, '\0');
157:
158: switch (token) {
159: case Token.LITERAL1:
160: case Token.LITERAL2:
161: addToken(length - lastOffset, Token.INVALID);
162: token = Token.NULL;
163: break;
164: case Token.KEYWORD2:
165: addToken(length - lastOffset, token);
166: if (!backslash)
167: token = Token.NULL;
168: default:
169: addToken(length - lastOffset, token);
170: break;
171: }
172:
173: return token;
174: }
175:
176: public static KeywordMap getKeywords() {
177: if (cKeywords == null) {
178: cKeywords = new KeywordMap(false);
179: cKeywords.add("char", Token.KEYWORD3);
180: cKeywords.add("double", Token.KEYWORD3);
181: cKeywords.add("enum", Token.KEYWORD3);
182: cKeywords.add("float", Token.KEYWORD3);
183: cKeywords.add("int", Token.KEYWORD3);
184: cKeywords.add("long", Token.KEYWORD3);
185: cKeywords.add("short", Token.KEYWORD3);
186: cKeywords.add("signed", Token.KEYWORD3);
187: cKeywords.add("struct", Token.KEYWORD3);
188: cKeywords.add("typedef", Token.KEYWORD3);
189: cKeywords.add("union", Token.KEYWORD3);
190: cKeywords.add("unsigned", Token.KEYWORD3);
191: cKeywords.add("void", Token.KEYWORD3);
192: cKeywords.add("auto", Token.KEYWORD1);
193: cKeywords.add("const", Token.KEYWORD1);
194: cKeywords.add("extern", Token.KEYWORD1);
195: cKeywords.add("register", Token.KEYWORD1);
196: cKeywords.add("static", Token.KEYWORD1);
197: cKeywords.add("volatile", Token.KEYWORD1);
198: cKeywords.add("break", Token.KEYWORD1);
199: cKeywords.add("case", Token.KEYWORD1);
200: cKeywords.add("continue", Token.KEYWORD1);
201: cKeywords.add("default", Token.KEYWORD1);
202: cKeywords.add("do", Token.KEYWORD1);
203: cKeywords.add("else", Token.KEYWORD1);
204: cKeywords.add("for", Token.KEYWORD1);
205: cKeywords.add("goto", Token.KEYWORD1);
206: cKeywords.add("if", Token.KEYWORD1);
207: cKeywords.add("return", Token.KEYWORD1);
208: cKeywords.add("sizeof", Token.KEYWORD1);
209: cKeywords.add("switch", Token.KEYWORD1);
210: cKeywords.add("while", Token.KEYWORD1);
211: cKeywords.add("asm", Token.KEYWORD2);
212: cKeywords.add("asmlinkage", Token.KEYWORD2);
213: cKeywords.add("far", Token.KEYWORD2);
214: cKeywords.add("huge", Token.KEYWORD2);
215: cKeywords.add("inline", Token.KEYWORD2);
216: cKeywords.add("near", Token.KEYWORD2);
217: cKeywords.add("pascal", Token.KEYWORD2);
218: cKeywords.add("true", Token.LITERAL2);
219: cKeywords.add("false", Token.LITERAL2);
220: cKeywords.add("NULL", Token.LITERAL2);
221: }
222: return cKeywords;
223: }
224:
225: // private members
226: private static KeywordMap cKeywords;
227:
228: private boolean cpp;
229: private KeywordMap keywords;
230: private int lastOffset;
231: private int lastKeyword;
232:
233: private boolean doKeyword(Segment line, int i, char c) {
234: int i1 = i + 1;
235:
236: int len = i - lastKeyword;
237: byte id = keywords.lookup(line, lastKeyword, len);
238: if (id != Token.NULL) {
239: if (lastKeyword != lastOffset)
240: addToken(lastKeyword - lastOffset, Token.NULL);
241: addToken(len, id);
242: lastOffset = i;
243: }
244: lastKeyword = i1;
245: return false;
246: }
247: }
|