use of org.antlr.v4.runtime.tree.Tree in project antlr4 by antlr.
the class LeftRecursiveRuleAnalyzer method text.
public String text(GrammarAST t) {
if (t == null)
return "";
int tokenStartIndex = t.getTokenStartIndex();
int tokenStopIndex = t.getTokenStopIndex();
// ignore tokens from existing option subtrees like:
// (ELEMENT_OPTIONS (= assoc right))
//
// element options are added back according to the values in the map
// returned by getOptions().
IntervalSet ignore = new IntervalSet();
List<GrammarAST> optionsSubTrees = t.getNodesWithType(ELEMENT_OPTIONS);
for (GrammarAST sub : optionsSubTrees) {
ignore.add(sub.getTokenStartIndex(), sub.getTokenStopIndex());
}
// Individual labels appear as RULE_REF or TOKEN_REF tokens in the tree,
// but do not support the ELEMENT_OPTIONS syntax. Make sure to not try
// and add the tokenIndex option when writing these tokens.
IntervalSet noOptions = new IntervalSet();
List<GrammarAST> labeledSubTrees = t.getNodesWithType(new IntervalSet(ASSIGN, PLUS_ASSIGN));
for (GrammarAST sub : labeledSubTrees) {
noOptions.add(sub.getChild(0).getTokenStartIndex());
}
StringBuilder buf = new StringBuilder();
int i = tokenStartIndex;
while (i <= tokenStopIndex) {
if (ignore.contains(i)) {
i++;
continue;
}
Token tok = tokenStream.get(i);
// Compute/hold any element options
StringBuilder elementOptions = new StringBuilder();
if (!noOptions.contains(i)) {
GrammarAST node = t.getNodeWithTokenIndex(tok.getTokenIndex());
if (node != null && (tok.getType() == TOKEN_REF || tok.getType() == STRING_LITERAL || tok.getType() == RULE_REF)) {
elementOptions.append("tokenIndex=").append(tok.getTokenIndex());
}
if (node instanceof GrammarASTWithOptions) {
GrammarASTWithOptions o = (GrammarASTWithOptions) node;
for (Map.Entry<String, GrammarAST> entry : o.getOptions().entrySet()) {
if (elementOptions.length() > 0) {
elementOptions.append(',');
}
elementOptions.append(entry.getKey());
elementOptions.append('=');
elementOptions.append(entry.getValue().getText());
}
}
}
// add actual text of the current token to the rewritten alternative
buf.append(tok.getText());
// move to the next token
i++;
// Are there args on a rule?
if (tok.getType() == RULE_REF && i <= tokenStopIndex && tokenStream.get(i).getType() == ARG_ACTION) {
buf.append('[' + tokenStream.get(i).getText() + ']');
i++;
}
// now that we have the actual element, we can add the options.
if (elementOptions.length() > 0) {
buf.append('<').append(elementOptions).append('>');
}
}
return buf.toString();
}
use of org.antlr.v4.runtime.tree.Tree in project antlr4 by antlr.
the class LeftRecursiveRuleTransformer method translateLeftRecursiveRule.
/** Return true if successful */
public boolean translateLeftRecursiveRule(GrammarRootAST ast, LeftRecursiveRule r, String language) {
//tool.log("grammar", ruleAST.toStringTree());
GrammarAST prevRuleAST = r.ast;
String ruleName = prevRuleAST.getChild(0).getText();
LeftRecursiveRuleAnalyzer leftRecursiveRuleWalker = new LeftRecursiveRuleAnalyzer(prevRuleAST, tool, ruleName, language);
boolean isLeftRec;
try {
// System.out.println("TESTING ---------------\n"+
// leftRecursiveRuleWalker.text(ruleAST));
isLeftRec = leftRecursiveRuleWalker.rec_rule();
} catch (RecognitionException re) {
// didn't match; oh well
isLeftRec = false;
}
if (!isLeftRec)
return false;
// replace old rule's AST; first create text of altered rule
GrammarAST RULES = (GrammarAST) ast.getFirstChildWithType(ANTLRParser.RULES);
String newRuleText = leftRecursiveRuleWalker.getArtificialOpPrecRule();
// System.out.println("created: "+newRuleText);
// now parse within the context of the grammar that originally created
// the AST we are transforming. This could be an imported grammar so
// we cannot just reference this.g because the role might come from
// the imported grammar and not the root grammar (this.g)
RuleAST t = parseArtificialRule(prevRuleAST.g, newRuleText);
// reuse the name token from the original AST since it refers to the proper source location in the original grammar
((GrammarAST) t.getChild(0)).token = ((GrammarAST) prevRuleAST.getChild(0)).getToken();
// update grammar AST and set rule's AST.
RULES.setChild(prevRuleAST.getChildIndex(), t);
r.ast = t;
// Reduce sets in newly created rule tree
GrammarTransformPipeline transform = new GrammarTransformPipeline(g, g.tool);
transform.reduceBlocksToSets(r.ast);
transform.expandParameterizedLoops(r.ast);
// Rerun semantic checks on the new rule
RuleCollector ruleCollector = new RuleCollector(g);
ruleCollector.visit(t, "rule");
BasicSemanticChecks basics = new BasicSemanticChecks(g, ruleCollector);
// disable the assoc element option checks because they are already
// handled for the pre-transformed rule.
basics.checkAssocElementOption = false;
basics.visit(t, "rule");
// track recursive alt info for codegen
r.recPrimaryAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
r.recPrimaryAlts.addAll(leftRecursiveRuleWalker.prefixAndOtherAlts);
if (r.recPrimaryAlts.isEmpty()) {
tool.errMgr.grammarError(ErrorType.NO_NON_LR_ALTS, g.fileName, ((GrammarAST) r.ast.getChild(0)).getToken(), r.name);
}
r.recOpAlts = new OrderedHashMap<Integer, LeftRecursiveRuleAltInfo>();
r.recOpAlts.putAll(leftRecursiveRuleWalker.binaryAlts);
r.recOpAlts.putAll(leftRecursiveRuleWalker.ternaryAlts);
r.recOpAlts.putAll(leftRecursiveRuleWalker.suffixAlts);
// walk alt info records and set their altAST to point to appropriate ALT subtree
// from freshly created AST
setAltASTPointers(r, t);
// update Rule to just one alt and add prec alt
ActionAST arg = (ActionAST) r.ast.getFirstChildWithType(ANTLRParser.ARG_ACTION);
if (arg != null) {
r.args = ScopeParser.parseTypedArgList(arg, arg.getText(), g);
r.args.type = AttributeDict.DictType.ARG;
r.args.ast = arg;
// todo: isn't this Rule or something?
arg.resolver = r.alt[1];
}
// these are so $label in action translation works
for (Pair<GrammarAST, String> pair : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
GrammarAST labelNode = pair.a;
GrammarAST labelOpNode = (GrammarAST) labelNode.getParent();
GrammarAST elementNode = (GrammarAST) labelOpNode.getChild(1);
LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
r.alt[1].labelDefs.map(labelNode.getText(), lp);
}
// copy to rule from walker
r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;
tool.log("grammar", "added: " + t.toStringTree());
return true;
}
use of org.antlr.v4.runtime.tree.Tree in project antlr4 by antlr.
the class TestVisitors method testShouldNotVisitTerminal.
/**
* This test verifies that {@link AbstractParseTreeVisitor#shouldVisitNextChild} is called before visiting the first
* child. It also verifies that {@link AbstractParseTreeVisitor#defaultResult} provides the default return value for
* visiting a tree.
*/
@Test
public void testShouldNotVisitTerminal() {
String input = "A";
VisitorBasicLexer lexer = new VisitorBasicLexer(new ANTLRInputStream(input));
VisitorBasicParser parser = new VisitorBasicParser(new CommonTokenStream(lexer));
VisitorBasicParser.SContext context = parser.s();
Assert.assertEquals("(s A <EOF>)", context.toStringTree(parser));
VisitorBasicVisitor<String> listener = new VisitorBasicBaseVisitor<String>() {
@Override
public String visitTerminal(TerminalNode node) {
throw new RuntimeException("Should not be reachable");
}
@Override
protected String defaultResult() {
return "default result";
}
@Override
protected boolean shouldVisitNextChild(RuleNode node, String currentResult) {
return false;
}
};
String result = listener.visit(context);
String expected = "default result";
Assert.assertEquals(expected, result);
}
use of org.antlr.v4.runtime.tree.Tree in project antlr4 by antlr.
the class BaseBrowserTest method writeParserTestFile.
protected void writeParserTestFile(String parserName, String lexerName, String listenerName, String visitorName, String parserStartRuleName, boolean debug) {
String html = "<!DOCTYPE html>\r\n" + "<html>\r\n" + " <head>\r\n" + " <script src='lib/require.js'></script>\r\n" + " <script>\r\n" + " antlr4 = null;\r\n" + " listener = null;\r\n" + " TreeShapeListener = null;\r\n" + " " + lexerName + " = null;\r\n" + " " + parserName + " = null;\r\n" + " " + listenerName + " = null;\r\n" + " " + visitorName + " = null;\r\n" + " printer = function() {\r\n" + " this.println = function(s) { document.getElementById('output').value += s + '\\n'; }\r\n" + " this.print = function(s) { document.getElementById('output').value += s; }\r\n" + " return this;\r\n" + " };\r\n" + "\r\n" + " loadParser = function() {\r\n" + " try {\r\n" + " antlr4 = require('antlr4/index');\r\n" + " " + lexerName + " = require('./parser/" + lexerName + "');\n" + " " + parserName + " = require('./parser/" + parserName + "');\n" + " " + listenerName + " = require('./parser/" + listenerName + "');\n" + " " + visitorName + " = require('./parser/" + visitorName + "');\n" + " } catch (ex) {\r\n" + " document.getElementById('errors').value = ex.toString();\r\n" + " }\r\n" + "\r\n" + " listener = function() {\r\n" + " antlr4.error.ErrorListener.call(this);\r\n" + " return this;\r\n" + " }\r\n" + " listener.prototype = Object.create(antlr4.error.ErrorListener.prototype);\r\n" + " listener.prototype.constructor = listener;\r\n" + " listener.prototype.syntaxError = function(recognizer, offendingSymbol, line, column, msg, e) {\r\n" + " document.getElementById('errors').value += 'line ' + line + ':' + column + ' ' + msg + '\\r\\n';\r\n" + " };\r\n" + "\r\n" + " TreeShapeListener = function() {\r\n" + " antlr4.tree.ParseTreeListener.call(this);\r\n" + " return this;\r\n" + " };\r\n" + "\r\n" + " TreeShapeListener.prototype = Object.create(antlr4.tree.ParseTreeListener.prototype);\r\n" + " TreeShapeListener.prototype.constructor = TreeShapeListener;\r\n" + "\r\n" + " TreeShapeListener.prototype.enterEveryRule = function(ctx) {\r\n" + " for(var i=0;i<ctx.getChildCount; i++) {\r\n" + " var child = ctx.getChild(i);\r\n" + " var parent = child.parentCtx;\r\n" + " if(parent.getRuleContext() !== ctx || !(parent instanceof antlr4.tree.RuleNode)) {\r\n" + " throw 'Invalid parse tree shape detected.';\r\n" + " }\r\n" + " }\r\n" + " };\r\n" + " }\r\n" + "\r\n" + " test = function() {\r\n" + " document.getElementById('output').value = ''\r\n" + " var input = document.getElementById('input').value;\r\n" + " var stream = new antlr4.InputStream(input, true);\n" + " var lexer = new " + lexerName + "." + lexerName + "(stream);\n" + " lexer._listeners = [new listener()];\r\n" + " var tokens = new antlr4.CommonTokenStream(lexer);\n" + " var parser = new " + parserName + "." + parserName + "(tokens);\n" + " parser._listeners.push(new listener());\n" + (debug ? " parser._listeners.push(new antlr4.error.DiagnosticErrorListener());\n" : "") + " parser.buildParseTrees = true;\n" + " parser.printer = new printer();\n" + " var tree = parser." + parserStartRuleName + "();\n" + " antlr4.tree.ParseTreeWalker.DEFAULT.walk(new TreeShapeListener(), tree);\n" + " };\r\n" + "\r\n" + " </script>\r\n" + " </head>\r\n" + " <body>\r\n" + " <textarea id='input'></textarea><br>\r\n" + " <button id='load' type='button' onclick='loadParser()'>Load</button><br>\r\n" + " <button id='submit' type='button' onclick='test()'>Test</button><br>\r\n" + " <textarea id='output'></textarea><br>\r\n" + " <textarea id='errors'></textarea><br>\r\n" + " </body>\r\n" + "</html>\r\n";
writeFile(httpdir, "Test.html", html);
}
use of org.antlr.v4.runtime.tree.Tree in project antlr4 by antlr.
the class BaseJavaTest method execStartRule.
public ParseTree execStartRule(String startRuleName, Parser parser) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Method startRule = null;
Object[] args = null;
try {
startRule = parser.getClass().getMethod(startRuleName);
} catch (NoSuchMethodException nsme) {
// try with int _p arg for recursive func
startRule = parser.getClass().getMethod(startRuleName, int.class);
args = new Integer[] { 0 };
}
ParseTree result = (ParseTree) startRule.invoke(parser, args);
// System.out.println("parse tree = "+result.toStringTree(parser));
return result;
}
Aggregations