1 21 22 package org.armedbear.j; 23 24 public final class JavaFormatter extends Formatter implements Constants 25 { 26 private static final int JAVA_FORMAT_TEXT = 0; 27 private static final int JAVA_FORMAT_COMMENT = 1; 28 private static final int JAVA_FORMAT_STRING = 2; 29 private static final int JAVA_FORMAT_IDENTIFIER = 3; 30 private static final int JAVA_FORMAT_KEYWORD = 4; 31 private static final int JAVA_FORMAT_FUNCTION = 5; 32 private static final int JAVA_FORMAT_OPERATOR = 6; 33 private static final int JAVA_FORMAT_BRACE = 7; 34 private static final int JAVA_FORMAT_NUMBER = 8; 35 36 public static final int JAVA_FORMAT_LAST = 8; 37 38 private final int language; 39 40 public JavaFormatter(Buffer buffer) 41 { 42 this(buffer, LANGUAGE_JAVA); 43 } 44 45 public JavaFormatter(Buffer buffer, int language) 46 { 47 this.buffer = buffer; 48 this.language = language; 49 } 50 51 private int tokenBegin = 0; 52 53 private void endToken(String text, int tokenEnd, int state) 54 { 55 if (tokenEnd - tokenBegin > 0) { 56 int format = JAVA_FORMAT_TEXT; 57 switch (state) { 58 case STATE_NEUTRAL: 59 format = JAVA_FORMAT_TEXT; 60 break; 61 case STATE_QUOTE: 62 format = JAVA_FORMAT_STRING; 63 break; 64 case STATE_IDENTIFIER: 65 format = JAVA_FORMAT_IDENTIFIER; 66 break; 67 case STATE_COMMENT: 68 format = JAVA_FORMAT_COMMENT; 69 break; 70 case STATE_OPERATOR: 71 format = JAVA_FORMAT_OPERATOR; 72 break; 73 case STATE_BRACE: 74 format = JAVA_FORMAT_BRACE; 75 break; 76 case STATE_NUMBER: 77 case STATE_HEXNUMBER: 78 format = JAVA_FORMAT_NUMBER; 79 break; 80 } 81 addSegment(text, tokenBegin, tokenEnd, format); 82 tokenBegin = tokenEnd; 83 } 84 } 85 86 private void parseLine(Line line) 87 { 88 final String text = getDetabbedText(line); 89 tokenBegin = 0; 90 boolean isPreprocessorLine = false; 91 char quoteChar = '\0'; 92 int state = line.flags(); 93 if (state == STATE_QUOTE) 94 quoteChar = '"'; 95 int i = 0; 96 final int limit = text.length(); 97 while (i < limit) { 99 if (Character.isWhitespace(text.charAt(i))) 100 ++i; 101 else { 102 endToken(text, i, state); 103 break; 104 } 105 } 106 char c; 107 if (state == STATE_SCRIPT) 108 state = STATE_NEUTRAL; 109 while (i < limit) { 110 c = text.charAt(i); 111 if (state == STATE_COMMENT) { 112 if (i < limit - 1 && c == '*' && text.charAt(i+1) == '/') { 113 endToken(text, i + 2, state); 114 state = STATE_NEUTRAL; 115 i += 2; 116 } 117 else 118 ++i; 119 continue; 120 } 121 if (state == STATE_QUOTE) { 122 if (c == quoteChar) { 123 endToken(text, i+1, state); 124 state = STATE_NEUTRAL; 125 } else if (c == '\\' && i < limit-1) { 126 ++i; 128 } 129 ++i; 130 continue; 131 } 132 if (c == '"' || c == '\'') { 134 endToken(text, i, state); 135 state = STATE_QUOTE; 136 quoteChar = c; 137 ++i; 138 continue; 139 } 140 if (c == '/') { 141 if (i < limit-1) { 142 if (text.charAt(i+1) == '*') { 143 endToken(text, i, state); 144 state = STATE_COMMENT; 145 i += 2; 146 } else if (text.charAt(i+1) == '/') { 147 endToken(text, i, state); 148 endToken(text, limit, STATE_COMMENT); 149 return; 150 } else 151 ++i; 152 } else 153 ++i; 154 continue; 155 } 156 if (isOperatorChar(c)) { 157 if (state != STATE_OPERATOR) { 158 endToken(text, i, state); 159 LineSegment segment = getLastSegment(); 161 if (segment != null && isKeyword(segment.getText())) 162 segment.setFormat(JAVA_FORMAT_KEYWORD); 163 state = STATE_OPERATOR; 164 } 165 ++i; 166 continue; 167 } 168 if (c == '{' || c == '}') { 169 if (state != STATE_BRACE) { 170 endToken(text, i, state); 171 LineSegment segment = getLastSegment(); 173 if (segment != null && isKeyword(segment.getText())) 174 segment.setFormat(JAVA_FORMAT_KEYWORD); 175 state = STATE_BRACE; 176 } 177 ++i; 178 continue; 179 } 180 if (state == STATE_OPERATOR || state == STATE_BRACE) { 181 if (Character.isJavaIdentifierStart(c)) { 182 endToken(text, i, state); 183 state = STATE_IDENTIFIER; 184 } else if (Character.isDigit(c)) { 185 endToken(text, i, state); 186 state = STATE_NUMBER; 187 } else { 188 endToken(text, i, state); 189 state = STATE_NEUTRAL; 190 } 191 ++i; 192 continue; 193 } 194 if (state == STATE_IDENTIFIER) { 195 if (!Character.isJavaIdentifierPart(c)) { 196 endToken(text, i, state); 197 LineSegment segment = getLastSegment(); 199 if (segment != null) { 200 String segmentText = segment.getText(); 201 if (!isPreprocessorLine && isKeyword(segmentText)) 202 segment.setFormat(JAVA_FORMAT_KEYWORD); 203 else if (c == '(') 204 segment.setFormat(JAVA_FORMAT_FUNCTION); 205 else if (Character.isWhitespace(c)) { 206 int j = i + 1; 208 while (j < limit && Character.isWhitespace(c = text.charAt(j))) 209 ++j; 210 if (c == '(') 211 segment.setFormat(JAVA_FORMAT_FUNCTION); 212 } 213 } 214 state = STATE_NEUTRAL; 215 } 216 ++i; 217 continue; 218 } 219 if (state == STATE_NUMBER) { 220 if (Character.isDigit(c)) 221 ; 222 else if (c == 'u' || c == 'U' || c == 'l' || c == 'L') 223 ; 224 else if (i - tokenBegin == 1 && c == 'x' || c == 'X') 225 state = STATE_HEXNUMBER; 226 else { 227 endToken(text, i, state); 228 if (Character.isJavaIdentifierStart(c)) 229 state = STATE_IDENTIFIER; 230 else 231 state = STATE_NEUTRAL; 232 } 233 ++i; 234 continue; 235 } 236 if (state == STATE_HEXNUMBER) { 237 if (Character.isDigit(c)) 238 ; 239 else if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) 240 ; 241 else if (c == 'u' || c == 'U' || c == 'l' || c == 'L') 242 ; 243 else { 244 endToken(text, i, state); 245 if (Character.isJavaIdentifierStart(c)) 246 state = STATE_IDENTIFIER; 247 else 248 state = STATE_NEUTRAL; 249 } 250 ++i; 251 continue; 252 } 253 if (state == STATE_NEUTRAL) { 254 if (Character.isJavaIdentifierStart(c)) { 255 endToken(text, i, state); 256 state = STATE_IDENTIFIER; 257 } else if (Character.isDigit(c)) { 258 endToken(text, i, state); 259 state = STATE_NUMBER; 260 } 261 } 262 ++i; 263 } 264 endToken(text, i, state); 266 if (state == STATE_IDENTIFIER) { 267 LineSegment segment = getLastSegment(); 269 if (segment != null && isKeyword(segment.getText())) 270 segment.setFormat(JAVA_FORMAT_KEYWORD); 271 } 272 } 273 274 public LineSegmentList formatLine(Line line) 275 { 276 clearSegmentList(); 277 if (line == null) { 278 addSegment("", JAVA_FORMAT_TEXT); 279 return segmentList; 280 } 281 parseLine(line); 282 return segmentList; 283 } 284 285 public boolean parseBuffer() 286 { 287 int state = STATE_NEUTRAL; 288 Line line = buffer.getFirstLine(); 289 boolean changed = false; 290 while (line != null) { 291 int oldflags = line.flags(); 292 if (state == STATE_QUOTE && language == LANGUAGE_JAVA) 294 state = STATE_NEUTRAL; 295 296 if (state != oldflags) { 297 line.setFlags(state); 298 changed = true; 299 } 300 char quoteChar = state == STATE_QUOTE ? '"' : '\0'; 301 final int limit = line.length(); 302 for (int i = 0; i < limit; i++) { 303 char c = line.charAt(i); 304 if (c == '\\' && i < limit-1) { 305 ++i; 307 continue; 308 } 309 if (state == STATE_COMMENT) { 310 if (c == '*' && i < limit-1) { 311 c = line.charAt(i+1); 312 if (c == '/') { 313 ++i; 314 state = STATE_NEUTRAL; 315 } 316 } 317 continue; 318 } 319 if (state == STATE_QUOTE) { 320 if (c == quoteChar) { 321 state = STATE_NEUTRAL; 322 quoteChar = '\0'; 323 } 324 continue; 325 } 326 327 if (c == '/' && i < limit-1) { 329 c = line.charAt(++i); 330 if (c == '/') { 331 break; 334 } else if (c == '*') 335 state = STATE_COMMENT; 336 } else if (c == '"' || c == '\'') { 337 state = STATE_QUOTE; 338 quoteChar = c; 339 } 340 } 341 line = line.next(); 342 } 343 buffer.setNeedsParsing(false); 344 return changed; 345 } 346 347 private static final boolean isOperatorChar(char c) 348 { 349 return "!&|<>=+/*-^".indexOf(c) >= 0; 350 } 351 352 public FormatTable getFormatTable() 353 { 354 if (formatTable == null) { 355 formatTable = new FormatTable("JavaMode"); 356 formatTable.addEntryFromPrefs(JAVA_FORMAT_TEXT, "text"); 357 formatTable.addEntryFromPrefs(JAVA_FORMAT_COMMENT, "comment"); 358 formatTable.addEntryFromPrefs(JAVA_FORMAT_STRING, "string"); 359 formatTable.addEntryFromPrefs(JAVA_FORMAT_IDENTIFIER, "identifier", "text"); 360 formatTable.addEntryFromPrefs(JAVA_FORMAT_KEYWORD, "keyword"); 361 formatTable.addEntryFromPrefs(JAVA_FORMAT_FUNCTION, "function"); 362 formatTable.addEntryFromPrefs(JAVA_FORMAT_OPERATOR, "operator"); 363 formatTable.addEntryFromPrefs(JAVA_FORMAT_BRACE, "brace"); 364 formatTable.addEntryFromPrefs(JAVA_FORMAT_NUMBER, "number"); 365 } 366 return formatTable; 367 } 368 } 369 | Popular Tags |