1 31 32 33 package org.antlr.works.grammar; 34 35 import antlr.RecognitionException; 36 import antlr.TokenStreamException; 37 import org.antlr.Tool; 38 import org.antlr.analysis.NFAState; 39 import org.antlr.tool.*; 40 import org.antlr.works.ate.syntax.misc.ATEToken; 41 import org.antlr.works.components.grammar.CEditorGrammar; 42 import org.antlr.works.prefs.AWPrefs; 43 import org.antlr.works.syntax.element.ElementGrammarName; 44 import org.antlr.works.syntax.element.ElementRule; 45 import org.antlr.works.utils.Console; 46 import org.antlr.works.utils.ErrorListener; 47 import org.antlr.works.utils.Utils; 48 49 import javax.swing.*; 50 import java.util.ArrayList ; 51 import java.util.List ; 52 import java.util.Set ; 53 54 public class EngineGrammar { 55 56 protected Grammar parserGrammar; 57 protected Grammar lexerGrammar; 58 protected List <EngineGrammarError> errors; 59 60 protected boolean grammarDirty; 61 protected boolean grammarAnalyzeDirty; 62 63 protected CEditorGrammar editor; 64 65 public EngineGrammar(CEditorGrammar editor) { 66 this.editor = editor; 67 errors = new ArrayList <EngineGrammarError>(); 68 makeDirty(); 69 } 70 71 public void makeDirty() { 72 grammarDirty = true; 73 grammarAnalyzeDirty = true; 74 } 75 76 public boolean isDirty() { 77 return grammarDirty || grammarAnalyzeDirty; 78 } 79 80 public Grammar getParserGrammar() { 81 return parserGrammar; 82 } 83 84 public Grammar getLexerGrammar() { 85 return lexerGrammar; 86 } 87 88 public NFAState getRuleStartState(String name) throws Exception { 89 Grammar g; 90 createGrammars(); 91 if(ATEToken.isLexerName(name)) 92 g = getLexerGrammar(); 93 else 94 g = getParserGrammar(); 95 96 return g == null ? null:g.getRuleStartState(name); 97 } 98 99 public Grammar getGrammarForRule(String name) throws Exception { 100 createGrammars(); 101 if(ATEToken.isLexerName(name)) 102 return getLexerGrammar(); 103 else 104 return getParserGrammar(); 105 } 106 107 public List <EngineGrammarError> getErrors() { 108 return errors; 109 } 110 111 public boolean isTreeParserGrammar() { 112 return getType() == ElementGrammarName.TREEPARSER; 113 } 114 115 public boolean hasGrammar() { 116 switch(getType()) { 117 case ElementGrammarName.COMBINED: 118 return parserGrammar != null; 119 case ElementGrammarName.TREEPARSER: 120 case ElementGrammarName.PARSER: 121 return parserGrammar != null; 122 case ElementGrammarName.LEXER: 123 return lexerGrammar != null; 124 } 125 return false; 126 } 127 128 public Grammar getANTLRGrammar() { 129 switch(getType()) { 130 case ElementGrammarName.COMBINED: 131 return parserGrammar; 132 case ElementGrammarName.TREEPARSER: 133 case ElementGrammarName.PARSER: 134 return parserGrammar; 135 case ElementGrammarName.LEXER: 136 return lexerGrammar; 137 } 138 return null; 139 } 140 141 public Tool getANTLRTool() { 142 String [] params = AWPrefs.getANTLR3Options(); 143 if(editor.getFileFolder() != null) { 144 params = Utils.concat(params, new String [] { "-lib", editor.getFileFolder() }); 145 } 146 return new Tool(params); 147 } 148 149 public String getName() { 150 ElementGrammarName name = editor.parserEngine.getName(); 151 if(name == null) 152 return null; 153 else 154 return name.getName(); 155 } 156 157 public int getType() { 158 ElementGrammarName name = editor.parserEngine.getName(); 159 if(name == null) 160 return ElementGrammarName.COMBINED; 161 else 162 return name.getType(); 163 } 164 165 public boolean createGrammars() throws Exception { 166 if(!grammarDirty) 167 return true; 168 169 ErrorManager.setErrorListener(ErrorListener.shared()); 170 ErrorListener.shared().clear(); 171 172 switch(getType()) { 173 case ElementGrammarName.COMBINED: 174 createCombinedGrammar(); 175 break; 176 case ElementGrammarName.TREEPARSER: 177 case ElementGrammarName.PARSER: 178 createParserGrammar(); 179 break; 180 case ElementGrammarName.LEXER: 181 createLexerGrammar(); 182 break; 183 } 184 185 if(!ErrorListener.shared().hasErrors()) { 186 grammarDirty = false; 187 return false; 188 } else { 189 return true; 190 } 191 } 192 193 public String getFileName() { 194 String fileName = editor.getFileName(); 195 return fileName==null?"<notsaved>":fileName; 196 } 197 198 protected Grammar createNewGrammar(String filename, String content) throws TokenStreamException, RecognitionException { 199 Grammar g = new Grammar(); 200 g.setTool(getANTLRTool()); 201 g.setFileName(filename); 202 g.setGrammarContent(content); 203 return g; 204 } 205 206 protected void createCombinedGrammar() throws Exception { 207 parserGrammar = createNewGrammar(getFileName(), editor.getText()); 208 parserGrammar.createNFAs(); 209 lexerGrammar = createLexerGrammarFromCombinedGrammar(parserGrammar); 210 } 211 212 protected Grammar createLexerGrammarFromCombinedGrammar(Grammar grammar) throws Exception { 213 String lexerGrammarStr = grammar.getLexerGrammar(); 214 if(lexerGrammarStr == null) 215 return null; 216 217 Grammar lexerGrammar = new Grammar(); 218 lexerGrammar.setTool(getANTLRTool()); 219 lexerGrammar.setFileName("<internally-generated-lexer>"); 220 lexerGrammar.importTokenVocabulary(grammar); 221 222 lexerGrammar.setGrammarContent(lexerGrammarStr); 223 lexerGrammar.createNFAs(); 224 225 return lexerGrammar; 226 } 227 228 protected void createParserGrammar() throws TokenStreamException, RecognitionException { 229 parserGrammar = createNewGrammar(getFileName(), editor.getText()); 230 parserGrammar.createNFAs(); 231 } 232 233 protected void createLexerGrammar() throws TokenStreamException, RecognitionException { 234 lexerGrammar = createNewGrammar(getFileName(), editor.getText()); 235 lexerGrammar.createNFAs(); 236 } 237 238 public void printLeftRecursionToConsole(List rules) { 239 StringBuffer info = new StringBuffer (); 240 info.append("Aborting because the following rules are mutually left-recursive:"); 241 for (Object rule : rules) { 242 Set rulesSet = (Set ) rule; 243 info.append("\n "); 244 info.append(rulesSet); 245 } 246 editor.getConsole().println(info.toString(), Console.LEVEL_ERROR); 247 } 248 249 public void markLeftRecursiveRules(List rules) { 250 for (Object rule : rules) { 252 Set rulesSet = (Set ) rule; 253 for (Object aRulesSet : rulesSet) { 254 String name = (String ) aRulesSet; 255 ElementRule r = editor.rules.getRuleWithName(name); 256 if (r == null) 257 continue; 258 r.setLeftRecursiveRulesSet(rulesSet); 259 } 260 } 261 } 262 263 public void analyze() throws Exception { 264 if(!createGrammars()) { 265 return; 266 } 267 268 Grammar g = getANTLRGrammar(); 269 if(g == null) { 270 return; 271 } 272 273 List rules = g.checkAllRulesForLeftRecursion(); 274 if(!rules.isEmpty()) { 275 printLeftRecursionToConsole(rules); 276 markLeftRecursiveRules(rules); 277 } 278 279 if(ErrorManager.doNotAttemptAnalysis()) { 280 return; 281 } 282 283 if(!grammarAnalyzeDirty) { 284 return; 285 } 286 287 ErrorManager.setErrorListener(ErrorListener.shared()); 288 290 try { 291 g.createLookaheadDFAs(); 292 if(getType() == ElementGrammarName.COMBINED) { 293 if(lexerGrammar != null) 295 lexerGrammar.createLookaheadDFAs(); 296 } 297 298 buildNonDeterministicErrors(); 299 markRulesWithWarningsOrErrors(); 300 } catch(Exception e) { 301 } 303 304 if(SwingUtilities.isEventDispatchThread()) { 305 editor.engineGrammarDidAnalyze(); 306 } else { 307 SwingUtilities.invokeLater(new Runnable () { 308 public void run() { 309 editor.engineGrammarDidAnalyze(); 310 } 311 }); 312 } 313 314 if(!ErrorListener.shared().hasErrors()) { 317 grammarAnalyzeDirty = false; 318 } 319 } 320 321 public void cancel() { 322 Grammar g = getANTLRGrammar(); 323 if(g != null) 324 g.externallyAbortNFAToDFAConversion(); 325 } 326 327 protected void buildNonDeterministicErrors() { 328 errors.clear(); 329 for (Message warning : ErrorListener.shared().warnings) { 330 buildError(warning); 331 } 332 for (Message error : ErrorListener.shared().errors) { 333 buildError(error); 334 } 335 } 336 337 protected void buildError(Object o) { 338 if(o instanceof GrammarUnreachableAltsMessage) 339 errors.add(buildUnreachableAltsError((GrammarUnreachableAltsMessage)o)); 340 else if(o instanceof GrammarNonDeterminismMessage) 341 errors.add(buildNonDeterministicError((GrammarNonDeterminismMessage)o)); 342 else if(o instanceof NonRegularDecisionMessage) 343 errors.add(buildNonRegularDecisionError((NonRegularDecisionMessage)o)); 344 } 345 346 protected EngineGrammarError buildNonDeterministicError(GrammarNonDeterminismMessage message) { 347 EngineGrammarError error = new EngineGrammarError(); 348 error.setLine(message.probe.dfa.getDecisionASTNode().getLine()-1); 349 350 List labels = message.probe.getSampleNonDeterministicInputSequence(message.problemState); 351 error.setLabels(labels); 352 353 String input = message.probe.getInputSequenceDisplay(labels); 354 error.setMessageText("Decision can match input such as \""+input+"\" using multiple alternatives"); 355 error.setMessage(message); 356 357 return error; 358 } 359 360 protected EngineGrammarError buildUnreachableAltsError(GrammarUnreachableAltsMessage message) { 361 EngineGrammarError error = new EngineGrammarError(); 362 363 error.setLine(message.probe.dfa.getDecisionASTNode().getLine()-1); 364 error.setMessageText("The following alternatives are unreachable: "+message.alts); 365 error.setMessage(message); 366 367 return error; 368 } 369 370 protected EngineGrammarError buildNonRegularDecisionError(NonRegularDecisionMessage message) { 371 EngineGrammarError error = new EngineGrammarError(); 372 373 error.setLine(message.probe.dfa.getDecisionASTNode().getLine()-1); 374 error.setMessageText(message.toString()); 375 error.setMessage(message); 376 377 return error; 378 } 379 380 protected void markRulesWithWarningsOrErrors() throws Exception { 381 editor.visual.clearCacheGraphs(); 383 for (ElementRule rule : editor.getParserEngine().getRules()) { 384 updateRuleWithErrors(rule, fetchErrorsForRule(rule)); 385 } 386 387 editor.rules.refreshRules(); 388 } 389 390 protected void updateRuleWithErrors(ElementRule rule, List <EngineGrammarError> errors) throws Exception { 391 rule.setErrors(errors); 392 rule.setNeedsToBuildErrors(true); 393 } 394 395 protected List <EngineGrammarError> fetchErrorsForRule(ElementRule rule) { 396 List <EngineGrammarError> errors = new ArrayList <EngineGrammarError>(); 397 for (EngineGrammarError error : getErrors()) { 398 if (error.line >= rule.start.startLineNumber && error.line <= rule.end.startLineNumber) 399 errors.add(error); 400 } 401 return errors; 402 } 403 404 public void computeRuleErrors(ElementRule rule) { 405 List <EngineGrammarError> errors = rule.getErrors(); 406 for (EngineGrammarError error : errors) { 407 Object o = error.getMessage(); 408 if (o instanceof GrammarUnreachableAltsMessage) 409 computeRuleError(rule, error, (GrammarUnreachableAltsMessage) o); 410 else if (o instanceof GrammarNonDeterminismMessage) 411 computeRuleError(rule, error, (GrammarNonDeterminismMessage) o); 412 else if (o instanceof NonRegularDecisionMessage) 413 computeRuleError(rule, error, (NonRegularDecisionMessage) o); 414 } 415 416 try { 417 editor.visual.createGraphsForRule(rule); 418 } catch (Exception e) { 419 } 421 422 rule.setNeedsToBuildErrors(false); 423 } 424 425 public void computeRuleError(ElementRule rule, EngineGrammarError error, GrammarNonDeterminismMessage message) { 426 List nonDetAlts = message.probe.getNonDeterministicAltsForState(message.problemState); 427 Set disabledAlts = message.probe.getDisabledAlternatives(message.problemState); 428 429 int firstAlt = 0; 430 431 for (Object nonDetAlt : nonDetAlts) { 432 Integer displayAltI = (Integer ) nonDetAlt; 433 NFAState nfaStart = message.probe.dfa.getNFADecisionStartState(); 434 435 int tracePathAlt = nfaStart.translateDisplayAltToWalkAlt(message.probe.dfa, displayAltI); 436 if (firstAlt == 0) 437 firstAlt = tracePathAlt; 438 439 List path = 440 message.probe.getNFAPathStatesForAlt(firstAlt, 441 tracePathAlt, 442 error.getLabels()); 443 444 error.addPath(path, disabledAlts.contains(displayAltI)); 445 error.addStates(path); 446 447 for (Object aPath : path) { 449 NFAState state = (NFAState) aPath; 450 error.addRule(state.getEnclosingRule()); 451 } 452 } 453 } 454 455 public void computeRuleError(ElementRule rule, EngineGrammarError error, GrammarUnreachableAltsMessage message) { 456 NFAState state = message.probe.dfa.getNFADecisionStartState(); 457 for (Object alt1 : message.alts) { 458 error.addUnreachableAlt(state, (Integer ) alt1); 459 error.addStates(state); 460 error.addRule(state.getEnclosingRule()); 461 } 462 } 463 464 public void computeRuleError(ElementRule rule, EngineGrammarError error, NonRegularDecisionMessage message) { 465 NFAState state = message.probe.dfa.getNFADecisionStartState(); 466 for (Object alt : message.altsWithRecursion) { 467 error.addUnreachableAlt(state, (Integer ) alt); 469 error.addStates(state); 470 error.addRule(state.getEnclosingRule()); 471 } 472 } 473 474 } 475 | Popular Tags |