1 21 22 package org.armedbear.j; 23 24 import gnu.regexp.RE; 25 import gnu.regexp.REMatch; 26 import gnu.regexp.UncheckedRE; 27 28 public final class MakefileFormatter extends Formatter 29 { 30 private static final int MAKEFILE_FORMAT_TEXT = 0; 31 private static final int MAKEFILE_FORMAT_COMMENT = 1; 32 private static final int MAKEFILE_FORMAT_STRING = 2; 33 private static final int MAKEFILE_FORMAT_KEYWORD = 3; 34 private static final int MAKEFILE_FORMAT_TARGET = 4; 35 36 private static final int STATE_BACKQUOTE = STATE_LAST + 1; 37 38 private FastStringBuffer sb = new FastStringBuffer(); 39 private int tokStart; 40 41 private static final RE targetRE = new UncheckedRE("^\\S+.*:"); 42 private static final RE assignmentRE = new UncheckedRE("^\\S+\\s*:?="); 43 private static final RE conditionalRE = 44 new UncheckedRE("^(ifn?(eq|def)\\s)|^(else\\s*)|^(endif\\s*)"); 45 46 public MakefileFormatter(Buffer buffer) 47 { 48 this.buffer = buffer; 49 } 50 51 private void endToken(int state) 52 { 53 if (sb.length() > 0) { 54 int format; 55 switch (state) { 56 case STATE_QUOTE: 57 case STATE_SINGLEQUOTE: 58 case STATE_BACKQUOTE: 59 format = MAKEFILE_FORMAT_STRING; 60 break; 61 case STATE_COMMENT: 62 format = MAKEFILE_FORMAT_COMMENT; 63 break; 64 default: 65 format = MAKEFILE_FORMAT_TEXT; 66 break; 67 } 68 addSegment(sb.toString(), format); 69 tokStart += sb.length(); 70 sb.setLength(0); 71 } 72 } 73 74 private void addToken(String s, int format) 75 { 76 int length = s.length(); 77 if (length > 0) { 78 addSegment(s, format); 79 tokStart += length; 80 } 81 } 82 83 private void parseLine(String text, int state) 84 { 85 if (Editor.tabsAreVisible()) 86 text = Utilities.makeTabsVisible(text, buffer.getTabWidth()); 87 else 88 text = Utilities.detab(text, buffer.getTabWidth()); 89 clearSegmentList(); 90 int braceCount = 0; 91 sb.setLength(0); 92 int i = 0; 93 tokStart = 0; 94 if (text.trim().startsWith("#")) { 95 addToken(text, MAKEFILE_FORMAT_COMMENT); 96 return; 97 } 98 REMatch match = conditionalRE.getMatch(text); 100 if (match != null) { 101 addToken(match.toString(), MAKEFILE_FORMAT_KEYWORD); 102 i += match.toString().length(); 103 } else { 104 match = assignmentRE.getMatch(text); 105 if (match != null) { 106 addToken(match.toString(), MAKEFILE_FORMAT_TEXT); 107 i += match.toString().length(); 108 } else { 109 match = targetRE.getMatch(text); 110 if (match != null) { 111 addToken(match.toString(), MAKEFILE_FORMAT_TARGET); 112 i += match.toString().length(); 113 } 114 } 115 } 116 final int limit = text.length(); 117 while (i < limit) { 119 char c = text.charAt(i); 120 if (Character.isWhitespace(c)) { 121 sb.append(c); 122 ++i; 123 } else { 124 endToken(state); 125 break; 126 } 127 } 128 while (i < limit) { 129 char c = text.charAt(i); 130 if (state == STATE_QUOTE) { 131 sb.append(c); 132 if (c == '"') { 133 endToken(state); 134 state = STATE_NEUTRAL; 135 } else if (c == '\\' && i < limit-1) { 136 sb.append(text.charAt(++i)); 138 } 139 ++i; 140 continue; 141 } 142 if (state == STATE_SINGLEQUOTE) { 143 sb.append(c); 144 if (c == '\'') { 145 endToken(state); 146 state = STATE_NEUTRAL; 147 } 148 ++i; 149 continue; 150 } 151 if (state == STATE_BACKQUOTE) { 152 sb.append(c); 153 if (c == '`') { 154 endToken(state); 155 state = STATE_NEUTRAL; 156 } 157 ++i; 158 continue; 159 } 160 if (c == '"') { 162 endToken(state); 163 sb.append(c); 164 state = STATE_QUOTE; 165 ++i; 166 continue; 167 } 168 if (c == '\'') { 169 endToken(state); 170 sb.append(c); 171 state = STATE_SINGLEQUOTE; 172 ++i; 173 continue; 174 } 175 if (c == '`') { 176 endToken(state); 177 sb.append(c); 178 state = STATE_BACKQUOTE; 179 ++i; 180 continue; 181 } 182 if (c == '#') { 183 endToken(state); 184 state = STATE_COMMENT; 185 sb.append(text.substring(i)); 186 endToken(state); 187 return; 188 } 189 if (state == STATE_IDENTIFIER) { 190 if (buffer.mode.isIdentifierPart(c)) 191 sb.append(c); 192 else { 193 endToken(state); 194 sb.append(c); 195 state = STATE_NEUTRAL; 196 } 197 ++i; 198 continue; 199 } 200 if (state == STATE_NUMBER) { 201 if (Character.isDigit(c)) 202 sb.append(c); 203 else { 204 endToken(state); 205 sb.append(c); 206 if (buffer.mode.isIdentifierStart(c)) 207 state = STATE_IDENTIFIER; 208 else 209 state = STATE_NEUTRAL; 210 } 211 ++i; 212 continue; 213 } 214 if (state == STATE_NEUTRAL) { 215 if (buffer.mode.isIdentifierStart(c)) { 216 endToken(state); 217 sb.append(c); 218 state = STATE_IDENTIFIER; 219 } else if (Character.isDigit(c)) { 220 endToken(state); 221 sb.append(c); 222 state = STATE_NUMBER; 223 } else sb.append(c); 225 } 226 ++i; 227 } 228 endToken(state); 229 } 230 231 public LineSegmentList formatLine(Line line) 232 { 233 if (line == null) { 234 clearSegmentList(); 235 addSegment("", MAKEFILE_FORMAT_TEXT); 236 return segmentList; 237 } 238 parseLine(line.getText(), line.flags()); 239 for (int i = 0; i < segmentList.size(); i++) { 240 LineSegment segment = segmentList.getSegment(i); 241 if (segment.getFormat() > 0) 242 continue; 243 String token = segment.getText(); 244 if (isKeyword(token)) 245 segment.setFormat(MAKEFILE_FORMAT_KEYWORD); 246 else 247 segment.setFormat(MAKEFILE_FORMAT_TEXT); 248 } 249 return segmentList; 250 } 251 252 public FormatTable getFormatTable() 253 { 254 if (formatTable == null) { 255 formatTable = new FormatTable("MakefileMode"); 256 formatTable.addEntryFromPrefs(MAKEFILE_FORMAT_TEXT, "text"); 257 formatTable.addEntryFromPrefs(MAKEFILE_FORMAT_COMMENT, "comment"); 258 formatTable.addEntryFromPrefs(MAKEFILE_FORMAT_STRING, "string"); 259 formatTable.addEntryFromPrefs(MAKEFILE_FORMAT_KEYWORD, "keyword"); 260 formatTable.addEntryFromPrefs(MAKEFILE_FORMAT_TARGET, "target"); 261 } 262 return formatTable; 263 } 264 } 265 | Popular Tags |