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