package antlr;
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.cs.usfca.edu
* Software rights: http://www.antlr.org/license.html
*
* $Id: //depot/code/org.antlr/release/antlr-2.7.6/antlr/AlternativeBlock.java#1 $
*/
import antlr.collections.impl.Vector;
/**A list of alternatives */
class AlternativeBlock extends AlternativeElement {
protected String initAction = null; // string for init action {...}
protected Vector alternatives; // Contains Alternatives
protected String label; // can label a looping block to break out of it.
protected int alti, altj; // which alts are being compared at the moment with
// deterministic()?
protected int analysisAlt; // which alt are we computing look on? Must be alti or altj
protected boolean hasAnAction = false; // does any alt have an action?
protected boolean hasASynPred = false; // does any alt have a syntactic predicate?
protected int ID = 0; // used to generate unique variables
protected static int nblks; // how many blocks have we allocated?
boolean not = false; // true if block is inverted.
boolean greedy = true; // Blocks are greedy by default
boolean greedySet = false; // but, if not explicitly greedy, warning might be generated
protected boolean doAutoGen = true; // false if no AST (or text) to be generated for block
protected boolean warnWhenFollowAmbig = true; // warn when an empty path or exit path
protected boolean generateAmbigWarnings = true; // the general warning "shut-up" mechanism
// conflicts with alt of subrule.
// Turning this off will suppress stuff
// like the if-then-else ambig.
public AlternativeBlock(Grammar g) {
super(g);
alternatives = new Vector(5);
this.not = false;
nblks++;
ID = nblks;
}
public AlternativeBlock(Grammar g, Token start, boolean not) {
super(g, start);
alternatives = new Vector(5);
// this.line = start.getLine();
// this.column = start.getColumn();
this.not = not;
nblks++;
ID = nblks;
}
public void addAlternative(Alternative alt) {
alternatives.appendElement(alt);
}
public void generate() {
grammar.generator.gen(this);
}
public Alternative getAlternativeAt(int i) {
return (Alternative)alternatives.elementAt(i);
}
public Vector getAlternatives() {
return alternatives;
}
public boolean getAutoGen() {
return doAutoGen;
}
public String getInitAction() {
return initAction;
}
public String getLabel() {
return label;
}
public Lookahead look(int k) {
return grammar.theLLkAnalyzer.look(k, this);
}
public void prepareForAnalysis() {
for (int i = 0; i < alternatives.size(); i++) {
// deterministic() uses an alternative cache and sets lookahead depth
Alternative a = (Alternative)alternatives.elementAt(i);
a.cache = new Lookahead[grammar.maxk + 1];
a.lookaheadDepth = GrammarAnalyzer.LOOKAHEAD_DEPTH_INIT;
}
}
/**Walk the syntactic predicate and, for a rule ref R, remove
* the ref from the list of FOLLOW references for R (stored
* in the symbol table.
*/
public void removeTrackingOfRuleRefs(Grammar g) {
for (int i = 0; i < alternatives.size(); i++) {
Alternative alt = getAlternativeAt(i);
AlternativeElement elem = alt.head;
while (elem != null) {
if (elem instanceof RuleRefElement) {
RuleRefElement rr = (RuleRefElement)elem;
RuleSymbol rs = (RuleSymbol)g.getSymbol(rr.targetRule);
if (rs == null) {
grammar.antlrTool.error("rule " + rr.targetRule + " referenced in (...)=>, but not defined");
}
else {
rs.references.removeElement(rr);
}
}
else if (elem instanceof AlternativeBlock) {// recurse into subrules
((AlternativeBlock)elem).removeTrackingOfRuleRefs(g);
}
elem = elem.next;
}
}
}
public void setAlternatives(Vector v) {
alternatives = v;
}
public void setAutoGen(boolean doAutoGen_) {
doAutoGen = doAutoGen_;
}
public void setInitAction(String initAction_) {
initAction = initAction_;
}
public void setLabel(String label_) {
label = label_;
}
public void setOption(Token key, Token value) {
if (key.getText().equals("warnWhenFollowAmbig")) {
if (value.getText().equals("true")) {
warnWhenFollowAmbig = true;
}
else if (value.getText().equals("false")) {
warnWhenFollowAmbig = false;
}
else {
grammar.antlrTool.error("Value for warnWhenFollowAmbig must be true or false", grammar.getFilename(), key.getLine(), key.getColumn());
}
}
else if (key.getText().equals("generateAmbigWarnings")) {
if (value.getText().equals("true")) {
generateAmbigWarnings = true;
}
else if (value.getText().equals("false")) {
generateAmbigWarnings = false;
}
else {
grammar.antlrTool.error("Value for generateAmbigWarnings must be true or false", grammar.getFilename(), key.getLine(), key.getColumn());
}
}
else if (key.getText().equals("greedy")) {
if (value.getText().equals("true")) {
greedy = true;
greedySet = true;
}
else if (value.getText().equals("false")) {
greedy = false;
greedySet = true;
}
else {
grammar.antlrTool.error("Value for greedy must be true or false", grammar.getFilename(), key.getLine(), key.getColumn());
}
}
else {
grammar.antlrTool.error("Invalid subrule option: " + key.getText(), grammar.getFilename(), key.getLine(), key.getColumn());
}
}
public String toString() {
String s = " (";
if (initAction != null) {
s += initAction;
}
for (int i = 0; i < alternatives.size(); i++) {
Alternative alt = getAlternativeAt(i);
Lookahead cache[] = alt.cache;
int k = alt.lookaheadDepth;
// dump lookahead set
if (k == GrammarAnalyzer.LOOKAHEAD_DEPTH_INIT) {
}
else if (k == GrammarAnalyzer.NONDETERMINISTIC) {
s += "{?}:";
}
else {
s += " {";
for (int j = 1; j <= k; j++) {
s += cache[j].toString(",", grammar.tokenManager.getVocabulary());
if (j < k && cache[j + 1] != null) s += ";";
}
s += "}:";
}
// dump alternative including pred (if any)
AlternativeElement p = alt.head;
String pred = alt.semPred;
if (pred != null) {
s += pred;
}
while (p != null) {
s += p;
p = p.next;
}
if (i < (alternatives.size() - 1)) {
s += " |";
}
}
s += " )";
return s;
}
}