001: /*
002: * EiffelTokenMarker.java - Eiffel token marker
003: * Copyright (C) 1999 Slava Pestov
004: * Copyright (C) 1999 Artur Biesiadowski
005: *
006: * You may use and modify this package for any purpose. Redistribution is
007: * permitted, in both source and binary form, provided that this notice
008: * remains intact in all source distributions of this package.
009: */
010:
011: package org.syntax.jedit.tokenmarker;
012:
013: import javax.swing.text.Segment;
014:
015: import org.syntax.jedit.KeywordMap;
016:
017: /**
018: * Eiffel token Marker.
019: *
020: * @author Artur Biesiadowski
021: */
022: public class EiffelTokenMarker extends TokenMarker {
023:
024: public EiffelTokenMarker() {
025: this .keywords = getKeywords();
026: }
027:
028: public byte markTokensImpl(byte token, Segment line, int lineIndex) {
029: char[] array = line.array;
030: int offset = line.offset;
031: lastOffset = offset;
032: lastKeyword = offset;
033: int length = line.count + offset;
034: boolean backslash = false;
035:
036: loop: for (int i = offset; i < length; i++) {
037: int i1 = (i + 1);
038:
039: char c = array[i];
040: if (c == '%') {
041: backslash = !backslash;
042: continue;
043: }
044:
045: switch (token) {
046: case Token.NULL:
047: switch (c) {
048: case '"':
049: doKeyword(line, i, c);
050: if (backslash)
051: backslash = false;
052: else {
053: addToken(i - lastOffset, token);
054: token = Token.LITERAL1;
055: lastOffset = lastKeyword = i;
056: }
057: break;
058: case '\'':
059: doKeyword(line, i, c);
060: if (backslash)
061: backslash = false;
062: else {
063: addToken(i - lastOffset, token);
064: token = Token.LITERAL2;
065: lastOffset = lastKeyword = i;
066: }
067: break;
068: case ':':
069: if (lastKeyword == offset) {
070: if (doKeyword(line, i, c))
071: break;
072: backslash = false;
073: addToken(i1 - lastOffset, Token.LABEL);
074: lastOffset = lastKeyword = i1;
075: } else if (doKeyword(line, i, c))
076: break;
077: break;
078: case '-':
079: backslash = false;
080: doKeyword(line, i, c);
081: if (length - i > 1) {
082: switch (array[i1]) {
083: case '-':
084: addToken(i - lastOffset, token);
085: addToken(length - i, Token.COMMENT1);
086: lastOffset = lastKeyword = length;
087: break loop;
088: }
089: }
090: break;
091: default:
092: backslash = false;
093: if (!Character.isLetterOrDigit(c) && c != '_')
094: doKeyword(line, i, c);
095: break;
096: }
097: break;
098: case Token.COMMENT1:
099: case Token.COMMENT2:
100: throw new RuntimeException("Wrong eiffel parser state");
101: case Token.LITERAL1:
102: if (backslash)
103: backslash = false;
104: else if (c == '"') {
105: addToken(i1 - lastOffset, token);
106: token = Token.NULL;
107: lastOffset = lastKeyword = i1;
108: }
109: break;
110: case Token.LITERAL2:
111: if (backslash)
112: backslash = false;
113: else if (c == '\'') {
114: addToken(i1 - lastOffset, Token.LITERAL1);
115: token = Token.NULL;
116: lastOffset = lastKeyword = i1;
117: }
118: break;
119: default:
120: throw new InternalError("Invalid state: " + token);
121: }
122: }
123:
124: if (token == Token.NULL)
125: doKeyword(line, length, '\0');
126:
127: switch (token) {
128: case Token.LITERAL1:
129: case Token.LITERAL2:
130: addToken(length - lastOffset, Token.INVALID);
131: token = Token.NULL;
132: break;
133: case Token.KEYWORD2:
134: addToken(length - lastOffset, token);
135: if (!backslash)
136: token = Token.NULL;
137: default:
138: addToken(length - lastOffset, token);
139: break;
140: }
141:
142: return token;
143: }
144:
145: public static KeywordMap getKeywords() {
146: if (eiffelKeywords == null) {
147: eiffelKeywords = new KeywordMap(true);
148: eiffelKeywords.add("alias", Token.KEYWORD1);
149: eiffelKeywords.add("all", Token.KEYWORD1);
150: eiffelKeywords.add("and", Token.KEYWORD1);
151: eiffelKeywords.add("as", Token.KEYWORD1);
152: eiffelKeywords.add("check", Token.KEYWORD1);
153: eiffelKeywords.add("class", Token.KEYWORD1);
154: eiffelKeywords.add("creation", Token.KEYWORD1);
155: eiffelKeywords.add("debug", Token.KEYWORD1);
156: eiffelKeywords.add("deferred", Token.KEYWORD1);
157: eiffelKeywords.add("do", Token.KEYWORD1);
158: eiffelKeywords.add("else", Token.KEYWORD1);
159: eiffelKeywords.add("elseif", Token.KEYWORD1);
160: eiffelKeywords.add("end", Token.KEYWORD1);
161: eiffelKeywords.add("ensure", Token.KEYWORD1);
162: eiffelKeywords.add("expanded", Token.KEYWORD1);
163: eiffelKeywords.add("export", Token.KEYWORD1);
164: eiffelKeywords.add("external", Token.KEYWORD1);
165: eiffelKeywords.add("feature", Token.KEYWORD1);
166: eiffelKeywords.add("from", Token.KEYWORD1);
167: eiffelKeywords.add("frozen", Token.KEYWORD1);
168: eiffelKeywords.add("if", Token.KEYWORD1);
169: eiffelKeywords.add("implies", Token.KEYWORD1);
170: eiffelKeywords.add("indexing", Token.KEYWORD1);
171: eiffelKeywords.add("infix", Token.KEYWORD1);
172: eiffelKeywords.add("inherit", Token.KEYWORD1);
173: eiffelKeywords.add("inspect", Token.KEYWORD1);
174: eiffelKeywords.add("invariant", Token.KEYWORD1);
175: eiffelKeywords.add("is", Token.KEYWORD1);
176: eiffelKeywords.add("like", Token.KEYWORD1);
177: eiffelKeywords.add("local", Token.KEYWORD1);
178: eiffelKeywords.add("loop", Token.KEYWORD1);
179: eiffelKeywords.add("not", Token.KEYWORD1);
180: eiffelKeywords.add("obsolete", Token.KEYWORD1);
181: eiffelKeywords.add("old", Token.KEYWORD1);
182: eiffelKeywords.add("once", Token.KEYWORD1);
183: eiffelKeywords.add("or", Token.KEYWORD1);
184: eiffelKeywords.add("prefix", Token.KEYWORD1);
185: eiffelKeywords.add("redefine", Token.KEYWORD1);
186: eiffelKeywords.add("rename", Token.KEYWORD1);
187: eiffelKeywords.add("require", Token.KEYWORD1);
188: eiffelKeywords.add("rescue", Token.KEYWORD1);
189: eiffelKeywords.add("retry", Token.KEYWORD1);
190: eiffelKeywords.add("select", Token.KEYWORD1);
191: eiffelKeywords.add("separate", Token.KEYWORD1);
192: eiffelKeywords.add("then", Token.KEYWORD1);
193: eiffelKeywords.add("undefine", Token.KEYWORD1);
194: eiffelKeywords.add("until", Token.KEYWORD1);
195: eiffelKeywords.add("variant", Token.KEYWORD1);
196: eiffelKeywords.add("when", Token.KEYWORD1);
197: eiffelKeywords.add("xor", Token.KEYWORD1);
198:
199: eiffelKeywords.add("current", Token.LITERAL2);
200: eiffelKeywords.add("false", Token.LITERAL2);
201: eiffelKeywords.add("precursor", Token.LITERAL2);
202: eiffelKeywords.add("result", Token.LITERAL2);
203: eiffelKeywords.add("strip", Token.LITERAL2);
204: eiffelKeywords.add("true", Token.LITERAL2);
205: eiffelKeywords.add("unique", Token.LITERAL2);
206: eiffelKeywords.add("void", Token.LITERAL2);
207:
208: }
209: return eiffelKeywords;
210: }
211:
212: // private members
213: private static KeywordMap eiffelKeywords;
214:
215: private boolean cpp;
216: private KeywordMap keywords;
217: private int lastOffset;
218: private int lastKeyword;
219:
220: private boolean doKeyword(Segment line, int i, char c) {
221: int i1 = i + 1;
222: boolean klassname = false;
223:
224: int len = i - lastKeyword;
225: byte id = keywords.lookup(line, lastKeyword, len);
226: if (id == Token.NULL) {
227: klassname = true;
228: for (int at = lastKeyword; at < lastKeyword + len; at++) {
229: char ch = line.array[at];
230: if (ch != '_' && !Character.isUpperCase(ch)) {
231: klassname = false;
232: break;
233: }
234: }
235: if (klassname)
236: id = Token.KEYWORD3;
237: }
238:
239: if (id != Token.NULL) {
240: if (lastKeyword != lastOffset)
241: addToken(lastKeyword - lastOffset, Token.NULL);
242: addToken(len, id);
243: lastOffset = i;
244: }
245: lastKeyword = i1;
246: return false;
247: }
248: }
|