KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * TclFormatter.java
3  *
4  * Copyright (C) 2002 Peter Graves
5  * $Id: TclFormatter.java,v 1.1.1.1 2002/09/24 16:09:09 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 TclFormatter extends Formatter implements Constants
25 {
26     private static final int TCL_STATE_NEUTRAL = 0;
27     private static final int TCL_STATE_COMMENT = 1;
28     private static final int TCL_STATE_QUOTE = 2;
29     private static final int TCL_STATE_IDENTIFIER = 3;
30     private static final int TCL_STATE_OPERATOR = 4;
31     private static final int TCL_STATE_BRACE = 5;
32     private static final int TCL_STATE_BRACKET = 6;
33     private static final int TCL_STATE_NUMBER = 7;
34
35     private static final int TCL_FORMAT_TEXT = 0;
36     private static final int TCL_FORMAT_COMMENT = 1;
37     private static final int TCL_FORMAT_STRING = 2;
38     private static final int TCL_FORMAT_IDENTIFIER = 3;
39     private static final int TCL_FORMAT_KEYWORD = 4;
40     private static final int TCL_FORMAT_ARRAY = 5;
41     private static final int TCL_FORMAT_OPERATOR = 6;
42     private static final int TCL_FORMAT_BRACE = 7;
43     private static final int TCL_FORMAT_BRACKET = 8;
44     private static final int TCL_FORMAT_NUMBER = 9;
45
46     private static final TclMode mode = TclMode.getMode();
47
48     public TclFormatter(Buffer buffer)
49     {
50         this.buffer = buffer;
51     }
52
53     private int tokenBegin = 0;
54
55     private void endToken(String JavaDoc text, int tokenEnd, int state)
56     {
57         if (tokenEnd - tokenBegin > 0) {
58             int format = TCL_FORMAT_TEXT;
59             switch (state) {
60                 case TCL_STATE_NEUTRAL:
61                     format = TCL_FORMAT_TEXT;
62                     break;
63                 case TCL_STATE_QUOTE:
64                     format = TCL_FORMAT_STRING;
65                     break;
66                 case TCL_STATE_IDENTIFIER:
67                     format = TCL_FORMAT_IDENTIFIER;
68                     break;
69                 case TCL_STATE_COMMENT:
70                     format = TCL_FORMAT_COMMENT;
71                     break;
72                 case TCL_STATE_OPERATOR:
73                     format = TCL_FORMAT_OPERATOR;
74                     break;
75                 case TCL_STATE_BRACE:
76                     format = TCL_FORMAT_BRACE;
77                     break;
78                 case TCL_STATE_BRACKET:
79                     format = TCL_FORMAT_BRACKET;
80                     break;
81                 case TCL_STATE_NUMBER:
82                     format = TCL_FORMAT_NUMBER;
83                     break;
84             }
85             addSegment(text, tokenBegin, tokenEnd, format);
86             tokenBegin = tokenEnd;
87         }
88     }
89
90     private void parseLine(Line line)
91     {
92         if (line == null) {
93             addSegment("", TCL_FORMAT_TEXT);
94             return;
95         }
96         String JavaDoc text;
97         if (Editor.tabsAreVisible())
98             text = Utilities.makeTabsVisible(line.getText(), buffer.getTabWidth());
99         else
100             text = Utilities.detab(line.getText(), buffer.getTabWidth());
101         tokenBegin = 0;
102         int state = TCL_STATE_NEUTRAL;
103         int i = 0;
104         final int limit = text.length();
105
106         // Skip whitespace at start of line.
107
while (i < limit) {
108             if (Character.isWhitespace(text.charAt(i))) {
109                 ++i;
110             } else {
111                 endToken(text, i, state);
112                 break;
113             }
114         }
115
116         while (i < limit) {
117             char c = text.charAt(i);
118             if (c == '\\' && i < limit-1) {
119                 i += 2;
120                 continue;
121             }
122             if (state == TCL_STATE_QUOTE) {
123                 if (c == '"') {
124                     endToken(text, i+1, state);
125                     state = TCL_STATE_NEUTRAL;
126                 }
127                 ++i;
128                 continue;
129             }
130             if (c == '"') {
131                 endToken(text, i, state);
132                 state = TCL_STATE_QUOTE;
133                 ++i;
134                 continue;
135             }
136             if (c == '#') {
137                 // It's only a real comment if '#' is the first non-whitespace
138
// character on the line or if it is immediately preceded by a
139
// semicolon, opening brace, or opening bracket.
140
boolean isComment = true;
141                 for (int j = i-1; j >= 0; j--) {
142                     char cc = text.charAt(j);
143                     if (Character.isWhitespace(cc))
144                         continue;
145                     if (";{[".indexOf(cc) >= 0)
146                         break;
147                     // Otherwise...
148
isComment = false;
149                     break;
150                 }
151                 if (isComment) {
152                     endToken(text, i, state);
153                     endToken(text, limit, TCL_STATE_COMMENT);
154                     return;
155                 } else {
156                     ++i;
157                     continue;
158                 }
159             }
160             if (c == '{' || c == '}') {
161                 if (state != TCL_STATE_BRACE) {
162                     endToken(text, i, state);
163                     state = TCL_STATE_BRACE;
164                 }
165                 ++i;
166                 continue;
167             }
168             if (c == '[' || c == ']') {
169                 if (state != TCL_STATE_BRACKET) {
170                     endToken(text, i, state);
171                     state = TCL_STATE_BRACKET;
172                 }
173                 ++i;
174                 continue;
175             }
176             if (state == TCL_STATE_BRACE || state == TCL_STATE_BRACKET) {
177                 if (mode.isIdentifierStart(c)) {
178                     endToken(text, i, state);
179                     state = TCL_STATE_IDENTIFIER;
180                 } else if (Character.isDigit(c)) {
181                     endToken(text, i, state);
182                     state = TCL_STATE_NUMBER;
183                 } else {
184                     endToken(text, i, state);
185                     state = TCL_STATE_NEUTRAL;
186                 }
187                 ++i;
188                 continue;
189             }
190             if (state == TCL_STATE_IDENTIFIER) {
191                 if (!mode.isIdentifierPart(c)) {
192                     endToken(text, i, state);
193                     final LineSegment segment = getLastSegment();
194                     if (segment != null) {
195                         final String JavaDoc segmentText = segment.getText();
196                         if (isKeyword(segmentText))
197                             segment.setFormat(TCL_FORMAT_KEYWORD);
198                         else if (isOperator(segmentText))
199                             segment.setFormat(TCL_FORMAT_OPERATOR);
200                         else if (c == '(')
201                             segment.setFormat(TCL_FORMAT_ARRAY);
202                     }
203                     state = TCL_STATE_NEUTRAL;
204                 }
205                 ++i;
206                 continue;
207             }
208             if (state == TCL_STATE_NUMBER) {
209                 if (!Character.isDigit(c)) {
210                     endToken(text, i, state);
211                     if (mode.isIdentifierStart(c))
212                         state = TCL_STATE_IDENTIFIER;
213                     else
214                         state = TCL_STATE_NEUTRAL;
215                 }
216                 ++i;
217                 continue;
218             }
219             if (state == TCL_STATE_NEUTRAL) {
220                 if (mode.isIdentifierStart(c)) {
221                     endToken(text, i, state);
222                     state = TCL_STATE_IDENTIFIER;
223                 } else if (Character.isDigit(c)) {
224                     endToken(text, i, state);
225                     state = TCL_STATE_NUMBER;
226                 }
227             }
228             ++i;
229         }
230
231         // Reached end of line.
232
endToken(text, i, state);
233         if (state == TCL_STATE_IDENTIFIER) {
234             final LineSegment segment = getLastSegment();
235             if (segment != null) {
236                 final String JavaDoc segmentText = segment.getText();
237                 if (isKeyword(segmentText))
238                     segment.setFormat(TCL_FORMAT_KEYWORD);
239                 else if (isOperator(segmentText))
240                     segment.setFormat(TCL_FORMAT_OPERATOR);
241             }
242         }
243     }
244
245     public LineSegmentList formatLine(Line line)
246     {
247         clearSegmentList();
248         parseLine(line);
249         return segmentList;
250     }
251
252     private static final boolean isOperator(String JavaDoc s)
253     {
254         for (int i = s.length()-1; i >= 0; i--) {
255             if (!isOperatorChar(s.charAt(i)))
256                 return false;
257         }
258         return true;
259     }
260
261     private static final boolean isOperatorChar(char c)
262     {
263         return "!&|<>=+/*-".indexOf(c) >= 0;
264     }
265
266     public FormatTable getFormatTable()
267     {
268         if (formatTable == null) {
269             formatTable = new FormatTable("TclMode");
270             formatTable.addEntryFromPrefs(TCL_FORMAT_TEXT, "text");
271             formatTable.addEntryFromPrefs(TCL_FORMAT_COMMENT, "comment");
272             formatTable.addEntryFromPrefs(TCL_FORMAT_STRING, "string");
273             formatTable.addEntryFromPrefs(TCL_FORMAT_IDENTIFIER, "identifier", "text");
274             formatTable.addEntryFromPrefs(TCL_FORMAT_KEYWORD, "keyword");
275             formatTable.addEntryFromPrefs(TCL_FORMAT_ARRAY, "text");
276             formatTable.addEntryFromPrefs(TCL_FORMAT_OPERATOR, "operator");
277             formatTable.addEntryFromPrefs(TCL_FORMAT_BRACE, "brace");
278             formatTable.addEntryFromPrefs(TCL_FORMAT_BRACKET, "bracket", "brace");
279             formatTable.addEntryFromPrefs(TCL_FORMAT_NUMBER, "number");
280         }
281         return formatTable;
282     }
283 }
284
Popular Tags