001: /*
002: * Copyright (C) 2005 - 2008 JasperSoft Corporation. All rights reserved.
003: * http://www.jaspersoft.com.
004: *
005: * Unless you have purchased a commercial license agreement from JasperSoft,
006: * the following license terms apply:
007: *
008: * This program is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU General Public License version 2 as published by
010: * the Free Software Foundation.
011: *
012: * This program is distributed WITHOUT ANY WARRANTY; and without the
013: * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
014: * See the GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, see http://www.gnu.org/licenses/gpl.txt
018: * or write to:
019: *
020: * Free Software Foundation, Inc.,
021: * 59 Temple Place - Suite 330,
022: * Boston, MA USA 02111-1307
023: *
024: *
025: *
026: *
027: * CTokenMarker.java
028: *
029: */
030:
031: package org.syntax.jedit.tokenmarker;
032:
033: import org.syntax.jedit.*;
034: import javax.swing.text.Segment;
035:
036: /**
037: * C token marker.
038: *
039: * @author Slava Pestov
040: * @version $Id: CTokenMarker.java 1167 2008-01-15 18:49:05Z gtoffoli $
041: */
042: public class CTokenMarker extends TokenMarker {
043: public CTokenMarker() {
044: this (true, getKeywords());
045: }
046:
047: public CTokenMarker(boolean cpp, KeywordMap keywords) {
048: this .cpp = cpp;
049: this .keywords = keywords;
050: }
051:
052: public byte markTokensImpl(byte token, Segment line, int lineIndex) {
053: char[] array = line.array;
054: int offset = line.offset;
055: lastOffset = offset;
056: lastKeyword = offset;
057: int length = line.count + offset;
058: boolean backslash = false;
059:
060: loop: for (int i = offset; i < length; i++) {
061: int i1 = (i + 1);
062:
063: char c = array[i];
064: if (c == '\\') {
065: backslash = !backslash;
066: continue;
067: }
068:
069: switch (token) {
070: case Token.NULL:
071: switch (c) {
072: case '#':
073: if (backslash)
074: backslash = false;
075: else if (cpp) {
076: if (doKeyword(line, i, c))
077: break;
078: addToken(i - lastOffset, token);
079: addToken(length - i, Token.KEYWORD2);
080: lastOffset = lastKeyword = length;
081: break loop;
082: }
083: break;
084: case '"':
085: doKeyword(line, i, c);
086: if (backslash)
087: backslash = false;
088: else {
089: addToken(i - lastOffset, token);
090: token = Token.LITERAL1;
091: lastOffset = lastKeyword = i;
092: }
093: break;
094: case '$':
095: backslash = false;
096: doKeyword(line, i, c);
097: if (length - i > 2
098: && (array[i1] == 'P' || array[i1] == 'F'
099: || array[i1] == 'V' || array[i1] == 'R')
100: && array[i + 2] == '{') {
101: addToken(i - lastOffset, token);
102: lastOffset = lastKeyword = i;
103: token = Token.PARAMETER;
104: }
105: break;
106: case '\'':
107: doKeyword(line, i, c);
108: if (backslash)
109: backslash = false;
110: else {
111: addToken(i - lastOffset, token);
112: token = Token.LITERAL2;
113: lastOffset = lastKeyword = i;
114: }
115: break;
116: case ':':
117: if (lastKeyword == offset) {
118: if (doKeyword(line, i, c))
119: break;
120: backslash = false;
121: addToken(i1 - lastOffset, Token.LABEL);
122: lastOffset = lastKeyword = i1;
123: } else if (doKeyword(line, i, c))
124: break;
125: break;
126: case '/':
127: backslash = false;
128: doKeyword(line, i, c);
129: if (length - i > 1) {
130: switch (array[i1]) {
131: case '*':
132: addToken(i - lastOffset, token);
133: lastOffset = lastKeyword = i;
134: if (length - i > 2 && array[i + 2] == '*')
135: token = Token.COMMENT2;
136: else
137: token = Token.COMMENT1;
138: break;
139: case '/':
140: addToken(i - lastOffset, token);
141: addToken(length - i, Token.COMMENT1);
142: lastOffset = lastKeyword = length;
143: break loop;
144: }
145: }
146: break;
147: default:
148: backslash = false;
149: if (!Character.isLetterOrDigit(c) && c != '_')
150: doKeyword(line, i, c);
151: break;
152: }
153: break;
154: case Token.COMMENT1:
155: case Token.COMMENT2:
156: backslash = false;
157: if (c == '*' && length - i > 1) {
158: if (array[i1] == '/') {
159: i++;
160: addToken((i + 1) - lastOffset, token);
161: token = Token.NULL;
162: lastOffset = lastKeyword = i + 1;
163: }
164: }
165: break;
166: case Token.LITERAL1:
167: if (backslash)
168: backslash = false;
169: else if (c == '"') {
170: addToken(i1 - lastOffset, token);
171: token = Token.NULL;
172: lastOffset = lastKeyword = i1;
173: }
174: break;
175: case Token.LITERAL2:
176: if (backslash)
177: backslash = false;
178: else if (c == '\'') {
179: addToken(i1 - lastOffset, Token.LITERAL1);
180: token = Token.NULL;
181: lastOffset = lastKeyword = i1;
182: }
183: break;
184: case Token.PARAMETER:
185: if (backslash) {
186: backslash = false;
187: } else if (c == '}') {
188: if (!doKeyword(line, i1, c)) {
189: addToken(i1 - lastOffset, token);
190: token = Token.NULL;
191: lastOffset = lastKeyword = i1;
192: }
193: }
194: break;
195: default:
196: throw new InternalError("Invalid state: " + token);
197: }
198: }
199:
200: if (token == Token.NULL)
201: doKeyword(line, length, '\0');
202:
203: switch (token) {
204: case Token.PARAMETER:
205: case Token.LITERAL1:
206: case Token.LITERAL2:
207: addToken(length - lastOffset, Token.INVALID);
208: token = Token.NULL;
209: break;
210: case Token.KEYWORD2:
211: addToken(length - lastOffset, token);
212: if (!backslash)
213: token = Token.NULL;
214: default:
215: addToken(length - lastOffset, token);
216: break;
217: }
218:
219: return token;
220: }
221:
222: public static KeywordMap getKeywords() {
223: if (cKeywords == null) {
224: cKeywords = new KeywordMap(false);
225: cKeywords.add("char", Token.KEYWORD3);
226: cKeywords.add("double", Token.KEYWORD3);
227: cKeywords.add("enum", Token.KEYWORD3);
228: cKeywords.add("float", Token.KEYWORD3);
229: cKeywords.add("int", Token.KEYWORD3);
230: cKeywords.add("long", Token.KEYWORD3);
231: cKeywords.add("short", Token.KEYWORD3);
232: cKeywords.add("signed", Token.KEYWORD3);
233: cKeywords.add("struct", Token.KEYWORD3);
234: cKeywords.add("typedef", Token.KEYWORD3);
235: cKeywords.add("union", Token.KEYWORD3);
236: cKeywords.add("unsigned", Token.KEYWORD3);
237: cKeywords.add("void", Token.KEYWORD3);
238: cKeywords.add("auto", Token.KEYWORD1);
239: cKeywords.add("const", Token.KEYWORD1);
240: cKeywords.add("extern", Token.KEYWORD1);
241: cKeywords.add("register", Token.KEYWORD1);
242: cKeywords.add("static", Token.KEYWORD1);
243: cKeywords.add("volatile", Token.KEYWORD1);
244: cKeywords.add("break", Token.KEYWORD1);
245: cKeywords.add("case", Token.KEYWORD1);
246: cKeywords.add("continue", Token.KEYWORD1);
247: cKeywords.add("default", Token.KEYWORD1);
248: cKeywords.add("do", Token.KEYWORD1);
249: cKeywords.add("else", Token.KEYWORD1);
250: cKeywords.add("for", Token.KEYWORD1);
251: cKeywords.add("goto", Token.KEYWORD1);
252: cKeywords.add("if", Token.KEYWORD1);
253: cKeywords.add("return", Token.KEYWORD1);
254: cKeywords.add("sizeof", Token.KEYWORD1);
255: cKeywords.add("switch", Token.KEYWORD1);
256: cKeywords.add("while", Token.KEYWORD1);
257: cKeywords.add("asm", Token.KEYWORD2);
258: cKeywords.add("asmlinkage", Token.KEYWORD2);
259: cKeywords.add("far", Token.KEYWORD2);
260: cKeywords.add("huge", Token.KEYWORD2);
261: cKeywords.add("inline", Token.KEYWORD2);
262: cKeywords.add("near", Token.KEYWORD2);
263: cKeywords.add("pascal", Token.KEYWORD2);
264: cKeywords.add("true", Token.LITERAL2);
265: cKeywords.add("false", Token.LITERAL2);
266: cKeywords.add("NULL", Token.LITERAL2);
267: }
268: return cKeywords;
269: }
270:
271: // private members
272: private static KeywordMap cKeywords;
273:
274: private boolean cpp;
275: protected KeywordMap keywords;
276: private int lastOffset;
277: private int lastKeyword;
278:
279: private boolean doKeyword(Segment line, int i, char c) {
280: int i1 = i + 1;
281:
282: int len = i - lastKeyword;
283: byte id = keywords.lookup(line, lastKeyword, len);
284:
285: if (id == Token.NULL && keywordLookup != null) {
286: id = keywordLookup.lookup(line, lastKeyword, len);
287: }
288:
289: if (id != Token.NULL) {
290: if (lastKeyword != lastOffset)
291: addToken(lastKeyword - lastOffset, Token.NULL);
292: addToken(len, id);
293: lastOffset = i;
294: }
295: lastKeyword = i1;
296: return false;
297: }
298: }
|