1 21 22 package org.armedbear.j; 23 24 import java.util.HashSet ; 25 26 public final class VerilogFormatter extends Formatter implements Constants 27 { 28 private static final int VERILOG_FORMAT_TEXT = 0; 29 private static final int VERILOG_FORMAT_COMMENT = 1; 30 private static final int VERILOG_FORMAT_STRING = 2; 31 private static final int VERILOG_FORMAT_IDENTIFIER = 3; 32 private static final int VERILOG_FORMAT_KEYWORD = 4; 33 private static final int VERILOG_FORMAT_COMPILER_DIRECTIVE = 5; 34 private static final int VERILOG_FORMAT_FUNCTION = 6; 35 private static final int VERILOG_FORMAT_OPERATOR = 7; 36 private static final int VERILOG_FORMAT_NUMBER = 8; 37 38 private static final VerilogMode mode = VerilogMode.getMode(); 39 40 public VerilogFormatter(Buffer buffer) 41 { 42 this.buffer = buffer; 43 } 44 45 private int tokenBegin = 0; 46 47 private void endToken(String text, int tokenEnd, int state) 48 { 49 if (tokenEnd - tokenBegin > 0) { 50 int format = VERILOG_FORMAT_TEXT; 51 switch (state) { 52 case STATE_NEUTRAL: 53 format = VERILOG_FORMAT_TEXT; 54 break; 55 case STATE_QUOTE: 56 format = VERILOG_FORMAT_STRING; 57 break; 58 case STATE_IDENTIFIER: 59 format = VERILOG_FORMAT_IDENTIFIER; 60 break; 61 case STATE_COMMENT: 62 format = VERILOG_FORMAT_COMMENT; 63 break; 64 case STATE_OPERATOR: 65 format = VERILOG_FORMAT_OPERATOR; 66 break; 67 case STATE_NUMBER: 68 format = VERILOG_FORMAT_NUMBER; 69 break; 70 } 71 addSegment(text, tokenBegin, tokenEnd, format); 72 tokenBegin = tokenEnd; 73 } 74 } 75 76 private void parseLine(Line line) 77 { 78 if (line == null) { 79 addSegment("", VERILOG_FORMAT_TEXT); 80 return; 81 } 82 String text; 83 if (Editor.tabsAreVisible()) 84 text = Utilities.makeTabsVisible(line.getText(), buffer.getTabWidth()); 85 else 86 text = Utilities.detab(line.getText(), buffer.getTabWidth()); 87 tokenBegin = 0; 88 int state = line.flags(); 89 int i = 0; 90 final int limit = text.length(); 91 while (i < limit) { 93 if (Character.isWhitespace(text.charAt(i))) { 94 ++i; 95 } else { 96 endToken(text, i, state); 97 break; 98 } 99 } 100 while (i < limit) { 101 char c = text.charAt(i); 102 if (state == STATE_COMMENT) { 103 if (i < limit-1 && c == '*' && text.charAt(i+1) == '/') { 104 endToken(text, i + 2, state); 105 state = STATE_NEUTRAL; 106 i += 2; 107 } else 108 ++i; 109 continue; 110 } 111 if (state == STATE_QUOTE) { 112 if (c == '"') { 113 endToken(text, i+1, state); 114 state = STATE_NEUTRAL; 115 } else if (c == '\\' && i < limit-1) { 116 ++i; 118 } 119 ++i; 120 continue; 121 } 122 if (c == '"') { 124 endToken(text, i, state); 125 state = STATE_QUOTE; 126 ++i; 127 continue; 128 } 129 if (c == '/') { 130 if (i < limit-1) { 131 if (text.charAt(i+1) == '*') { 132 endToken(text, i, state); 133 state = STATE_COMMENT; 134 i += 2; 135 } else if (text.charAt(i+1) == '/') { 136 endToken(text, i, state); 137 endToken(text, limit, STATE_COMMENT); 138 return; 139 } else 140 ++i; 141 } else 142 ++i; 143 continue; 144 } 145 if (isOperatorChar(c)) { 146 if (state != STATE_OPERATOR) { 147 endToken(text, i, state); 148 final LineSegment segment = getLastSegment(); 150 if (segment != null) { 151 final String segmentText = segment.getText(); 152 if (isKeyword(segmentText)) 153 segment.setFormat(VERILOG_FORMAT_KEYWORD); 154 else if (isCompilerDirective(segmentText)) 155 segment.setFormat(VERILOG_FORMAT_COMPILER_DIRECTIVE); 156 } 157 state = STATE_OPERATOR; 158 } 159 ++i; 160 continue; 161 } 162 if (state == STATE_OPERATOR) { 163 if (c == '\'') { 164 if (i < limit-1) { 165 c = text.charAt(i+1); 166 if ("bBoOdDhH".indexOf(c) >= 0) { 167 endToken(text, i, state); 168 state = STATE_NUMBER; 169 i += 2; 170 continue; 171 } 172 } 173 } else if (mode.isIdentifierStart(c)) { 174 endToken(text, i, state); 175 state = STATE_IDENTIFIER; 176 } else if (Character.isDigit(c)) { 177 endToken(text, i, state); 178 state = STATE_NUMBER; 179 } else { 180 endToken(text, i, state); 181 state = STATE_NEUTRAL; 182 } 183 ++i; 184 continue; 185 } 186 if (state == STATE_IDENTIFIER) { 187 if (!mode.isIdentifierPart(c)) { 188 endToken(text, i, state); 189 final LineSegment segment = getLastSegment(); 191 if (segment != null) { 192 final String segmentText = segment.getText(); 193 if (isKeyword(segmentText)) { 194 segment.setFormat(VERILOG_FORMAT_KEYWORD); 195 } else if (isCompilerDirective(segmentText)) { 196 segment.setFormat(VERILOG_FORMAT_COMPILER_DIRECTIVE); 197 } else if (c == '(') { 198 segment.setFormat(VERILOG_FORMAT_FUNCTION); 199 } else if (Character.isWhitespace(c)) { 200 int j = i + 1; 202 while (j < limit && Character.isWhitespace(c = text.charAt(j))) 203 ++j; 204 if (c == '(') 205 segment.setFormat(VERILOG_FORMAT_FUNCTION); 206 } 207 } 208 state = STATE_NEUTRAL; 209 } 210 ++i; 211 continue; 212 } 213 if (state == STATE_NUMBER) { 214 if (Character.isDigit(c)) 215 ; 216 else if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) 217 ; else if ("xXzZ?_".indexOf(c) >= 0) 219 ; else if (c == '\'') { 221 if (i < limit-1) { 222 c = text.charAt(i+1); 223 if ("bBoOdDhH".indexOf(c) >= 0) { 224 i += 2; 225 continue; 226 } 227 } 228 } else { 229 endToken(text, i, state); 230 if (mode.isIdentifierStart(c)) 231 state = STATE_IDENTIFIER; 232 else 233 state = STATE_NEUTRAL; 234 } 235 ++i; 236 continue; 237 } 238 if (state == STATE_NEUTRAL) { 239 if (c == '\'') { 240 if (i < limit-1) { 241 c = text.charAt(i+1); 242 if ("bBoOdDhH".indexOf(c) >= 0) { 243 endToken(text, i, state); 244 state = STATE_NUMBER; 245 i += 2; 246 continue; 247 } 248 } 249 } else if (mode.isIdentifierStart(c)) { 250 endToken(text, i, state); 251 state = STATE_IDENTIFIER; 252 } else if (Character.isDigit(c)) { 253 endToken(text, i, state); 254 state = STATE_NUMBER; 255 } 256 } 257 ++i; 258 } 259 endToken(text, i, state); 261 if (state == STATE_IDENTIFIER) { 262 final LineSegment segment = getLastSegment(); 264 if (segment != null) { 265 final String segmentText = segment.getText(); 266 if (isKeyword(segmentText)) 267 segment.setFormat(VERILOG_FORMAT_KEYWORD); 268 else if (isCompilerDirective(segmentText)) 269 segment.setFormat(VERILOG_FORMAT_COMPILER_DIRECTIVE); 270 } 271 } 272 } 273 274 public LineSegmentList formatLine(Line line) 275 { 276 clearSegmentList(); 277 parseLine(line); 278 return segmentList; 279 } 280 281 public boolean parseBuffer() 282 { 283 int state = STATE_NEUTRAL; 284 Line line = buffer.getFirstLine(); 285 boolean changed = false; 286 while (line != null) { 287 int oldflags = line.flags(); 288 if (state == STATE_QUOTE) 290 state = STATE_NEUTRAL; 291 if (state != oldflags) { 292 line.setFlags(state); 293 changed = true; 294 } 295 final int limit = line.length(); 296 for (int i = 0; i < limit; i++) { 297 char c = line.charAt(i); 298 if (c == '\\' && i < limit-1) { 299 ++i; 301 continue; 302 } 303 if (state == STATE_COMMENT) { 304 if (c == '*' && i < limit-1) { 305 c = line.charAt(i+1); 306 if (c == '/') { 307 ++i; 308 state = STATE_NEUTRAL; 309 } 310 } 311 continue; 312 } 313 if (state == STATE_QUOTE) { 314 if (c == '"') 315 state = STATE_NEUTRAL; 316 continue; 317 } 318 if (c == '/' && i < limit-1) { 320 c = line.charAt(++i); 321 if (c == '/') { 322 break; 325 } else if (c == '*') 326 state = STATE_COMMENT; 327 } else if (c == '"') 328 state = STATE_QUOTE; 329 } 330 line = line.next(); 331 } 332 buffer.setNeedsParsing(false); 333 return changed; 334 } 335 336 private static final boolean isOperatorChar(char c) 337 { 338 return "!&|<>=+/*-".indexOf(c) >= 0; 339 } 340 341 public FormatTable getFormatTable() 342 { 343 if (formatTable == null) { 344 formatTable = new FormatTable("VerilogMode"); 345 formatTable.addEntryFromPrefs(VERILOG_FORMAT_TEXT, "text"); 346 formatTable.addEntryFromPrefs(VERILOG_FORMAT_COMMENT, "comment"); 347 formatTable.addEntryFromPrefs(VERILOG_FORMAT_STRING, "string"); 348 formatTable.addEntryFromPrefs(VERILOG_FORMAT_IDENTIFIER, "identifier", "text"); 349 formatTable.addEntryFromPrefs(VERILOG_FORMAT_KEYWORD, "keyword"); 350 formatTable.addEntryFromPrefs(VERILOG_FORMAT_COMPILER_DIRECTIVE, "preprocessor"); 351 formatTable.addEntryFromPrefs(VERILOG_FORMAT_FUNCTION, "function"); 352 formatTable.addEntryFromPrefs(VERILOG_FORMAT_OPERATOR, "operator"); 353 formatTable.addEntryFromPrefs(VERILOG_FORMAT_NUMBER, "number"); 354 } 355 return formatTable; 356 } 357 358 private static boolean isCompilerDirective(String s) 359 { 360 if (s.length() > 0 && s.charAt(0) == '`') 361 return getCompilerDirectives().contains(s); 362 return false; 363 } 364 365 private static HashSet compilerDirectiveHashSet; 366 367 private static HashSet getCompilerDirectives() 368 { 369 if (compilerDirectiveHashSet == null) { 370 String [] array = compilerDirectives; 371 int count = array.length; 372 compilerDirectiveHashSet = new HashSet (Math.max(2 * count, 11)); 373 for (int i = count - 1; i >= 0; i--) 374 compilerDirectiveHashSet.add(array[i]); 375 } 376 return compilerDirectiveHashSet; 377 } 378 379 private static String [] compilerDirectives = { 380 "`autoexpand_vectornets", 381 "`celldefine", 382 "`default_nettype", 383 "`define", 384 "`delay_mode_distributed", 385 "`delay_mode_path", 386 "`delay_mode_unit", 387 "`delay_mode_zero", 388 "`else", 389 "`endcelldefine", 390 "`endif", 391 "`endprotect", 392 "`endprotected", 393 "`expand_vectornets", 394 "`ifdef", 395 "`ifndef", 396 "`include", 397 "`noexpand_vectornets", 398 "`noremove_gatename", 399 "`noremove_netname", 400 "`nounconnected_drive", 401 "`protect", 402 "`protected", 403 "`remove_gatename", 404 "`remove_netname", 405 "`reset_all", 406 "`signed", 407 "`timescale", 408 "`unconnected_drive", 409 "`undef", 410 "`unsigned", 411 "`uselib" 412 }; 413 } 414 | Popular Tags |