1 21 22 package net.percederberg.grammatica; 23 24 import net.percederberg.grammatica.parser.Node; 25 import net.percederberg.grammatica.parser.ParseException; 26 import net.percederberg.grammatica.parser.ParserCreationException; 27 import net.percederberg.grammatica.parser.Production; 28 import net.percederberg.grammatica.parser.ProductionPattern; 29 import net.percederberg.grammatica.parser.ProductionPatternAlternative; 30 import net.percederberg.grammatica.parser.ProductionPatternElement; 31 import net.percederberg.grammatica.parser.Token; 32 import net.percederberg.grammatica.parser.TokenPattern; 33 34 43 class SecondPassAnalyzer extends GrammarAnalyzer { 44 45 48 private Grammar grammar; 49 50 55 private ProductionPattern currentProduction = null; 56 57 60 private int nextSynteticId = 3001; 61 62 67 public SecondPassAnalyzer(Grammar grammar) { 68 this.grammar = grammar; 69 } 70 71 81 protected Node exitIdentifier(Token node) throws ParseException { 82 String name = node.getImage(); 83 TokenPattern token = grammar.getTokenPatternByName(name); 84 ProductionPattern prod = grammar.getProductionPatternByName(name); 85 86 if (token != null) { 87 node.addValue(token); 88 } else if (prod != null) { 89 node.addValue(prod); 90 } else { 91 throw new ParseException( 92 ParseException.ANALYSIS_ERROR, 93 "unrecognized identifier '" + name + "'", 94 node.getStartLine(), 95 node.getStartColumn()); 96 } 97 return node; 98 } 99 100 110 protected Node exitQuotedString(Token node) throws ParseException { 111 String str; 112 TokenPattern token; 113 114 str = node.getImage(); 115 str = str.substring(1, str.length() - 1); 116 token = grammar.getTokenPatternByImage(str); 117 if (token != null) { 118 node.addValue(token); 119 } else { 120 throw new ParseException( 121 ParseException.ANALYSIS_ERROR, 122 "unrecognized token \"" + str + "\"", 123 node.getStartLine(), 124 node.getStartColumn()); 125 } 126 return node; 127 } 128 129 136 protected Node exitGrammar(Production node) { 137 return null; 138 } 139 140 148 protected Node exitProductionPart(Production node) { 149 return null; 150 } 151 152 162 protected void childProductionDeclaration(Production node, Node child) 163 throws ParseException { 164 165 super.childProductionDeclaration(node, child); 166 if (child.getId() == GrammarConstants.IDENTIFIER) { 167 currentProduction = (ProductionPattern) child.getValue(0); 168 } 169 } 170 171 182 protected Node exitProductionDeclaration(Production node) 183 throws ParseException { 184 185 ProductionPattern pattern; 186 ProductionPatternAlternative alt; 187 Node child; 188 189 pattern = (ProductionPattern) getValue(getChildAt(node, 0), 0); 190 child = getChildAt(node, 2); 191 for (int i = 0; i < child.getValueCount(); i++) { 192 alt = (ProductionPatternAlternative) getValue(child, i); 193 try { 194 pattern.addAlternative(alt); 195 } catch (ParserCreationException e) { 196 throw new ParseException( 197 ParseException.ANALYSIS_ERROR, 198 e.getMessage(), 199 node.getStartLine(), 200 node.getStartColumn()); 201 } 202 } 203 return null; 204 } 205 206 215 protected Node exitProduction(Production node) throws ParseException { 216 ProductionPatternAlternative alt; 217 ProductionPatternElement elem; 218 Node child; 219 220 alt = new ProductionPatternAlternative(); 221 node.addValue(alt); 222 for (int i = 0; i < node.getChildCount(); i++) { 223 child = getChildAt(node, i); 224 if (child.getId() == GrammarConstants.PRODUCTION_ATOM) { 225 for (int j = 0; j < child.getValueCount(); j++) { 226 elem = (ProductionPatternElement) getValue(child, j); 227 alt.addElement(elem); 228 } 229 } else if (child.getId() == GrammarConstants.PRODUCTION) { 230 node.addValues(child.getAllValues()); 231 } 232 } 233 234 return node; 235 } 236 237 246 protected Node exitProductionAtom(Production node) 247 throws ParseException { 248 249 Node child; 250 boolean token = false; 251 int id = 0; 252 int min = 1; 253 int max = 1; 254 Object obj; 255 256 child = getChildAt(node, 0); 258 switch (child.getId()) { 259 case GrammarConstants.IDENTIFIER: 260 obj = getValue(child, 0); 261 if (obj instanceof TokenPattern) { 262 token = true; 263 id = ((TokenPattern) obj).getId(); 264 } else { 265 token = false; 266 id = ((ProductionPattern) obj).getId(); 267 } 268 break; 269 case GrammarConstants.QUOTED_STRING: 270 token = true; 271 id = ((TokenPattern) getValue(child, 0)).getId(); 272 break; 273 case GrammarConstants.LEFT_PAREN: 274 case GrammarConstants.LEFT_BRACE: 275 case GrammarConstants.LEFT_BRACKET: 276 ProductionPatternElement elem; 277 278 if (child.getId() == GrammarConstants.LEFT_BRACE) { 279 min = 0; 280 max = -1; 281 } else if (child.getId() == GrammarConstants.LEFT_BRACKET) { 282 min = 0; 283 max = 1; 284 } 285 elem = getProductionElement(getChildAt(node, 1)); 286 token = elem.isToken(); 287 id = elem.getId(); 288 break; 289 } 290 291 child = getChildAt(node, node.getChildCount() - 1); 293 if (child.getId() == GrammarConstants.QUESTION_MARK) { 294 min = 0; 295 max = 1; 296 } else if (child.getId() == GrammarConstants.ASTERISK) { 297 min = 0; 298 max = -1; 299 } else if (child.getId() == GrammarConstants.PLUS_SIGN) { 300 min = 1; 301 max = -1; 302 } 303 304 node.addValue(new ProductionPatternElement(token, id, min, max)); 306 return node; 307 } 308 309 323 private ProductionPatternElement getProductionElement(Node node) 324 throws ParseException { 325 326 ProductionPattern prod; 327 ProductionPatternAlternative alt; 328 String str; 329 330 alt = (ProductionPatternAlternative) getValue(node, 0); 331 if (node.getValueCount() == 1 && isSimple(alt)) { 332 return alt.getElement(0); 333 } else { 334 str = currentProduction.getName() + "(" + 335 (nextSynteticId - 3000) + ")"; 336 prod = new ProductionPattern(nextSynteticId, str); 337 prod.setSynthetic(true); 338 for (int i = 0; i < node.getValueCount(); i++) { 339 alt = (ProductionPatternAlternative) getValue(node, i); 340 try { 341 prod.addAlternative(alt); 342 } catch (ParserCreationException e) { 343 throw new ParseException( 344 ParseException.ANALYSIS_ERROR, 345 e.getMessage(), 346 node.getStartLine(), 347 node.getStartColumn()); 348 } 349 } 350 grammar.addProduction(prod, 351 node.getStartLine(), 352 node.getEndLine()); 353 return new ProductionPatternElement(false, 354 nextSynteticId++, 355 1, 356 1); 357 } 358 } 359 360 369 private boolean isSimple(ProductionPatternAlternative alt) { 370 return alt.getElementCount() == 1 371 && alt.getMinElementCount() == 1 372 && alt.getMaxElementCount() == 1; 373 } 374 } 375 | Popular Tags |