public ParserInterpreter createParserInterpreter(TokenStream tokenStream) { if (this.isLexer()) { throw new IllegalStateException("A parser interpreter can only be created for a parser or combined grammar."); } char[] serializedAtn = ATNSerializer.getSerializedAsChars(atn); ATN deserialized = new ATNDeserializer().deserialize(serializedAtn); return new ParserInterpreter(fileName, getVocabulary(), Arrays.asList(getRuleNames()), deserialized, tokenStream); }
public static void popupLookaheadTreesDialog(PreviewState previewState, LookaheadEventInfo lookaheadInfo) { // pop up subtrees for lookahead ShowAmbigTreesDialog dialog = new ShowAmbigTreesDialog(); ParserInterpreter parser = (ParserInterpreter) previewState.parsingResult.parser; int startRuleIndex = parser.getRuleIndex(previewState.startRuleName); List<ParserRuleContext> lookaheadParseTrees = GrammarParserInterpreter.getLookaheadParseTrees(previewState.g, parser, parser.getTokenStream(), startRuleIndex, lookaheadInfo.decision, lookaheadInfo.startIndex, lookaheadInfo.stopIndex); if ( parser.getNumberOfSyntaxErrors()>0 ) { // should be no errors for ambiguities, unless original // input itself has errors. Just display error in this case. JBPanel errPanel = new JBPanel(new BorderLayout()); errPanel.add(new JBLabel("Cannot display lookahead trees while there are syntax errors in your input.")); dialog.treeScrollPane.setViewportView(errPanel); lookaheadParseTrees = null; } if ( lookaheadParseTrees!=null ) { Interval range = Interval.of(lookaheadInfo.startIndex, lookaheadInfo.stopIndex); String phrase = parser.getTokenStream().getText(range); if ( phrase.length()>MAX_PHRASE_WIDTH ) { phrase = phrase.substring(0, MAX_PHRASE_WIDTH)+"..."; } String title = lookaheadParseTrees.size()+ " Interpretations of Lookahead Phrase: "+ phrase; dialog.ambigPhraseLabel.setText(title); dialog.setTrees(previewState, lookaheadParseTrees, title, lookaheadInfo.predictedAlt-1, lookaheadInfo.startIndex, lookaheadInfo.stopIndex, false); } dialog.pack(); dialog.setVisible(true); }
/** Return a list of parse trees, one for each alternative in a decision * given the same input. * * Very similar to {@link #getAllPossibleParseTrees} except * that it re-parses the input for every alternative in a decision, * not just the ambiguous ones (there is no alts parameter here). * This method also tries to reduce the size of the parse trees * by stripping away children of the tree that are completely out of range * of startIndex..stopIndex. Also, because errors are expected, we * use a specialized error handler that more or less bails out * but that also consumes the first erroneous token at least. This * ensures that an error node will be in the parse tree for display. * * NOTES: // we must parse the entire input now with decision overrides // we cannot parse a subset because it could be that a decision // above our decision of interest needs to read way past // lookaheadInfo.stopIndex. It seems like there is no escaping // the use of a full and complete token stream if we are // resetting to token index 0 and re-parsing from the start symbol. // It's not easy to restart parsing somewhere in the middle like a // continuation because our call stack does not match the // tree stack because of left recursive rule rewriting. grrrr! * * @since 4.5.1 */ public static List<ParserRuleContext> getLookaheadParseTrees(Grammar g, ParserInterpreter originalParser, TokenStream tokens, int startRuleIndex, int decision, int startIndex, int stopIndex) { List<ParserRuleContext> trees = new ArrayList<ParserRuleContext>(); // Create a new parser interpreter to parse the ambiguous subphrase ParserInterpreter parser = deriveTempParserInterpreter(g, originalParser, tokens); BailButConsumeErrorStrategy errorHandler = new BailButConsumeErrorStrategy(); parser.setErrorHandler(errorHandler); DecisionState decisionState = originalParser.getATN().decisionToState.get(decision); for (int alt=1; alt<=decisionState.getTransitions().length; alt++) { // re-parse entire input for all ambiguous alternatives // (don't have to do first as it's been parsed, but do again for simplicity // using this temp parser.) parser.reset(); parser.addDecisionOverride(decision, startIndex, alt); ParserRuleContext tt = parser.parse(startRuleIndex); int stopTreeAt = stopIndex; if ( errorHandler.firstErrorTokenIndex>=0 ) { stopTreeAt = errorHandler.firstErrorTokenIndex; // cut off rest at first error } ParserRuleContext subtree = Trees.getRootOfSubtreeEnclosingRegion(tt, startIndex, stopTreeAt); // Use higher of overridden decision tree or tree enclosing all tokens if ( Trees.isAncestorOf(parser.getOverrideDecisionRoot(), subtree) ) { subtree = parser.getOverrideDecisionRoot(); } Trees.stripChildrenOutOfRange(subtree, parser.getOverrideDecisionRoot(), startIndex, stopTreeAt); trees.add(subtree); } return trees; }
@Override public ParserInterpreter getParserInterpreter() { return parser; }
public ParserInterpreter getParserInterpreter();