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