use of org.antlr.v4.tool.ast.GrammarASTWithOptions in project antlr4 by antlr.
the class GrammarTransformPipeline method augmentTokensWithOriginalPosition.
public static void augmentTokensWithOriginalPosition(final Grammar g, GrammarAST tree) {
if (tree == null)
return;
List<GrammarAST> optionsSubTrees = tree.getNodesWithType(ANTLRParser.ELEMENT_OPTIONS);
for (int i = 0; i < optionsSubTrees.size(); i++) {
GrammarAST t = optionsSubTrees.get(i);
CommonTree elWithOpt = t.parent;
if (elWithOpt instanceof GrammarASTWithOptions) {
Map<String, GrammarAST> options = ((GrammarASTWithOptions) elWithOpt).getOptions();
if (options.containsKey(LeftRecursiveRuleTransformer.TOKENINDEX_OPTION_NAME)) {
GrammarToken newTok = new GrammarToken(g, elWithOpt.getToken());
newTok.originalTokenIndex = Integer.valueOf(options.get(LeftRecursiveRuleTransformer.TOKENINDEX_OPTION_NAME).getText());
elWithOpt.token = newTok;
GrammarAST originalNode = g.ast.getNodeWithTokenIndex(newTok.getTokenIndex());
if (originalNode != null) {
// update the AST node start/stop index to match the values
// of the corresponding node in the original parse tree.
elWithOpt.setTokenStartIndex(originalNode.getTokenStartIndex());
elWithOpt.setTokenStopIndex(originalNode.getTokenStopIndex());
} else {
// the original AST node could not be located by index;
// make sure to assign valid values for the start/stop
// index so toTokenString will not throw exceptions.
elWithOpt.setTokenStartIndex(newTok.getTokenIndex());
elWithOpt.setTokenStopIndex(newTok.getTokenIndex());
}
}
}
}
}
use of org.antlr.v4.tool.ast.GrammarASTWithOptions 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.tool.ast.GrammarASTWithOptions in project antlr4 by antlr.
the class LeftRecursiveRuleTransformer method translateLeftRecursiveRules.
public void translateLeftRecursiveRules() {
String language = g.getOptionString("language");
// translate all recursive rules
List<String> leftRecursiveRuleNames = new ArrayList<String>();
for (Rule r : rules) {
if (!Grammar.isTokenName(r.name)) {
if (LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(r.ast, r.name)) {
boolean fitsPattern = translateLeftRecursiveRule(ast, (LeftRecursiveRule) r, language);
if (fitsPattern) {
leftRecursiveRuleNames.add(r.name);
} else {
// better given an error that non-conforming left-recursion exists
tool.errMgr.grammarError(ErrorType.NONCONFORMING_LR_RULE, g.fileName, ((GrammarAST) r.ast.getChild(0)).token, r.name);
}
}
}
}
// update all refs to recursive rules to have [0] argument
for (GrammarAST r : ast.getNodesWithType(ANTLRParser.RULE_REF)) {
// must be rule def
if (r.getParent().getType() == ANTLRParser.RULE)
continue;
// already has arg; must be in rewritten rule
if (((GrammarASTWithOptions) r).getOptionString(PRECEDENCE_OPTION_NAME) != null)
continue;
if (leftRecursiveRuleNames.contains(r.getText())) {
// found ref to recursive rule not already rewritten with arg
((GrammarASTWithOptions) r).setOption(PRECEDENCE_OPTION_NAME, (GrammarAST) new GrammarASTAdaptor().create(ANTLRParser.INT, "0"));
}
}
}
Aggregations