private String translateToAssertionsPushCalls(SingleExpressionContext assertionStatementLeftHandSide, RuleContext ctx) { String translatedText = ctx.getText(); String xpath = "//singleExpression"; ParseTree parseTree = (ParseTree) ctx; translatedText = translateAssertionFunctionShortcuts(ctx, false); ParseTreePattern assertionExpressionPattern = this.parser.compileParseTreePattern( "<assertionOperator> <singleExpression>", HL7MappingValidatorParser.RULE_singleExpression); List<ParseTreeMatch> assertionExpressionMatches = assertionExpressionPattern.findAll(parseTree, xpath); for (ParseTreeMatch match : assertionExpressionMatches) { AssertionOperatorContext operator = (AssertionOperatorContext) match.get("assertionOperator"); SingleExpressionContext assertionStatementRightHandSide = (SingleExpressionContext) match.get("singleExpression"); String translatedFunctionCall = translateToAssertionsPushCall(assertionStatementLeftHandSide, operator, assertionStatementRightHandSide); String matchTextTranslated = translateAssertionFunctionShortcuts((RuleContext) match.getTree(), false); translatedText = translatedText.replace(matchTextTranslated, translatedFunctionCall); } return translatedText; }
private void detectAssertionShortcuts(RuleContext ctx) { String xpath = "//singleExpression"; ParseTree parseTree = (ParseTree) ctx; ParseTreePattern p = this.parser.compileParseTreePattern( "@ <arguments>", HL7MappingValidatorParser.RULE_singleExpression); List<ParseTreeMatch> matches = p.findAll(parseTree, xpath); for (ParseTreeMatch match : matches) { System.out.println(match.getTree().getText()); } }
/** * The same as {@link #compileParseTreePattern(String, int)} but specify a * {@link Lexer} rather than trying to deduce it from this parser. */ public ParseTreePattern compileParseTreePattern(String pattern, int patternRuleIndex, Lexer lexer) { ParseTreePatternMatcher m = new ParseTreePatternMatcher(lexer, this); return m.compile(pattern, patternRuleIndex); }
@Override public void actionPerformed(AnActionEvent e) { LOG.info("actionPerformed GenerateLexerRulesForLiteralsAction"); final Project project = e.getProject(); final PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE); if (psiFile == null) { return; } String inputText = psiFile.getText(); ParsingResult results = ParsingUtils.parseANTLRGrammar(inputText); final Parser parser = results.parser; final ParseTree tree = results.tree; Collection<ParseTree> literalNodes = XPath.findAll(tree, "//ruleBlock//STRING_LITERAL", parser); LinkedHashMap<String, String> lexerRules = new LinkedHashMap<String, String>(); for (ParseTree node : literalNodes) { String literal = node.getText(); String ruleText = String.format("%s : %s ;", RefactorUtils.getLexerRuleNameFromLiteral(literal), literal); lexerRules.put(literal, ruleText); } // remove those already defined String lexerRulesXPath = "//lexerRule"; String treePattern = "<TOKEN_REF> : <STRING_LITERAL>;"; ParseTreePattern p = parser.compileParseTreePattern(treePattern, ANTLRv4Parser.RULE_lexerRule); List<ParseTreeMatch> matches = p.findAll(tree, lexerRulesXPath); for (ParseTreeMatch match : matches) { ParseTree lit = match.get("STRING_LITERAL"); if (lexerRules.containsKey(lit.getText())) { // we have rule for this literal already lexerRules.remove(lit.getText()); } } final LiteralChooser chooser = new LiteralChooser(project, new ArrayList<String>(lexerRules.values())); chooser.show(); List<String> selectedElements = chooser.getSelectedElements(); // chooser disposed automatically. final Editor editor = e.getData(PlatformDataKeys.EDITOR); final Document doc = editor.getDocument(); final CommonTokenStream tokens = (CommonTokenStream) parser.getTokenStream(); // System.out.println(selectedElements); if (selectedElements != null) { String text = doc.getText(); int cursorOffset = editor.getCaretModel().getOffset(); // make sure it's not in middle of rule; put between. // System.out.println("offset "+cursorOffset); Collection<ParseTree> allRuleNodes = XPath.findAll(tree, "//ruleSpec", parser); for (ParseTree r : allRuleNodes) { Interval extent = r.getSourceInterval(); // token indexes int start = tokens.get(extent.a).getStartIndex(); int stop = tokens.get(extent.b).getStopIndex(); // System.out.println("rule "+r.getChild(0).getText()+": "+start+".."+stop); if (cursorOffset < start) { // before this rule, so must be between previous and this one cursorOffset = start; // put right before this rule break; } else if (cursorOffset >= start && cursorOffset <= stop) { // cursor in this rule cursorOffset = stop + 2; // put right before this rule (after newline) if (cursorOffset >= text.length()) { cursorOffset = text.length(); } break; } } String allRules = Utils.join(selectedElements.iterator(), "\n"); text = text.substring(0, cursorOffset) + "\n" + allRules + "\n" + text.substring(cursorOffset, text.length()); MyPsiUtils.replacePsiFileFromText(project, psiFile, text); } }
/** * The preferred method of getting a tree pattern. For example, here's a * sample use: * * <pre> * ParseTree t = parser.expr(); * ParseTreePattern p = parser.compileParseTreePattern("<ID>+0", MyParser.RULE_expr); * ParseTreeMatch m = p.match(t); * String id = m.get("ID"); * </pre> */ public ParseTreePattern compileParseTreePattern(String pattern, int patternRuleIndex) { if ( getTokenStream()!=null ) { TokenSource tokenSource = getTokenStream().getTokenSource(); if ( tokenSource instanceof Lexer ) { Lexer lexer = (Lexer)tokenSource; return compileParseTreePattern(pattern, patternRuleIndex, lexer); } } throw new UnsupportedOperationException("Parser can't discover a lexer to use"); }
/** * Searches for subtrees that adhere to the given XPath expression * and applies pattern matching on each subtree. * * @param pattern the parse tree pattern, refer to https://github.com/antlr/antlr4/blob/master/doc/faq/parse-trees.md * @param rule the production rule in the parser that the pattern adheres to * @param xPath the XPath expression that will be used to find subtrees * @return a list of matches */ List<ParseTreeMatch> match(String pattern, int rule, String xPath) { ParseTreePattern p = ast.getParser().compileParseTreePattern(pattern, rule); return p.findAll(ast.getTree(), xPath); }