001: package antlr;
002:
003: /* ANTLR Translator Generator
004: * Project led by Terence Parr at http://www.jGuru.com
005: * Software rights: http://www.antlr.org/RIGHTS.html
006: *
007: * $Id: AlternativeBlock.java,v 1.1 2004/01/21 19:21:02 rgrimm Exp $
008: */
009:
010: import antlr.collections.impl.Vector;
011:
012: /**A list of alternatives */
013: class AlternativeBlock extends AlternativeElement {
014: protected String initAction = null; // string for init action {...}
015: protected Vector alternatives; // Contains Alternatives
016:
017: protected String label; // can label a looping block to break out of it.
018:
019: protected int alti, altj; // which alts are being compared at the moment with
020: // deterministic()?
021: protected int analysisAlt; // which alt are we computing look on? Must be alti or altj
022:
023: protected boolean hasAnAction = false; // does any alt have an action?
024: protected boolean hasASynPred = false; // does any alt have a syntactic predicate?
025:
026: protected int ID = 0; // used to generate unique variables
027: protected static int nblks; // how many blocks have we allocated?
028: boolean not = false; // true if block is inverted.
029:
030: boolean greedy = true; // Blocks are greedy by default
031: boolean greedySet = false; // but, if not explicitly greedy, warning might be generated
032:
033: protected boolean doAutoGen = true; // false if no AST (or text) to be generated for block
034:
035: protected boolean warnWhenFollowAmbig = true; // warn when an empty path or exit path
036:
037: protected boolean generateAmbigWarnings = true; // the general warning "shut-up" mechanism
038:
039: // conflicts with alt of subrule.
040: // Turning this off will suppress stuff
041: // like the if-then-else ambig.
042:
043: public AlternativeBlock(Grammar g) {
044: super (g);
045: alternatives = new Vector(5);
046: this .not = false;
047: nblks++;
048: ID = nblks;
049: }
050:
051: public AlternativeBlock(Grammar g, Token start, boolean not) {
052: super (g, start);
053: alternatives = new Vector(5);
054: // this.line = start.getLine();
055: // this.column = start.getColumn();
056: this .not = not;
057: nblks++;
058: ID = nblks;
059: }
060:
061: public void addAlternative(Alternative alt) {
062: alternatives.appendElement(alt);
063: }
064:
065: public void generate() {
066: grammar.generator.gen(this );
067: }
068:
069: public Alternative getAlternativeAt(int i) {
070: return (Alternative) alternatives.elementAt(i);
071: }
072:
073: public Vector getAlternatives() {
074: return alternatives;
075: }
076:
077: public boolean getAutoGen() {
078: return doAutoGen;
079: }
080:
081: public String getInitAction() {
082: return initAction;
083: }
084:
085: public String getLabel() {
086: return label;
087: }
088:
089: public Lookahead look(int k) {
090: return grammar.theLLkAnalyzer.look(k, this );
091: }
092:
093: public void prepareForAnalysis() {
094: for (int i = 0; i < alternatives.size(); i++) {
095: // deterministic() uses an alternative cache and sets lookahead depth
096: Alternative a = (Alternative) alternatives.elementAt(i);
097: a.cache = new Lookahead[grammar.maxk + 1];
098: a.lookaheadDepth = GrammarAnalyzer.LOOKAHEAD_DEPTH_INIT;
099: }
100: }
101:
102: /**Walk the syntactic predicate and, for a rule ref R, remove
103: * the ref from the list of FOLLOW references for R (stored
104: * in the symbol table.
105: */
106: public void removeTrackingOfRuleRefs(Grammar g) {
107: for (int i = 0; i < alternatives.size(); i++) {
108: Alternative alt = getAlternativeAt(i);
109: AlternativeElement elem = alt.head;
110: while (elem != null) {
111: if (elem instanceof RuleRefElement) {
112: RuleRefElement rr = (RuleRefElement) elem;
113: RuleSymbol rs = (RuleSymbol) g
114: .getSymbol(rr.targetRule);
115: if (rs == null) {
116: grammar.antlrTool
117: .error("rule "
118: + rr.targetRule
119: + " referenced in (...)=>, but not defined");
120: } else {
121: rs.references.removeElement(rr);
122: }
123: } else if (elem instanceof AlternativeBlock) {// recurse into subrules
124: ((AlternativeBlock) elem)
125: .removeTrackingOfRuleRefs(g);
126: }
127: elem = elem.next;
128: }
129: }
130: }
131:
132: public void setAlternatives(Vector v) {
133: alternatives = v;
134: }
135:
136: public void setAutoGen(boolean doAutoGen_) {
137: doAutoGen = doAutoGen_;
138: }
139:
140: public void setInitAction(String initAction_) {
141: initAction = initAction_;
142: }
143:
144: public void setLabel(String label_) {
145: label = label_;
146: }
147:
148: public void setOption(Token key, Token value) {
149: if (key.getText().equals("warnWhenFollowAmbig")) {
150: if (value.getText().equals("true")) {
151: warnWhenFollowAmbig = true;
152: } else if (value.getText().equals("false")) {
153: warnWhenFollowAmbig = false;
154: } else {
155: grammar.antlrTool
156: .error(
157: "Value for warnWhenFollowAmbig must be true or false",
158: grammar.getFilename(), key.getLine(),
159: key.getColumn());
160: }
161: } else if (key.getText().equals("generateAmbigWarnings")) {
162: if (value.getText().equals("true")) {
163: generateAmbigWarnings = true;
164: } else if (value.getText().equals("false")) {
165: generateAmbigWarnings = false;
166: } else {
167: grammar.antlrTool
168: .error(
169: "Value for generateAmbigWarnings must be true or false",
170: grammar.getFilename(), key.getLine(),
171: key.getColumn());
172: }
173: } else if (key.getText().equals("greedy")) {
174: if (value.getText().equals("true")) {
175: greedy = true;
176: greedySet = true;
177: } else if (value.getText().equals("false")) {
178: greedy = false;
179: greedySet = true;
180: } else {
181: grammar.antlrTool.error(
182: "Value for greedy must be true or false",
183: grammar.getFilename(), key.getLine(), key
184: .getColumn());
185: }
186: } else {
187: grammar.antlrTool.error("Invalid subrule option: "
188: + key.getText(), grammar.getFilename(), key
189: .getLine(), key.getColumn());
190: }
191: }
192:
193: public String toString() {
194: String s = " (";
195: if (initAction != null) {
196: s += initAction;
197: }
198: for (int i = 0; i < alternatives.size(); i++) {
199: Alternative alt = getAlternativeAt(i);
200: Lookahead cache[] = alt.cache;
201: int k = alt.lookaheadDepth;
202: // dump lookahead set
203: if (k == GrammarAnalyzer.LOOKAHEAD_DEPTH_INIT) {
204: } else if (k == GrammarAnalyzer.NONDETERMINISTIC) {
205: s += "{?}:";
206: } else {
207: s += " {";
208: for (int j = 1; j <= k; j++) {
209: s += cache[j].toString(",", grammar.tokenManager
210: .getVocabulary());
211: if (j < k && cache[j + 1] != null)
212: s += ";";
213: }
214: s += "}:";
215: }
216: // dump alternative including pred (if any)
217: AlternativeElement p = alt.head;
218: String pred = alt.semPred;
219: if (pred != null) {
220: s += pred;
221: }
222: while (p != null) {
223: s += p;
224: p = p.next;
225: }
226: if (i < (alternatives.size() - 1)) {
227: s += " |";
228: }
229: }
230: s += " )";
231: return s;
232: }
233:
234: }
|