KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > SchemeFormatter


1 /*
2  * SchemeFormatter.java
3  *
4  * Copyright (C) 1998-2002 Peter Graves
5  * $Id: SchemeFormatter.java,v 1.1.1.1 2002/09/24 16:09:14 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 public final class SchemeFormatter extends Formatter
25 {
26     // Formats.
27
private static final int SCHEME_FORMAT_TEXT = 0;
28     private static final int SCHEME_FORMAT_COMMENT = 1;
29     private static final int SCHEME_FORMAT_STRING = 2;
30     private static final int SCHEME_FORMAT_KEYWORD = 3;
31     private static final int SCHEME_FORMAT_FUNCTION = 4;
32     private static final int SCHEME_FORMAT_NUMBER = 5;
33
34     private FastStringBuffer sb = new FastStringBuffer();
35     private int tokStart;
36
37     public SchemeFormatter(Buffer buffer)
38     {
39         this.buffer = buffer;
40     }
41
42     private void endToken(int state)
43     {
44         if (sb.length() > 0) {
45             int format = -1;
46             switch (state) {
47                 case STATE_NEUTRAL:
48                     break;
49                 case STATE_QUOTE:
50                     format = SCHEME_FORMAT_STRING;
51                     break;
52                 case STATE_IDENTIFIER:
53                     break;
54                 case STATE_COMMENT:
55                     format = SCHEME_FORMAT_COMMENT;
56                     break;
57                 case STATE_NUMBER:
58                 case STATE_HEXNUMBER:
59                     format = SCHEME_FORMAT_NUMBER;
60                     break;
61             }
62             addSegment(sb.toString(), format);
63             tokStart += sb.length();
64             sb.setLength(0);
65         }
66     }
67
68     private void parseLine(String JavaDoc text, int state)
69     {
70         if (Editor.tabsAreVisible())
71             text = Utilities.makeTabsVisible(text, buffer.getTabWidth());
72         else
73             text = Utilities.detab(text, buffer.getTabWidth());
74         clearSegmentList();
75         sb.setLength(0);
76         int i = 0;
77         tokStart = 0;
78         final int limit = text.length();
79         // Skip whitespace at start of line.
80
while (i < limit) {
81             char c = text.charAt(i);
82             if (Character.isWhitespace(c)) {
83                 sb.append(c);
84                 ++i;
85             } else {
86                 endToken(state);
87                 break;
88             }
89         }
90         while (i < limit) {
91             char c = text.charAt(i);
92             if (c == '\\' && i < limit-1) {
93                 sb.append(c);
94                 sb.append(text.charAt(++i));
95                 ++i;
96                 continue;
97             }
98             if (state == STATE_COMMENT) {
99                 if (c == '|' && i < limit-1) {
100                     c = text.charAt(i+1);
101                     if (c == '#') {
102                         sb.append("|#");
103                         endToken(state);
104                         state = STATE_NEUTRAL;
105                         i += 2;
106                         continue;
107                     }
108                 }
109                 sb.append(c);
110                 ++i;
111                 continue;
112             }
113             if (state == STATE_QUOTE) {
114                 sb.append(c);
115                 if (c == '"') {
116                     endToken(state);
117                     state = STATE_NEUTRAL;
118                 }
119                 ++i;
120                 continue;
121             }
122             // Reaching here, we're not in a quoted string.
123
if (c == '"') {
124                 endToken(state);
125                 sb.append(c);
126                 state = STATE_QUOTE;
127                 ++i;
128                 continue;
129             }
130             if (c == ';') {
131                 endToken(state);
132                 state = STATE_COMMENT;
133                 sb.append(text.substring(i));
134                 endToken(state);
135                 return;
136             }
137             if (c == '#' && i < limit-1) {
138                 if (text.charAt(i+1) == '|') {
139                     endToken(state);
140                     state = STATE_COMMENT;
141                     sb.append("#|");
142                     i += 2;
143                     continue;
144                 }
145             }
146             if (state == STATE_IDENTIFIER) {
147                 if (buffer.getMode().isIdentifierPart(c))
148                     sb.append(c);
149                 else {
150                     endToken(state);
151                     sb.append(c);
152                     state = STATE_NEUTRAL;
153                 }
154                 ++i;
155                 continue;
156             }
157             if (state == STATE_NUMBER) {
158                 if (Character.isDigit(c))
159                     sb.append(c);
160                 else if (c == 'u' || c == 'U' || c == 'l' || c == 'L')
161                     sb.append(c); // Valid suffix.
162
else if (sb.length() == 1 && c == 'x' || c == 'X') {
163                     sb.append(c);
164                     state = STATE_HEXNUMBER;
165                 } else {
166                     endToken(state);
167                     sb.append(c);
168                     if (Character.isJavaIdentifierStart(c))
169                         state = STATE_IDENTIFIER;
170                     else
171                         state = STATE_NEUTRAL;
172                 }
173                 ++i;
174                 continue;
175             }
176             if (state == STATE_HEXNUMBER) {
177                 if (Character.isDigit(c))
178                     sb.append(c);
179                 else if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
180                     sb.append(c);
181                 else if (c == 'u' || c == 'U' || c == 'l' || c == 'L')
182                     sb.append(c); // Valid suffix.
183
else {
184                     endToken(state);
185                     sb.append(c);
186                     if (Character.isJavaIdentifierStart(c))
187                         state = STATE_IDENTIFIER;
188                     else
189                         state = STATE_NEUTRAL;
190                 }
191                 ++i;
192                 continue;
193             }
194             if (state == STATE_NEUTRAL) {
195                 if (buffer.mode.isIdentifierStart(c)) {
196                     endToken(state);
197                     sb.append(c);
198                     state = STATE_IDENTIFIER;
199                 } else if (Character.isDigit(c)) {
200                     endToken(state);
201                     sb.append(c);
202                     state = STATE_NUMBER;
203                 } else // Still neutral...
204
sb.append(c);
205             }
206             ++i;
207         }
208         endToken(state);
209     }
210
211     public LineSegmentList formatLine(Line line)
212     {
213         if (line == null) {
214             clearSegmentList();
215             addSegment("", SCHEME_FORMAT_TEXT);
216             return segmentList;
217         }
218         parseLine(line.getText(), line.flags());
219         final int size = segmentList.size();
220         for (int i = 0; i < size; i++) {
221             LineSegment segment = segmentList.getSegment(i);
222             if (segment.getFormat() >= 0)
223                 continue;
224             String JavaDoc token = segment.getText();
225             if (isKeyword(token))
226                 segment.setFormat(SCHEME_FORMAT_KEYWORD);
227             else {
228                 boolean isFunction = false;
229                 if (i >= 2) {
230                     LineSegment prevSegment = segmentList.getSegment(i-2);
231                     String JavaDoc prevToken = prevSegment.getText();
232                     String JavaDoc trim = prevToken.trim();
233                     if (trim.equals("define"))
234                         isFunction = true;
235                 }
236                 segment.setFormat(isFunction ? SCHEME_FORMAT_FUNCTION : SCHEME_FORMAT_TEXT);
237             }
238         }
239         return segmentList;
240     }
241
242     public boolean parseBuffer()
243     {
244         int state = STATE_NEUTRAL;
245         boolean changed = false;
246         Line line = buffer.getFirstLine();
247         while (line != null) {
248             int oldflags = line.flags();
249             if (state != oldflags) {
250                 line.setFlags(state);
251                 changed = true;
252             }
253             final int limit = line.length();
254             for (int i = 0; i < limit; i++) {
255                 char c = line.charAt(i);
256                 if (c == '\\' && i < limit-1) {
257                     // Escape.
258
++i;
259                     continue;
260                 }
261                 if (state == STATE_COMMENT) {
262                     if (c == '|' && i < limit-1 && line.charAt(i+1) == '#') {
263                         ++i;
264                         state = STATE_NEUTRAL;
265                     }
266                     continue;
267                 }
268                 if (state == STATE_QUOTE) {
269                     if (c == '"')
270                         state = STATE_NEUTRAL;
271                     continue;
272                 }
273                 // Not in comment or quoted string.
274
if (c == ';') {
275                     // Single-line comment beginning. Ignore rest of line.
276
break;
277                 }
278                 if (c == '#') {
279                     if (i < limit-1 && line.charAt(i+1) == '|') {
280                         state = STATE_COMMENT;
281                         ++i;
282                     }
283                     continue;
284                 }
285                 if (c == '"')
286                     state = STATE_QUOTE;
287             }
288             line = line.next();
289         }
290         buffer.setNeedsParsing(false);
291         return changed;
292     }
293
294     public FormatTable getFormatTable()
295     {
296         if (formatTable == null) {
297             formatTable = new FormatTable("SchemeMode");
298             formatTable.addEntryFromPrefs(SCHEME_FORMAT_TEXT, "text");
299             formatTable.addEntryFromPrefs(SCHEME_FORMAT_COMMENT, "comment");
300             formatTable.addEntryFromPrefs(SCHEME_FORMAT_STRING, "string");
301             formatTable.addEntryFromPrefs(SCHEME_FORMAT_KEYWORD, "keyword");
302             formatTable.addEntryFromPrefs(SCHEME_FORMAT_FUNCTION, "function");
303             formatTable.addEntryFromPrefs(SCHEME_FORMAT_NUMBER, "number");
304         }
305         return formatTable;
306     }
307 }
308
Popular Tags