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