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	import java.util.Hashtable;
35	
36	/**A list of alternatives and info contained in
37	 * the rule definition.
38	 */
39	public class RuleBlock extends AlternativeBlock {
40		protected String ruleName;
41		protected String argAction = null;		// string for rule arguments [...]
42		protected String returnAction = null;	// string for rule return type(s) <...>
43		protected RuleEndElement endNode;		// which node ends this rule?
44	
45		// Generate literal-testing code for lexer rule?
46		protected boolean testLiterals=false;
47	
48		Vector labeledElements;			// List of labeled elements found in this rule
49										// This is a list of AlternativeElement (or subclass)
50	
51		protected boolean[] lock;		// for analysis; used to avoid infinite loops
52										// 1..k
53		protected Lookahead cache[];	// Each rule can cache it's lookahead computation.
54										// This cache contains an epsilon
55										// imaginary token if the FOLLOW is required.  No
56										// FOLLOW information is cached here.
57										// The FIRST(rule) is stored in this cache; 1..k
58										// This set includes FIRST of all alts.
59	
60		Hashtable exceptionSpecs;		// table of String-to-ExceptionSpec.
61	
62		// grammar-settable options
63		protected boolean defaultErrorHandler = true;
64		protected String  ignoreRule = null;
65	
66	
67		/** Construct a named rule. */
68		public RuleBlock(Grammar g, String r) {
69			super(g);
70			ruleName = r;
71			labeledElements = new Vector();
72			cache = new Lookahead[g.maxk+1];
73			exceptionSpecs = new Hashtable();
74			setAutoGen(g instanceof ParserGrammar);
75		}
76		/** Construct a named rule with line number information */
77		public RuleBlock(Grammar g, String r, int line, boolean doAutoGen_) {
78			this(g,r);
79			this.line = line;
80			setAutoGen(doAutoGen_);
81		}
82		public void addExceptionSpec(ExceptionSpec ex) {
83			if (findExceptionSpec(ex.label) != null) {
84				if (ex.label != null) {
85					grammar.tool.error("Rule '" + ruleName + "' already has an exception handler for label: " + ex.label);
86				}
87				else {
88					grammar.tool.error("Rule '" + ruleName + "' already has an exception handler");
89				}
90			} 
91			else {
92				exceptionSpecs.put( (ex.label==null ? "" : ex.label.getText()), ex);
93			}
94		}
95		public ExceptionSpec findExceptionSpec(Token label) {
96			return (ExceptionSpec)exceptionSpecs.get(label==null ? "" : label.getText());
97		}
98		public ExceptionSpec findExceptionSpec(String label) {
99			return (ExceptionSpec)exceptionSpecs.get(label==null ? "" : label);
100		}
101		public void generate() {
102			grammar.generator.gen(this);
103		}
104		public boolean getDefaultErrorHandler() { 
105			return defaultErrorHandler;
106		}
107		public RuleEndElement getEndElement() {
108			return endNode;
109		}
110		public String getIgnoreRule() {
111			return ignoreRule;
112		}
113		public String getRuleName() {
114			return ruleName;
115		}
116		public boolean getTestLiterals() {
117			return testLiterals;
118		}
119		public boolean isLexerAutoGenRule() {
120			return ruleName.equals("nextToken");
121		}
122		public Lookahead look(int k) {
123			return grammar.theLLkAnalyzer.look(k, this);
124		}
125		public void prepareForAnalysis() {
126			super.prepareForAnalysis();
127			lock = new boolean[grammar.maxk+1];
128		}
129		// rule option values
130		public void setDefaultErrorHandler(boolean value) { 
131			defaultErrorHandler = value;
132		}
133		public void setEndElement(RuleEndElement re) {
134			endNode = re;
135		}
136		public void setOption(Token key, Token value) {
137			if (key.getText().equals("defaultErrorHandler")) {
138				if (value.getText().equals("true")) {
139					defaultErrorHandler = true;
140				} else if (value.getText().equals("false")) {
141					defaultErrorHandler = false;
142				} else {
143					grammar.tool.error("Value for defaultErrorHandler must be true or false", key.getLine());
144				}
145			} 
146			else if (key.getText().equals("testLiterals")) {
147				if (!(grammar instanceof LexerGrammar)) {
148					grammar.tool.error("testLiterals option only valid for lexer rules", key.getLine());
149				}
150				else {
151					if (value.getText().equals("true")) {
152						testLiterals = true;
153					} else if (value.getText().equals("false")) {
154						testLiterals = false;
155					} else {
156						grammar.tool.error("Value for testLiterals must be true or false", key.getLine());
157					}
158				}
159			}
160			else if (key.getText().equals("ignore")) {
161				if (!(grammar instanceof LexerGrammar)) {
162					grammar.tool.error("ignore option only valid for lexer rules", key.getLine());
163				}
164				else {
165					ignoreRule = value.getText();
166				}
167			} 
168			else if (key.getText().equals("paraphrase")) {
169				if (!(grammar instanceof LexerGrammar)) {
170					grammar.tool.error("paraphrase option only valid for lexer rules", key.getLine());
171				}
172				else {
173					// find token def associated with this rule
174					TokenSymbol ts = grammar.tokenManager.getTokenSymbol(ruleName);
175					if ( ts==null ) {
176						antlr.Tool.panic("cannot find token associated with rule "+ruleName);
177					}
178					ts.setParaphrase(value.getText());
179				}
180			} 
181			else if (key.equals("generateAmbigWarnings")) {
182				if (value.getText().equals("true")) {
183					generateAmbigWarnings = true;
184				} else if (value.getText().equals("false")) {
185					generateAmbigWarnings = false;
186				} else {
187					grammar.tool.error("Value for generateAmbigWarnings must be true or false", key.getLine());
188				}
189			}
190			else {
191				grammar.tool.error("Invalid rule option: " + key.getText(), key.getLine());
192			}
193		}
194		public String toString() {
195			return ruleName + ": " + super.toString() + " ;";
196		}
197	}
198