1 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 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 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 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 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 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 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 endToken(text, i, state); 233 if (state == TCL_STATE_IDENTIFIER) { 234 final LineSegment segment = getLastSegment(); 235 if (segment != null) { 236 final String 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 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 |