View Javadoc

1   /*
2    * EiffelTokenMarker.java - Eiffel token marker
3    * Copyright (C) 1999 Slava Pestov
4    * Copyright (C) 1999 Artur Biesiadowski
5    *
6    * You may use and modify this package for any purpose. Redistribution is
7    * permitted, in both source and binary form, provided that this notice
8    * remains intact in all source distributions of this package.
9    */
10  
11  package org.syntax.jedit.tokenmarker;
12  
13  import javax.swing.text.Segment;
14  
15  import org.syntax.jedit.KeywordMap;
16  
17  /***
18   * Eiffel token Marker.
19   *
20   * @author Artur Biesiadowski
21   */
22  public class EiffelTokenMarker extends TokenMarker
23  {
24  
25  	public EiffelTokenMarker()
26  	{
27  		this.keywords = getKeywords();
28  	}
29  
30  	public byte markTokensImpl(byte token, Segment line, int lineIndex)
31  	{
32  		char[] array = line.array;
33  		int offset = line.offset;
34  		lastOffset = offset;
35  		lastKeyword = offset;
36  		int length = line.count + offset;
37  		boolean backslash = false;
38  
39  loop:		for(int i = offset; i < length; i++)
40  		{
41  			int i1 = (i+1);
42  
43  			char c = array[i];
44  			if(c == '%')
45  			{
46  				backslash = !backslash;
47  				continue;
48  			}
49  
50  			switch(token)
51  			{
52  			case Token.NULL:
53  				switch(c)
54  				{
55  				case '"':
56  					doKeyword(line,i,c);
57  					if(backslash)
58  						backslash = false;
59  					else
60  					{
61  						addToken(i - lastOffset,token);
62  						token = Token.LITERAL1;
63  						lastOffset = lastKeyword = i;
64  					}
65  					break;
66  				case '\'':
67  					doKeyword(line,i,c);
68  					if(backslash)
69  						backslash = false;
70  					else
71  					{
72  						addToken(i - lastOffset,token);
73  						token = Token.LITERAL2;
74  						lastOffset = lastKeyword = i;
75  					}
76  					break;
77  				case ':':
78  					if(lastKeyword == offset)
79  					{
80  						if(doKeyword(line,i,c))
81  							break;
82  						backslash = false;
83  						addToken(i1 - lastOffset,Token.LABEL);
84  						lastOffset = lastKeyword = i1;
85  					}
86  					else if(doKeyword(line,i,c))
87  						break;
88  					break;
89  				case '-':
90  					backslash = false;
91  					doKeyword(line,i,c);
92  					if(length - i > 1)
93  					{
94  						switch(array[i1])
95  						{
96  						case '-':
97  							addToken(i - lastOffset,token);
98  							addToken(length - i,Token.COMMENT1);
99  							lastOffset = lastKeyword = length;
100 							break loop;
101 						}
102 					}
103 					break;
104 				default:
105 					backslash = false;
106 					if(!Character.isLetterOrDigit(c)
107 						&& c != '_')
108 						doKeyword(line,i,c);
109 					break;
110 				}
111 				break;
112 			case Token.COMMENT1:
113 			case Token.COMMENT2:
114 				throw new RuntimeException("Wrong eiffel parser state");
115 			case Token.LITERAL1:
116 				if(backslash)
117 					backslash = false;
118 				else if(c == '"')
119 				{
120 					addToken(i1 - lastOffset,token);
121 					token = Token.NULL;
122 					lastOffset = lastKeyword = i1;
123 				}
124 				break;
125 			case Token.LITERAL2:
126 				if(backslash)
127 					backslash = false;
128 				else if(c == '\'')
129 				{
130 					addToken(i1 - lastOffset,Token.LITERAL1);
131 					token = Token.NULL;
132 					lastOffset = lastKeyword = i1;
133 				}
134 				break;
135 			default:
136 				throw new InternalError("Invalid state: "
137 					+ token);
138 			}
139 		}
140 
141 		if(token == Token.NULL)
142 			doKeyword(line,length,'\0');
143 
144 		switch(token)
145 		{
146 		case Token.LITERAL1:
147 		case Token.LITERAL2:
148 			addToken(length - lastOffset,Token.INVALID);
149 			token = Token.NULL;
150 			break;
151 		case Token.KEYWORD2:
152 			addToken(length - lastOffset,token);
153 			if(!backslash)
154 				token = Token.NULL;
155 		default:
156 			addToken(length - lastOffset,token);
157 			break;
158 		}
159 
160 		return token;
161 	}
162 
163 	public static KeywordMap getKeywords()
164 	{
165 		if(eiffelKeywords == null)
166 		{
167 			eiffelKeywords = new KeywordMap(true);
168 			eiffelKeywords.add("alias", Token.KEYWORD1);
169 			eiffelKeywords.add("all", Token.KEYWORD1);
170 			eiffelKeywords.add("and", Token.KEYWORD1);
171 			eiffelKeywords.add("as", Token.KEYWORD1);
172 			eiffelKeywords.add("check", Token.KEYWORD1);
173 			eiffelKeywords.add("class", Token.KEYWORD1);
174 			eiffelKeywords.add("creation", Token.KEYWORD1);
175 			eiffelKeywords.add("debug", Token.KEYWORD1);
176 			eiffelKeywords.add("deferred", Token.KEYWORD1);
177 			eiffelKeywords.add("do", Token.KEYWORD1);
178 			eiffelKeywords.add("else",Token.KEYWORD1);
179 			eiffelKeywords.add("elseif", Token.KEYWORD1);
180 			eiffelKeywords.add("end", Token.KEYWORD1);
181 			eiffelKeywords.add("ensure", Token.KEYWORD1);
182 			eiffelKeywords.add("expanded", Token.KEYWORD1);
183 			eiffelKeywords.add("export", Token.KEYWORD1);
184 			eiffelKeywords.add("external", Token.KEYWORD1);
185 			eiffelKeywords.add("feature", Token.KEYWORD1);
186 			eiffelKeywords.add("from", Token.KEYWORD1);
187 			eiffelKeywords.add("frozen", Token.KEYWORD1);
188 			eiffelKeywords.add("if", Token.KEYWORD1);
189 			eiffelKeywords.add("implies",Token.KEYWORD1);
190 			eiffelKeywords.add("indexing", Token.KEYWORD1);
191 			eiffelKeywords.add("infix", Token.KEYWORD1);
192 			eiffelKeywords.add("inherit", Token.KEYWORD1);
193 			eiffelKeywords.add("inspect", Token.KEYWORD1);
194 			eiffelKeywords.add("invariant", Token.KEYWORD1);
195 			eiffelKeywords.add("is", Token.KEYWORD1);
196 			eiffelKeywords.add("like", Token.KEYWORD1);
197 			eiffelKeywords.add("local", Token.KEYWORD1);
198 			eiffelKeywords.add("loop", Token.KEYWORD1);
199 			eiffelKeywords.add("not", Token.KEYWORD1);
200 			eiffelKeywords.add("obsolete", Token.KEYWORD1);
201 			eiffelKeywords.add("old",Token.KEYWORD1);
202 			eiffelKeywords.add("once", Token.KEYWORD1);
203 			eiffelKeywords.add("or", Token.KEYWORD1);
204 			eiffelKeywords.add("prefix", Token.KEYWORD1);
205 			eiffelKeywords.add("redefine", Token.KEYWORD1);
206 			eiffelKeywords.add("rename", Token.KEYWORD1);
207 			eiffelKeywords.add("require", Token.KEYWORD1);
208 			eiffelKeywords.add("rescue", Token.KEYWORD1);
209 			eiffelKeywords.add("retry", Token.KEYWORD1);
210 			eiffelKeywords.add("select", Token.KEYWORD1);
211 			eiffelKeywords.add("separate", Token.KEYWORD1);
212 			eiffelKeywords.add("then",Token.KEYWORD1);
213 			eiffelKeywords.add("undefine", Token.KEYWORD1);
214 			eiffelKeywords.add("until", Token.KEYWORD1);
215 			eiffelKeywords.add("variant", Token.KEYWORD1);
216 			eiffelKeywords.add("when", Token.KEYWORD1);
217 			eiffelKeywords.add("xor", Token.KEYWORD1);
218 
219 			eiffelKeywords.add("current",Token.LITERAL2);
220 			eiffelKeywords.add("false",Token.LITERAL2);
221 			eiffelKeywords.add("precursor",Token.LITERAL2);
222 			eiffelKeywords.add("result",Token.LITERAL2);
223 			eiffelKeywords.add("strip",Token.LITERAL2);
224 			eiffelKeywords.add("true",Token.LITERAL2);
225 			eiffelKeywords.add("unique",Token.LITERAL2);
226 			eiffelKeywords.add("void",Token.LITERAL2);
227 
228 		}
229 		return eiffelKeywords;
230 	}
231 
232 	// private members
233 	private static KeywordMap eiffelKeywords;
234 
235 	private boolean cpp;
236 	private KeywordMap keywords;
237 	private int lastOffset;
238 	private int lastKeyword;
239 
240 	private boolean doKeyword(Segment line, int i, char c)
241 	{
242 		int i1 = i+1;
243 		boolean klassname = false;
244 
245 		int len = i - lastKeyword;
246 		byte id = keywords.lookup(line,lastKeyword,len);
247 		if ( id == Token.NULL )
248 		{
249 			klassname = true;
250 			for ( int at = lastKeyword; at < lastKeyword + len; at++ )
251 			{
252 				char ch = line.array[at];
253 				if ( ch != '_' && !Character.isUpperCase(ch) )
254 				{
255 					klassname = false;
256 					break;
257 				}
258 			}
259 			if ( klassname )
260 				id = Token.KEYWORD3;
261 		}
262 
263 		if(id != Token.NULL)
264 		{
265 			if(lastKeyword != lastOffset)
266 				addToken(lastKeyword - lastOffset,Token.NULL);
267 			addToken(len,id);
268 			lastOffset = i;
269 		}
270 		lastKeyword = i1;
271 		return false;
272 	}
273 }