1 22 23 package org.javacc.parser; 24 25 import java.util.Vector ; 26 27 public class LookaheadCalc extends JavaCCGlobals { 28 29 static MatchInfo overlap(Vector v1, Vector v2) { 30 MatchInfo m1, m2, m3; 31 int size; 32 boolean diff; 33 for (int i = 0; i < v1.size(); i++) { 34 m1 = (MatchInfo)v1.elementAt(i); 35 for (int j = 0; j < v2.size(); j++) { 36 m2 = (MatchInfo)v2.elementAt(j); 37 size = m1.firstFreeLoc; m3 = m1; 38 if (size > m2.firstFreeLoc) { 39 size = m2.firstFreeLoc; m3 = m2; 40 } 41 if (size == 0) return null; 42 diff = false; 44 for (int k = 0; k < size; k++) { 45 if (m1.match[k] != m2.match[k]) { 46 diff = true; 47 break; 48 } 49 } 50 if (!diff) return m3; 51 } 52 } 53 return null; 54 } 55 56 static boolean javaCodeCheck(Vector v) { 57 for (int i = 0; i < v.size(); i++) { 58 if (((MatchInfo)v.elementAt(i)).firstFreeLoc == 0) { 59 return true; 60 } 61 } 62 return false; 63 } 64 65 static String image(MatchInfo m) { 66 String ret = ""; 67 for (int i = 0; i < m.firstFreeLoc; i++) { 68 if (m.match[i] == 0) { 69 ret += " <EOF>"; 70 } else { 71 RegularExpression re = (RegularExpression)rexps_of_tokens.get(new Integer (m.match[i])); 72 if (re instanceof RStringLiteral) { 73 ret += " \"" + add_escapes(((RStringLiteral)re).image) + "\""; 74 } else if (re.label != null && !re.label.equals("")) { 75 ret += " <" + re.label + ">"; 76 } else { 77 ret += " <token of kind " + i + ">"; 78 } 79 } 80 } 81 if (m.firstFreeLoc == 0) { 82 return ""; 83 } else { 84 return ret.substring(1); 85 } 86 } 87 88 public static void choiceCalc(Choice ch) { 89 int first = firstChoice(ch); 90 Vector [] dbl = new Vector [ch.choices.size()]; 94 Vector [] dbr = new Vector [ch.choices.size()]; 95 int[] minLA = new int[ch.choices.size()-1]; 96 MatchInfo[] overlapInfo = new MatchInfo[ch.choices.size()-1]; 97 int[] other = new int[ch.choices.size()-1]; 98 MatchInfo m; 99 Vector v; 100 boolean overlapDetected; 101 for (int la = 1; la <= Options.getChoiceAmbiguityCheck(); la++) { 102 MatchInfo.laLimit = la; 103 LookaheadWalk.considerSemanticLA = !Options.getForceLaCheck(); 104 for (int i = first; i < ch.choices.size()-1; i++) { 105 LookaheadWalk.sizeLimitedMatches = new java.util.Vector (); 106 m = new MatchInfo(); 107 m.firstFreeLoc = 0; 108 v = new java.util.Vector (); 109 v.addElement(m); 110 LookaheadWalk.genFirstSet(v, (Expansion)ch.choices.elementAt(i)); 111 dbl[i] = LookaheadWalk.sizeLimitedMatches; 112 } 113 LookaheadWalk.considerSemanticLA = false; 114 for (int i = first+1; i < ch.choices.size(); i++) { 115 LookaheadWalk.sizeLimitedMatches = new java.util.Vector (); 116 m = new MatchInfo(); 117 m.firstFreeLoc = 0; 118 v = new java.util.Vector (); 119 v.addElement(m); 120 LookaheadWalk.genFirstSet(v, (Expansion)ch.choices.elementAt(i)); 121 dbr[i] = LookaheadWalk.sizeLimitedMatches; 122 } 123 if (la == 1) { 124 for (int i = first; i < ch.choices.size()-1; i++) { 125 Expansion exp = (Expansion)ch.choices.elementAt(i); 126 if (Semanticize.emptyExpansionExists(exp)) { 127 JavaCCErrors.warning(exp, "This choice can expand to the empty token sequence and will therefore always be taken in favor of the choices appearing later."); 128 break; 129 } else if (javaCodeCheck(dbl[i])) { 130 JavaCCErrors.warning(exp, "JAVACODE non-terminal will force this choice to be taken in favor of the choices appearing later."); 131 break; 132 } 133 } 134 } 135 overlapDetected = false; 136 for (int i = first; i < ch.choices.size()-1; i++) { 137 for (int j = i+1; j < ch.choices.size(); j++) { 138 if ((m = overlap(dbl[i], dbr[j])) != null) { 139 minLA[i] = la+1; 140 overlapInfo[i] = m; 141 other[i] = j; 142 overlapDetected = true; 143 break; 144 } 145 } 146 } 147 if (!overlapDetected) { 148 break; 149 } 150 } 151 for (int i = first; i < ch.choices.size()-1; i++) { 152 if (explicitLA((Expansion)ch.choices.elementAt(i)) && !Options.getForceLaCheck()) { 153 continue; 154 } 155 if (minLA[i] > Options.getChoiceAmbiguityCheck()) { 156 JavaCCErrors.warning("Choice conflict involving two expansions at"); 157 System.err.print(" line " + ((Expansion)ch.choices.elementAt(i)).line); 158 System.err.print(", column " + ((Expansion)ch.choices.elementAt(i)).column); 159 System.err.print(" and line " + ((Expansion)ch.choices.elementAt(other[i])).line); 160 System.err.print(", column " + ((Expansion)ch.choices.elementAt(other[i])).column); 161 System.err.println(" respectively."); 162 System.err.println(" A common prefix is: " + image(overlapInfo[i])); 163 System.err.println(" Consider using a lookahead of " + minLA[i] + " or more for earlier expansion."); 164 } else if (minLA[i] > 1) { 165 JavaCCErrors.warning("Choice conflict involving two expansions at"); 166 System.err.print(" line " + ((Expansion)ch.choices.elementAt(i)).line); 167 System.err.print(", column " + ((Expansion)ch.choices.elementAt(i)).column); 168 System.err.print(" and line " + ((Expansion)ch.choices.elementAt(other[i])).line); 169 System.err.print(", column " + ((Expansion)ch.choices.elementAt(other[i])).column); 170 System.err.println(" respectively."); 171 System.err.println(" A common prefix is: " + image(overlapInfo[i])); 172 System.err.println(" Consider using a lookahead of " + minLA[i] + " for earlier expansion."); 173 } 174 } 175 } 176 177 static boolean explicitLA(Expansion exp) { 178 if (!(exp instanceof Sequence)) { 179 return false; 180 } 181 Sequence seq = (Sequence)exp; 182 Object obj = seq.units.elementAt(0); 183 if (!(obj instanceof Lookahead)) { 184 return false; 185 } 186 Lookahead la = (Lookahead)obj; 187 return la.isExplicit; 188 } 189 190 static int firstChoice(Choice ch) { 191 if (Options.getForceLaCheck()) { 192 return 0; 193 } 194 for (int i = 0; i < ch.choices.size(); i++) { 195 if (!explicitLA((Expansion)ch.choices.elementAt(i))) { 196 return i; 197 } 198 } 199 return ch.choices.size(); 200 } 201 202 private static String image(Expansion exp) { 203 if (exp instanceof OneOrMore) { 204 return "(...)+"; 205 } else if (exp instanceof ZeroOrMore) { 206 return "(...)*"; 207 } else { 208 return "[...]"; 209 } 210 } 211 212 public static void ebnfCalc(Expansion exp, Expansion nested) { 213 MatchInfo m, m1 = null; 215 Vector v, first, follow; 216 int la; 217 for (la = 1; la <= Options.getOtherAmbiguityCheck(); la++) { 218 MatchInfo.laLimit = la; 219 LookaheadWalk.sizeLimitedMatches = new java.util.Vector (); 220 m = new MatchInfo(); 221 m.firstFreeLoc = 0; 222 v = new java.util.Vector (); 223 v.addElement(m); 224 LookaheadWalk.considerSemanticLA = !Options.getForceLaCheck(); 225 LookaheadWalk.genFirstSet(v, nested); 226 first = LookaheadWalk.sizeLimitedMatches; 227 LookaheadWalk.sizeLimitedMatches = new java.util.Vector (); 228 LookaheadWalk.considerSemanticLA = false; 229 LookaheadWalk.genFollowSet(v, exp, Expansion.nextGenerationIndex++); 230 follow = LookaheadWalk.sizeLimitedMatches; 231 if (la == 1) { 232 if (javaCodeCheck(first)) { 233 JavaCCErrors.warning(nested, "JAVACODE non-terminal within " + image(exp) + " construct will force this construct to be entered in favor of expansions occurring after construct."); 234 } 235 } 236 if ((m = overlap(first, follow)) == null) { 237 break; 238 } 239 m1 = m; 240 } 241 if (la > Options.getOtherAmbiguityCheck()) { 242 JavaCCErrors.warning("Choice conflict in " + image(exp) + " construct at line " + exp.line + ", column " + exp.column + "."); 243 System.err.println(" Expansion nested within construct and expansion following construct"); 244 System.err.println(" have common prefixes, one of which is: " + image(m1)); 245 System.err.println(" Consider using a lookahead of " + la + " or more for nested expansion."); 246 } else if (la > 1) { 247 JavaCCErrors.warning("Choice conflict in " + image(exp) + " construct at line " + exp.line + ", column " + exp.column + "."); 248 System.err.println(" Expansion nested within construct and expansion following construct"); 249 System.err.println(" have common prefixes, one of which is: " + image(m1)); 250 System.err.println(" Consider using a lookahead of " + la + " for nested expansion."); 251 } 252 } 253 254 } 255 | Popular Tags |