1	package antlr;
2	
3	/**
4	 * <b>SOFTWARE RIGHTS</b>
5	 * <p>
6	 * ANTLR 2.5.0 MageLang Institute, 1998
7	 * <p>
8	 * We reserve no legal rights to the ANTLR--it is fully in the
9	 * public domain. An individual or company may do whatever
10	 * they wish with source code distributed with ANTLR or the
11	 * code generated by ANTLR, including the incorporation of
12	 * ANTLR, or its output, into commerical software.
13	 * <p>
14	 * We encourage users to develop software with ANTLR. However,
15	 * we do ask that credit is given to us for developing
16	 * ANTLR. By "credit", we mean that if you use ANTLR or
17	 * incorporate any source code into one of your programs
18	 * (commercial product, research project, or otherwise) that
19	 * you acknowledge this fact somewhere in the documentation,
20	 * research report, etc... If you like ANTLR and have
21	 * developed a nice tool with the output, please mention that
22	 * you developed it using ANTLR. In addition, we ask that the
23	 * headers remain intact in our source code. As long as these
24	 * guidelines are kept, we expect to continue enhancing this
25	 * system and expect to make other tools available as they are
26	 * completed.
27	 * <p>
28	 * The ANTLR gang:
29	 * @version ANTLR 2.5.0 MageLang Institute, 1998
30	 * @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
31	 * @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
32	 */
33	import antlr.collections.impl.Vector;
34	
35	/**A list of alternatives */
36	class AlternativeBlock extends AlternativeElement {
37		protected String initAction = null;	// string for init action {...}
38		protected Vector alternatives;	// Contains Alternatives
39	
40		protected String label;			// can label a looping block to break out of it.
41	
42		protected int alti, altj;		// which alts are being compared at the moment with
43										// deterministic()?
44		protected int analysisAlt;		// which alt are we computing look on?  Must be alti or altj
45	
46		protected boolean hasAnAction = false;	// does any alt have an action?
47		protected boolean hasASynPred = false;	// does any alt have a syntactic predicate?
48	
49		protected int ID=0;				// used to generate unique variables
50		protected static int nblks;	// how many blocks have we allocated?
51		boolean not = false;				// true if block is inverted.
52	
53		// JEL removed this because it was only used for synpred, and it was
54		// screwed up by the shell game played by EBNF replacing a subrule block
55		// with another block.
56		//protected AlternativeBlock enclosingBlock;
57		
58		protected boolean doAutoGen=true;	// false if no AST (or text) to be generated for block
59	
60		protected boolean warnWhenFollowAmbig = true; // warn when an empty path or exit path
61	
62		protected boolean generateAmbigWarnings = true;  // the general warning "shut-up" mechanism
63	
64																		// conflicts with alt of subrule.
65																		// Turning this off will suppress stuff
66																		// like the if-then-else ambig.
67	
68		public AlternativeBlock(Grammar g) {
69			this(g,0,false);
70		}
71		public AlternativeBlock(Grammar g, int line, boolean not) {
72			super(g);
73			alternatives = new Vector(5);
74			this.line = line;
75			this.not = not;
76			nblks++;
77			ID = nblks;
78		}
79		public void addAlternative(Alternative alt) {
80			alternatives.appendElement(alt);
81		}
82		public void generate() {
83			grammar.generator.gen(this);
84		}
85		public Alternative getAlternativeAt(int i)
86		{
87			return (Alternative)alternatives.elementAt(i);
88		}
89		public Vector getAlternatives() {
90			return alternatives;
91		}
92		public boolean getAutoGen() { 
93			return doAutoGen; 
94		}
95		public String getInitAction() { 
96			return initAction;
97		}
98		public String getLabel() {
99			return label;
100		}
101		public Lookahead look(int k) {
102			return grammar.theLLkAnalyzer.look(k, this);
103		}
104		public void prepareForAnalysis() {
105			for (int i=0; i<alternatives.size(); i++) {
106				// deterministic() uses an alternative cache and sets lookahead depth
107				Alternative a = (Alternative)alternatives.elementAt(i);
108				a.cache = new Lookahead[grammar.maxk+1];
109				a.lookaheadDepth = GrammarAnalyzer.LOOKAHEAD_DEPTH_INIT;
110			}
111		}
112		/**Walk the syntactic predicate and, for a rule ref R, remove
113		 * the ref from the list of FOLLOW references for R (stored
114		 * in the symbol table.
115		 */
116		public void removeTrackingOfRuleRefs(Grammar g) {
117			for (int i=0; i<alternatives.size(); i++) {
118				Alternative alt = getAlternativeAt(i);
119				AlternativeElement elem = alt.head;
120				while ( elem!=null ) {
121					if ( elem instanceof RuleRefElement ) {
122						RuleRefElement rr = (RuleRefElement)elem;
123						RuleSymbol rs = (RuleSymbol)g.getSymbol(rr.targetRule);
124						if ( rs==null ) {
125							grammar.tool.error("rule "+rr.targetRule+" referenced in (...)=>, but not defined");
126						}
127						else {
128							rs.references.removeElement(rr);
129						}	
130					}
131					else if ( elem instanceof AlternativeBlock ) {// recurse into subrules
132						((AlternativeBlock)elem).removeTrackingOfRuleRefs(g);
133					}
134					elem = elem.next;
135				}
136			}
137		}
138		public void setAlternatives(Vector v) {
139			alternatives = v;
140		}
141		public void setAutoGen(boolean doAutoGen_) {
142			doAutoGen = doAutoGen_;
143		}
144		public void setInitAction(String initAction_) {
145			initAction = initAction_;
146		}
147		public void setLabel(String label_) { 
148			label = label_; 
149		}
150		public void setOption(Token key, Token value) {
151			if (key.getText().equals("warnWhenFollowAmbig")) {
152				if (value.getText().equals("true")) {
153					warnWhenFollowAmbig = true;
154				} else if (value.getText().equals("false")) {
155					warnWhenFollowAmbig = false;
156				} else {
157					grammar.tool.error("Value for warnWhenFollowAmbig must be true or false", key.getLine());
158				}
159			} 
160			else if (key.getText().equals("generateAmbigWarnings")) {
161				if (value.getText().equals("true")) {
162					generateAmbigWarnings = true;
163				} else if (value.getText().equals("false")) {
164					generateAmbigWarnings = false;
165				} else {
166					grammar.tool.error("Value for generateAmbigWarnings must be true or false", key.getLine());
167				}
168			} 
169			else {
170				grammar.tool.error("Invalid subrule option: " + key.getText(), key.getLine());
171			}
172		}
173		public String toString() {
174			String s=" (";
175			if ( initAction!=null ) {
176				s += initAction;
177			}
178			for (int i=0; i<alternatives.size(); i++) {
179				Alternative alt = getAlternativeAt(i);
180				AlternativeElement p = alt.head;
181				String pred = alt.semPred;
182				if ( pred!=null ) {
183					s += pred;
184				}
185				while (p!=null ) {
186					s += p;
187					p = p.next;
188				}
189				if ( i<(alternatives.size()-1) ) {
190					s += " |";
191				}
192			}
193			s += " )";
194			return s;
195		}
196	}
197