1 11 package org.eclipse.ant.internal.ui.dtd.schema; 12 13 import com.ibm.icu.text.MessageFormat; 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 19 import org.eclipse.ant.internal.ui.dtd.ParseError; 20 import org.eclipse.ant.internal.ui.dtd.util.SortedMap; 21 import org.eclipse.ant.internal.ui.dtd.util.SortedMapFactory; 22 23 48 public class NfmParser { 49 50 public Dfm parse(Nfm nfm) throws ParseError { 51 52 54 Dfm dfm = parseStart(nfm.getStart(), nfm.getStop()); 55 56 58 ArrayList dfms = new ArrayList (); 59 collect(dfm, dfms); 60 61 63 HashMap duplicates = new HashMap (); 64 detect(dfms, duplicates); 65 66 68 replace(dfms, duplicates); 69 70 72 Nfm.free(nfm); 73 NfmNode.freeAll(); 74 75 return dfm; 76 } 77 78 private void reportError(String name) throws ParseError { 79 throw new ParseError(MessageFormat.format(AntDTDSchemaMessages.NfmParser_Ambiguous, new String []{name})); 80 } 81 82 public static void collect(Dfm dfm, List dfms) { 83 dfms.add(dfm); 84 collect1(dfm, dfms); 85 } 86 87 private static void collect1(Dfm dfm, List dfms) { 88 Object [] follows = dfm.getValues(); 89 if (follows != null) { 90 for (int i = 0; i < follows.length; i++) { 91 Dfm follow = (Dfm) follows[i]; 92 if (!dfms.contains(follow)) { 93 dfms.add(follow); 94 collect1(follow, dfms); 95 } 96 } 97 } 98 } 99 100 101 104 private void replace(ArrayList dfms, HashMap removed) { 105 for (int i = 0; i < dfms.size(); i++) { 106 Dfm dfm = (Dfm) dfms.get(i); 107 Object [] follows = dfm.getValues(); 108 if (follows != null) { 109 for (int j = 0; j < follows.length; j++) { 110 Dfm replacement, follow = (Dfm) follows[j]; 111 while ((replacement = (Dfm) removed.get(follow)) != null) 112 follow = replacement; 113 follows[j] = follow; 114 } 115 } 116 } 117 118 Iterator rit = removed.keySet().iterator(); 120 while (rit.hasNext()) 121 Dfm.free((Dfm)rit.next()); 122 } 123 124 125 140 private void detect(ArrayList dfms, HashMap duplicates) throws ParseError { 141 for (Iterator iter = dfms.iterator(); iter.hasNext();) { 142 Dfm dfm = (Dfm) iter.next(); 143 144 Object [] accepts = dfm.getKeys(); 145 Object [] follows = dfm.getValues(); 146 if (accepts != null) { 147 String last = null; 148 for (int i = 0, lasti = -1; i < accepts.length; i++) { 149 String accept = accepts[i].toString(); 150 152 if (last != null && last == accept) { 153 if (follows[i] != follows[lasti]) 154 checkConflict(new Conflict(accept, (Dfm)follows[lasti], (Dfm)follows[i])); 155 } 156 else { 157 last = accept; 158 lasti = i; 159 } 160 } 161 } 162 } 163 164 166 for (Iterator iter = dfms.iterator(); iter.hasNext();) { 167 Dfm dfm = (Dfm) iter.next(); 168 169 Object [] accepts = dfm.getKeys(); 171 Object [] follows = dfm.getValues(); 172 boolean remove = false; 173 if (accepts != null) { 174 boolean[] removes = new boolean[accepts.length]; 175 String last = null; 176 for (int i = 0, lasti = -1; i < accepts.length; i++) { 177 String accept = accepts[i].toString(); 178 179 if (last != null && last == accept) { 180 remove = true; 181 removes[i] = true; 182 if (follows[i] != follows[lasti]) { 183 Dfm dfmhi = (Dfm) follows[i]; 184 Dfm dfmlo = (Dfm) follows[lasti]; 185 if (dfmhi.id < dfmlo.id) { 186 Dfm tmp = dfmhi; 187 dfmhi = dfmlo; 188 dfmlo = tmp; 189 } 190 Dfm dup = (Dfm) duplicates.get(dfmhi); 191 if (dup == null || dfmlo.id < dup.id) { 192 duplicates.put(dfmhi, dfmlo); 193 } else { 194 duplicates.put(dfmlo, dup); 195 } 196 } 197 } 198 else { 199 last = accept; 200 lasti = i; 201 } 202 } 203 204 if (remove) { 205 SortedMap map = dfm.getMap(); 206 int i = 0; 207 for (Iterator iterator = map.keyIterator(); iterator.hasNext(); i++) { 208 iterator.next(); 209 if (removes[i]) 210 iterator.remove(); 211 } 212 SortedMapFactory.freeMap(map); 213 } 214 } 215 } 216 } 217 218 222 private void checkConflict(Conflict conflict) throws ParseError { 223 if (conflict.dfm1.accepting != conflict.dfm2.accepting) { 224 reportError(conflict.name); 225 } 226 Object [] accept1 = conflict.dfm1.getKeys(); 227 Object [] accept2 = conflict.dfm2.getKeys(); 228 if ((accept1 == null) != (accept2 == null)) { 229 reportError(conflict.name); 230 } 231 if (accept1 != null) { 232 if (accept1.length != accept2.length) { 233 reportError(conflict.name); 234 } 235 for (int j = 0; j < accept2.length; j++) { 236 if (accept1[j] != accept2[j]) { 237 reportError(conflict.name); 238 } 239 } 240 } 241 } 242 243 247 private Dfm parseStart(NfmNode start, NfmNode accept) { 248 Dfm result = Dfm.dfm(false); 250 start.dfm = result; 251 252 while (start.next1 != null && start.next2 == null && start.symbol == null) { 254 start = start.next1; 255 start.dfm = result; 256 } 257 258 Dfm parsed = parse(1, start, accept); 259 result.merge(parsed); 260 261 Dfm.free(parsed); 262 263 return result; 264 } 265 266 private void parseNext(int mark, Dfm result, NfmNode start, NfmNode accept) { 267 Dfm parsed = parse(mark+1, start, accept); 268 result.merge(parsed); 269 270 Dfm.free(parsed); 271 } 272 273 277 private Dfm parse(int mark, NfmNode start, NfmNode accept) { 278 279 while (start.next1 != null && start.next2 == null && start.symbol == null) 281 start = start.next1; 282 283 if (start == accept) 285 return Dfm.dfm(true); 286 287 if (start.symbol != null) { 289 Dfm nextdfm = null; 290 NfmNode next = start.next1, snext = next; 291 while (snext.dfm == null && snext.next1 != null && snext.next2 == null && snext.symbol == null) 292 snext = snext.next1; 293 if (snext.dfm != null) { 294 for (NfmNode n = next; n != snext; n = n.next1) 295 n.dfm = snext.dfm; 296 nextdfm = snext.dfm; 297 } 298 else { 299 nextdfm = Dfm.dfm(false); 300 snext.dfm = nextdfm; 301 for (NfmNode n = next; n != snext; n = n.next1) 302 n.dfm = nextdfm; 303 parseNext(mark, nextdfm, snext, accept); 304 } 305 Dfm dfm = Dfm.dfm(start.symbol, nextdfm); 306 return dfm; 307 } 308 309 Dfm dfm1 = null, dfm2 = null; 311 int saveMark; 312 if (start.next1 != null && start.next1.mark != mark) { 313 saveMark = start.next1.mark; 314 start.next1.mark = mark; 315 dfm1 = parse(mark, start.next1, accept); 316 start.next1.mark = saveMark; 317 } 318 if (start.next2 != null && start.next2.mark != mark) { 319 saveMark = start.next2.mark; 320 start.next2.mark = mark; 321 dfm2 = parse(mark, start.next2, accept); 322 start.next2.mark = saveMark; 323 } 324 325 if (dfm2 != null) { 326 if (dfm1 != null) 327 dfm1.merge(dfm2); 328 else 329 dfm1 = dfm2; 330 } 331 return dfm1; 332 } 333 334 private static class Conflict { 335 public String name; 336 public Dfm dfm1, dfm2; 337 public Conflict(String name, Dfm dfm1, Dfm dfm2) { 338 this.name = name; 339 this.dfm1 = dfm1; 340 this.dfm2 = dfm2; 341 } 342 public int hashCode() { 343 return dfm1.hashCode() + dfm2.hashCode(); 344 } 345 public boolean equals(Object o) { 346 if (o == this) 347 return true; 348 if (!(o instanceof Conflict)) 349 return false; 350 Conflict other = (Conflict) o; 351 return (dfm1 == other.dfm1 && dfm2 == other.dfm2) 352 || (dfm1 == other.dfm2 && dfm2 == other.dfm1); 353 } 354 } 355 356 } 357 | Popular Tags |