1
2
3
4
5
6
7
8
9
10 package org.syntax.jedit.tokenmarker;
11
12 import javax.swing.text.Segment;
13
14 import org.syntax.jedit.KeywordMap;
15 import org.syntax.jedit.SyntaxUtilities;
16
17 /***
18 * HTML token marker.
19 *
20 * @author Slava Pestov
21 * @version $Id: HTMLTokenMarker.java,v 1.34 1999/12/13 03:40:29 sp Exp $
22 */
23 public class HTMLTokenMarker extends TokenMarker
24 {
25 public static final byte JAVASCRIPT = Token.INTERNAL_FIRST;
26
27 public HTMLTokenMarker()
28 {
29 this(true);
30 }
31
32 public HTMLTokenMarker(boolean js)
33 {
34 this.js = js;
35 keywords = JavaScriptTokenMarker.getKeywords();
36 }
37
38 public byte markTokensImpl(byte token, Segment line, int lineIndex)
39 {
40 char[] array = line.array;
41 int offset = line.offset;
42 lastOffset = offset;
43 lastKeyword = offset;
44 int length = line.count + offset;
45 boolean backslash = false;
46
47 loop: for(int i = offset; i < length; i++)
48 {
49 int i1 = (i+1);
50
51 char c = array[i];
52 if(c == '//')
53 {
54 backslash = !backslash;
55 continue;
56 }
57
58 switch(token)
59 {
60 case Token.NULL:
61 backslash = false;
62 switch(c)
63 {
64 case '<':
65 addToken(i - lastOffset,token);
66 lastOffset = lastKeyword = i;
67 if(SyntaxUtilities.regionMatches(false,
68 line,i1,"!--"))
69 {
70 i += 3;
71 token = Token.COMMENT1;
72 }
73 else if(js && SyntaxUtilities.regionMatches(
74 true,line,i1,"script>"))
75 {
76 addToken(8,Token.KEYWORD1);
77 lastOffset = lastKeyword = (i += 8);
78 token = JAVASCRIPT;
79 }
80 else
81 {
82 token = Token.KEYWORD1;
83 }
84 break;
85 case '&':
86 addToken(i - lastOffset,token);
87 lastOffset = lastKeyword = i;
88 token = Token.KEYWORD2;
89 break;
90 }
91 break;
92 case Token.KEYWORD1:
93 backslash = false;
94 if(c == '>')
95 {
96 addToken(i1 - lastOffset,token);
97 lastOffset = lastKeyword = i1;
98 token = Token.NULL;
99 }
100 break;
101 case Token.KEYWORD2:
102 backslash = false;
103 if(c == ';')
104 {
105 addToken(i1 - lastOffset,token);
106 lastOffset = lastKeyword = i1;
107 token = Token.NULL;
108 break;
109 }
110 break;
111 case Token.COMMENT1:
112 backslash = false;
113 if(SyntaxUtilities.regionMatches(false,line,i,"-->"))
114 {
115 addToken((i + 3) - lastOffset,token);
116 lastOffset = lastKeyword = i + 3;
117 token = Token.NULL;
118 }
119 break;
120 case JAVASCRIPT:
121 switch(c)
122 {
123 case '<':
124 backslash = false;
125 doKeyword(line,i,c);
126 if(SyntaxUtilities.regionMatches(true,
127 line,i1,"/script>"))
128 {
129 addToken(i - lastOffset,
130 Token.NULL);
131 addToken(9,Token.KEYWORD1);
132 lastOffset = lastKeyword = (i += 9);
133 token = Token.NULL;
134 }
135 break;
136 case '"':
137 if(backslash)
138 backslash = false;
139 else
140 {
141 doKeyword(line,i,c);
142 addToken(i - lastOffset,Token.NULL);
143 lastOffset = lastKeyword = i;
144 token = Token.LITERAL1;
145 }
146 break;
147 case '\'':
148 if(backslash)
149 backslash = false;
150 else
151 {
152 doKeyword(line,i,c);
153 addToken(i - lastOffset,Token.NULL);
154 lastOffset = lastKeyword = i;
155 token = Token.LITERAL2;
156 }
157 break;
158 case '/':
159 backslash = false;
160 doKeyword(line,i,c);
161 if(length - i > 1)
162 {
163 addToken(i - lastOffset,Token.NULL);
164 lastOffset = lastKeyword = i;
165 if(array[i1] == '/')
166 {
167 addToken(length - i,Token.COMMENT2);
168 lastOffset = lastKeyword = length;
169 break loop;
170 }
171 else if(array[i1] == '*')
172 {
173 token = Token.COMMENT2;
174 }
175 }
176 break;
177 default: backslash = false;
178 if(!Character.isLetterOrDigit(c)
179 && c != '_')
180 doKeyword(line,i,c);
181 break;
182 }
183 break;
184 case Token.LITERAL1:
185 if(backslash)
186 backslash = false;
187 else if(c == '"')
188 {
189 addToken(i1 - lastOffset,Token.LITERAL1);
190 lastOffset = lastKeyword = i1;
191 token = JAVASCRIPT;
192 }
193 break;
194 case Token.LITERAL2:
195 if(backslash)
196 backslash = false;
197 else if(c == '\'')
198 {
199 addToken(i1 - lastOffset,Token.LITERAL1);
200 lastOffset = lastKeyword = i1;
201 token = JAVASCRIPT;
202 }
203 break;
204 case Token.COMMENT2:
205 backslash = false;
206 if(c == '*' && length - i > 1 && array[i1] == '/')
207 {
208 addToken((i+=2) - lastOffset,Token.COMMENT2);
209 lastOffset = lastKeyword = i;
210 token = JAVASCRIPT;
211 }
212 break;
213 default:
214 throw new InternalError("Invalid state: "
215 + token);
216 }
217 }
218
219 switch(token)
220 {
221 case Token.LITERAL1:
222 case Token.LITERAL2:
223 addToken(length - lastOffset,Token.INVALID);
224 token = JAVASCRIPT;
225 break;
226 case Token.KEYWORD2:
227 addToken(length - lastOffset,Token.INVALID);
228 token = Token.NULL;
229 break;
230 case JAVASCRIPT:
231 doKeyword(line,length,'\0');
232 addToken(length - lastOffset,Token.NULL);
233 break;
234 default:
235 addToken(length - lastOffset,token);
236 break;
237 }
238
239 return token;
240 }
241
242
243 private KeywordMap keywords;
244 private boolean js;
245 private int lastOffset;
246 private int lastKeyword;
247
248 private boolean doKeyword(Segment line, int i, char c)
249 {
250 int i1 = i+1;
251
252 int len = i - lastKeyword;
253 byte id = keywords.lookup(line,lastKeyword,len);
254 if(id != Token.NULL)
255 {
256 if(lastKeyword != lastOffset)
257 addToken(lastKeyword - lastOffset,Token.NULL);
258 addToken(len,id);
259 lastOffset = i;
260 }
261 lastKeyword = i1;
262 return false;
263 }
264 }