org.antlr.v4.tool.Alternative Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of antlr4 Show documentation
Show all versions of antlr4 Show documentation
The ANTLR 4 grammar compiler.
/*
* Copyright (c) 2012 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD-3-Clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.tool;
import org.antlr.v4.runtime.misc.MultiMap;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.AltAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.TerminalAST;
import java.util.ArrayList;
import java.util.List;
/** An outermost alternative for a rule. We don't track inner alternatives. */
public class Alternative implements AttributeResolver {
public Rule rule;
public AltAST ast;
/** What alternative number is this outermost alt? 1..n */
public int altNum;
// token IDs, string literals in this alt
public MultiMap tokenRefs = new MultiMap();
// does not include labels
public MultiMap tokenRefsInActions = new MultiMap();
// all rule refs in this alt
public MultiMap ruleRefs = new MultiMap();
// does not include labels
public MultiMap ruleRefsInActions = new MultiMap();
/** A list of all LabelElementPair attached to tokens like id=ID, ids+=ID */
public MultiMap labelDefs = new MultiMap();
// track all token, rule, label refs in rewrite (right of ->)
//public List rewriteElements = new ArrayList();
/** Track all executable actions other than named actions like @init
* and catch/finally (not in an alt). Also tracks predicates, rewrite actions.
* We need to examine these actions before code generation so
* that we can detect refs to $rule.attr etc...
*
* This tracks per alt
*/
public List actions = new ArrayList();
public Alternative(Rule r, int altNum) { this.rule = r; this.altNum = altNum; }
@Override
public boolean resolvesToToken(String x, ActionAST node) {
if ( tokenRefs.get(x)!=null ) return true;
LabelElementPair anyLabelDef = getAnyLabelDef(x);
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.TOKEN_LABEL ) return true;
return false;
}
@Override
public boolean resolvesToAttributeDict(String x, ActionAST node) {
if ( resolvesToToken(x, node) ) return true;
if ( ruleRefs.get(x)!=null ) return true; // rule ref in this alt?
LabelElementPair anyLabelDef = getAnyLabelDef(x);
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.RULE_LABEL ) return true;
return false;
}
/** $x Attribute: rule arguments, return values, predefined rule prop.
*/
@Override
public Attribute resolveToAttribute(String x, ActionAST node) {
return rule.resolveToAttribute(x, node); // reuse that code
}
/** $x.y, x can be surrounding rule, token/rule/label ref. y is visible
* attr in that dictionary. Can't see args on rule refs.
*/
@Override
public Attribute resolveToAttribute(String x, String y, ActionAST node) {
if ( tokenRefs.get(x)!=null ) { // token ref in this alt?
return rule.getPredefinedScope(LabelType.TOKEN_LABEL).get(y);
}
if ( ruleRefs.get(x)!=null ) { // rule ref in this alt?
// look up rule, ask it to resolve y (must be retval or predefined)
return rule.g.getRule(x).resolveRetvalOrProperty(y);
}
LabelElementPair anyLabelDef = getAnyLabelDef(x);
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.RULE_LABEL ) {
return rule.g.getRule(anyLabelDef.element.getText()).resolveRetvalOrProperty(y);
}
else if ( anyLabelDef!=null ) {
AttributeDict scope = rule.getPredefinedScope(anyLabelDef.type);
if (scope == null) {
return null;
}
return scope.get(y);
}
return null;
}
@Override
public boolean resolvesToLabel(String x, ActionAST node) {
LabelElementPair anyLabelDef = getAnyLabelDef(x);
return anyLabelDef!=null &&
(anyLabelDef.type==LabelType.TOKEN_LABEL ||
anyLabelDef.type==LabelType.RULE_LABEL);
}
@Override
public boolean resolvesToListLabel(String x, ActionAST node) {
LabelElementPair anyLabelDef = getAnyLabelDef(x);
return anyLabelDef!=null &&
(anyLabelDef.type==LabelType.RULE_LIST_LABEL ||
anyLabelDef.type==LabelType.TOKEN_LIST_LABEL);
}
public LabelElementPair getAnyLabelDef(String x) {
List labels = labelDefs.get(x);
if ( labels!=null ) return labels.get(0);
return null;
}
/** x can be ruleref or rule label. */
public Rule resolveToRule(String x) {
if ( ruleRefs.get(x)!=null ) return rule.g.getRule(x);
LabelElementPair anyLabelDef = getAnyLabelDef(x);
if ( anyLabelDef!=null && anyLabelDef.type==LabelType.RULE_LABEL ) {
return rule.g.getRule(anyLabelDef.element.getText());
}
return null;
}
}