/** From editor's cursor, find associated parse tree node so we can highlight * in structure view. It wants the parse tree node not a * StructureViewTreeElement. It will try to find a path from root to * that node and highlight it. */ @Nullable public Object getCurrentEditorElement() { if (editor==null) return null; final int offset = editor.getCaretModel().getOffset(); if ( parseTree==null ) return null; Tree selectedNode = Trees.findNodeSuchThat(parseTree, new Predicate<Tree>() { @Override public boolean test(Tree node) { if ( !(node instanceof TerminalNode) ) return false; Token t = ((TerminalNode) node).getSymbol(); return offset>=t.getStartIndex() && offset<=t.getStopIndex(); } }); if ( selectedNode==null ) return null; // now walk up looking for template def node ParseTree p = (ParseTree)selectedNode; while ( p!=null && !(p instanceof STGParser.TemplateContext) ) { p = p.getParent(); } if ( p!=null ) { return ((STGParser.TemplateContext)p).ID(0); } return null; }
protected void doCompareParseTree(final File treeFile, final StartRuleContext startRule, final VisualBasic6Parser parser) throws IOException { final String treeFileData = FileUtils.readFileToString(treeFile); if (!Strings.isBlank(treeFileData)) { LOG.info("Comparing parse tree with file {}.", treeFile.getName()); final String inputFileTree = Trees.toStringTree(startRule, parser); final String cleanedInputFileTree = io.proleap.vb6.util.StringUtils.cleanFileTree(inputFileTree); final String cleanedTreeFileData = io.proleap.vb6.util.StringUtils.cleanFileTree(treeFileData); assertEquals(cleanedTreeFileData, cleanedInputFileTree); } else { LOG.info("Ignoring empty parse tree file {}.", treeFile.getName()); } }
@Override public Collection<ParseTree> evaluate(ParseTree t) { // return all children of t that match nodeName List<ParseTree> nodes = new ArrayList<ParseTree>(); for (Tree c : Trees.getChildren(t)) { if ( c instanceof ParserRuleContext ) { ParserRuleContext ctx = (ParserRuleContext)c; if ( (ctx.getRuleIndex() == ruleIndex && !invert) || (ctx.getRuleIndex() != ruleIndex && invert) ) { nodes.add(ctx); } } } return nodes; }
@Override public Collection<ParseTree> evaluate(ParseTree t) { // return all children of t that match nodeName List<ParseTree> nodes = new ArrayList<ParseTree>(); for (Tree c : Trees.getChildren(t)) { if ( c instanceof TerminalNode ) { TerminalNode tnode = (TerminalNode)c; if ( (tnode.getSymbol().getType() == tokenType && !invert) || (tnode.getSymbol().getType() != tokenType && invert) ) { nodes.add(tnode); } } } return nodes; }
@Override public String getText(Tree node) { if ( node instanceof PreviewInterpreterRuleContext) { PreviewInterpreterRuleContext inode = (PreviewInterpreterRuleContext)node; Rule r = g.getRule(inode.getRuleIndex()); String[] altLabels = getAltLabels(r); String name = r.name; int outerAltNum = inode.getOuterAltNum(); if ( altLabels!=null ) { if ( outerAltNum>=0 && outerAltNum<altLabels.length ) { return name+":"+altLabels[outerAltNum]; } else { return name; } } else if ( r.getOriginalNumberOfAlts()>1 ) { return name + ":" +outerAltNum; } else { return name; // don't display an alternative number if there's only one } } return Trees.getNodeText(node, Arrays.asList(parser.getRuleNames())); }
/** Same as loadGrammar(fileName) except import vocab from existing lexer */ // public static Grammar loadGrammar(Tool tool, String fileName, LexerGrammar lexerGrammar) { // GrammarRootAST grammarRootAST = parseGrammar(fileName); // if ( grammarRootAST==null ) return null; // final Grammar g = tool.createGrammar(grammarRootAST); // g.fileName = fileName; // if ( lexerGrammar!=null ) { // g.importVocab(lexerGrammar); // } // tool.process(g, false); // return g; // } public static Tree findOverriddenDecisionRoot(Tree ctx) { return Trees.findNodeSuchThat(ctx, new Predicate<Tree>() { @Override public boolean test(Tree t) { return t instanceof PreviewInterpreterRuleContext ? ((PreviewInterpreterRuleContext) t).isDecisionOverrideRoot() : false; } }); }
@Test public void parse() throws IOException { System.out.println(file.getName() + "-------------------------------"); final LLVMLexer lexer = new LLVMLexer(new ANTLRFileStream(file.getAbsolutePath())); final CommonTokenStream stream = new CommonTokenStream(lexer); final LLVMParser parser = new LLVMParser(stream); parser.setErrorHandler(new BailErrorStrategy()); final ModuleContext module = parser.module(); System.out.println(Trees.toStringTree(module)); }
public void enterEveryRule(ParserRuleContext ctx) { // Find sibling lists that are children of this parent node Set<Class> completed = new HashSet<>(); // only count sibling list for each subtree type once for (int i = 0; i<ctx.getChildCount(); i++) { ParseTree child = ctx.getChild(i); if ( completed.contains(child.getClass()) ) continue; // avoid counting repeatedly completed.add(child.getClass()); if ( child instanceof TerminalNode ) continue; // tokens are separators at most not siblings // found subtree child List<? extends ParserRuleContext> siblings = ctx.getRuleContexts(((ParserRuleContext) child).getClass()); if ( siblings.size()>1 ) { // we found a list // check for separator by looking between first two siblings (assume all are same) ParserRuleContext first = siblings.get(0); ParserRuleContext second = siblings.get(1); List<Tree> children = Trees.getChildren(ctx); int firstIndex = children.indexOf(first); int secondIndex = children.indexOf(second); if ( firstIndex+1 == secondIndex ) continue; // nothing between first and second so no separator ParseTree between = ctx.getChild(firstIndex+1); if ( between instanceof TerminalNode ) { // is it a token? Token separator = ((TerminalNode) between).getSymbol(); visitNonSingletonWithSeparator(ctx, siblings, separator); } } } }
public static List<Tree> getSeparators(ParserRuleContext ctx, List<? extends ParserRuleContext> siblings) { ParserRuleContext first = siblings.get(0); ParserRuleContext last = siblings.get(siblings.size()-1); int start = BuffUtils.indexOf(ctx, first); int end = BuffUtils.indexOf(ctx, last); List<Tree> elements = Trees.getChildren(ctx).subList(start, end+1); return BuffUtils.filter(elements, c -> c instanceof TerminalNode); }
@Override public void visitTerminal(TerminalNode node) { if (builder.length() > 0) { builder.append(' '); } builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); }
@Override public void visitErrorNode(ErrorNode node) { if (builder.length() > 0) { builder.append(' '); } builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); }
@NotNull @Override public TreeElement[] getChildren() { ParserRuleContext root = (ParserRuleContext) this.node; Collection<ParseTree> rules = Trees.findAllRuleNodes(root, STGParser.RULE_template); if ( rules.size()==0 ) return EMPTY_ARRAY; List<TreeElement> treeElements = new ArrayList<TreeElement>(rules.size()); for (ParseTree t : rules) { ParseTree nameNode = t.getChild(0); treeElements.add(new STGroupTemplateDefTreeElement(model, nameNode)); } // System.out.println("rules="+rules); return treeElements.toArray(new TreeElement[treeElements.size()]); }
private String process(final Tree t, final List<String> ruleNames) { if (t.getChildCount() == 0) return Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false); StringBuilder sb = new StringBuilder(); sb.append(lead(level)); level++; String s = Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false); sb.append(s + ' '); for (int i = 0; i < t.getChildCount(); i++) { sb.append(process(t.getChild(i), ruleNames)); } level--; sb.append(lead(level)); return sb.toString(); }
@Override public void visitTerminal(TerminalNode node) { String text = Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false); if(text.startsWith(" ") || text.endsWith(" ")){ text = "'" + text + "'"; } stack.get(node.getParent()).add(text); }
/** * @see org.antlr.v4.runtime.tree.Trees.toStringTree(Tree, List<String>) */ public static String toStringTree(final Tree t, @Nullable final List<String> ruleNames, final int depth) { String s = Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false); if (t.getChildCount() == 0) { return s; } final StringBuilder buf = new StringBuilder(); if (depth > 0) { buf.append(NEWLINE); } buf.append(indent(depth)); buf.append("("); s = Utils.escapeWhitespace(Trees.getNodeText(t, ruleNames), false); buf.append(s); buf.append(' '); for (int i = 0; i < t.getChildCount(); i++) { if (i > 0) { buf.append(' '); } buf.append(toStringTree(t.getChild(i), ruleNames, depth + 1)); } buf.append(")"); return buf.toString(); }
@Override public Collection<ParseTree> evaluate(final ParseTree t) { if ( invert ) return new ArrayList<ParseTree>(); // !* is weird but valid (empty) List<ParseTree> kids = new ArrayList<ParseTree>(); for (Tree c : Trees.getChildren(t)) { kids.add((ParseTree)c); } return kids; }
/** Save this tree in a postscript file using a particular font name and size */ public void save(@Nullable List<String> ruleNames, String fileName, String fontName, int fontSize) throws IOException { Trees.writePS(this, ruleNames, fileName, fontName, fontSize); }
@Override public void visitTerminal(TerminalNode node) { if (builder.length() > 0) { builder.append(' '); } append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); }
@Override public void visitErrorNode(ErrorNode node) { if (builder.length() > 0) { builder.append(' '); } append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); }
public static ParseTree getParseTreeNodeWithToken(ParseTree tree, Token token) { if ( tree==null || token==null ) { return null; } Collection<ParseTree> tokenNodes = Trees.findAllTokenNodes(tree, token.getType()); for (ParseTree t : tokenNodes) { TerminalNode tnode = (TerminalNode)t; if ( tnode.getPayload() == token ) { return tnode; } } return null; }
/** Given a token index into buffer, find surrounding rule then return * char position of start of next rule. */ public static int getCharIndexOfNextRuleStart(ParserRuleContext tree, int tokenIndex) { final ParserRuleContext selNode = Trees.getRootOfSubtreeEnclosingRegion(tree, tokenIndex, tokenIndex); final ParserRuleContext ruleRoot = (ParserRuleContext) getAncestorWithType(selNode, ANTLRv4Parser.RuleSpecContext.class); return ruleRoot.getStop().getStopIndex() + 2; // insert after '\n' following ';' // int ruleIndex = childIndexOf(ruleRoot.getParent(), ruleRoot); // ParserRuleContext nextRuleRoot = (ParserRuleContext)ruleRoot.getParent().getChild(ruleIndex+1); // if ( nextRuleRoot==null ) { // this rule must be last in grammar; put after ';' of this rule // } // return nextRuleRoot.getStart().getStartIndex(); }
/** 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 String getText(Tree node) { return String.valueOf(Trees.getNodeText(node, ruleNames)); }
private String convertToStringTree(ParseTree tree, List<String> ruleNamesList) { if (!getTreePretty()) { return Trees.toStringTree(tree, ruleNamesList); } return toPrettyTree(tree, ruleNamesList); }
@Override public void visitErrorNode(ErrorNode node) { stack.get(node.getParent()).add(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); }
@Override public Collection<ParseTree> evaluate(ParseTree t) { if ( invert ) return new ArrayList<ParseTree>(); // !* is weird but valid (empty) return Trees.descendants(t); }
@Override public Collection<ParseTree> evaluate(ParseTree t) { return Trees.findAllRuleNodes(t, ruleIndex); }
@Override public Collection<ParseTree> evaluate(ParseTree t) { return Trees.findAllTokenNodes(t, tokenType); }
/** Save this tree in a postscript file */ public void save(@Nullable List<String> ruleNames, String fileName) throws IOException, PrintException { Trees.writePS(this, ruleNames, fileName); }
/** Print out a whole tree, not just a node, in LISP format * (root child1 .. childN). Print just a node if this is a leaf. * We have to know the recognizer so we can get rule names. */ @Override public String toStringTree(@Nullable Parser recog) { return Trees.toStringTree(this, recog); }
/** Print out a whole tree, not just a node, in LISP format * (root child1 .. childN). Print just a node if this is a leaf. */ public String toStringTree(@Nullable List<String> ruleNames) { return Trees.toStringTree(this, ruleNames); }