001: package persistence.antlr;
002:
003: /* ANTLR Translator Generator
004: * Project led by Terence Parr at http://www.jGuru.com
005: * Software rights: http://www.antlr.org/license.html
006: *
007: */
008:
009: import persistence.antlr.collections.impl.Vector;
010:
011: import java.util.Hashtable;
012:
013: /**A list of alternatives and info contained in
014: * the rule definition.
015: */
016: public class RuleBlock extends AlternativeBlock {
017: protected String ruleName;
018: protected String argAction = null; // string for rule arguments [...]
019: protected String throwsSpec = null;
020: protected String returnAction = null;// string for rule return type(s) <...>
021: protected RuleEndElement endNode; // which node ends this rule?
022:
023: // Generate literal-testing code for lexer rule?
024: protected boolean testLiterals = false;
025:
026: Vector labeledElements; // List of labeled elements found in this rule
027: // This is a list of AlternativeElement (or subclass)
028:
029: protected boolean[] lock; // for analysis; used to avoid infinite loops
030: // 1..k
031: protected Lookahead cache[];// Each rule can cache it's lookahead computation.
032:
033: // This cache contains an epsilon
034: // imaginary token if the FOLLOW is required. No
035: // FOLLOW information is cached here.
036: // The FIRST(rule) is stored in this cache; 1..k
037: // This set includes FIRST of all alts.
038:
039: Hashtable exceptionSpecs; // table of String-to-ExceptionSpec.
040:
041: // grammar-settable options
042: protected boolean defaultErrorHandler = true;
043: protected String ignoreRule = null;
044:
045: /** Construct a named rule. */
046: public RuleBlock(Grammar g, String r) {
047: super (g);
048: ruleName = r;
049: labeledElements = new Vector();
050: cache = new Lookahead[g.maxk + 1];
051: exceptionSpecs = new Hashtable();
052: setAutoGen(g instanceof ParserGrammar);
053: }
054:
055: /** Construct a named rule with line number information */
056: public RuleBlock(Grammar g, String r, int line, boolean doAutoGen_) {
057: this (g, r);
058: this .line = line;
059: setAutoGen(doAutoGen_);
060: }
061:
062: public void addExceptionSpec(ExceptionSpec ex) {
063: if (findExceptionSpec(ex.label) != null) {
064: if (ex.label != null) {
065: grammar.antlrTool
066: .error("Rule '"
067: + ruleName
068: + "' already has an exception handler for label: "
069: + ex.label);
070: } else {
071: grammar.antlrTool.error("Rule '" + ruleName
072: + "' already has an exception handler");
073: }
074: } else {
075: exceptionSpecs.put((ex.label == null ? "" : ex.label
076: .getText()), ex);
077: }
078: }
079:
080: public ExceptionSpec findExceptionSpec(Token label) {
081: return (ExceptionSpec) exceptionSpecs.get(label == null ? ""
082: : label.getText());
083: }
084:
085: public ExceptionSpec findExceptionSpec(String label) {
086: return (ExceptionSpec) exceptionSpecs.get(label == null ? ""
087: : label);
088: }
089:
090: public void generate() {
091: grammar.generator.gen(this );
092: }
093:
094: public boolean getDefaultErrorHandler() {
095: return defaultErrorHandler;
096: }
097:
098: public RuleEndElement getEndElement() {
099: return endNode;
100: }
101:
102: public String getIgnoreRule() {
103: return ignoreRule;
104: }
105:
106: public String getRuleName() {
107: return ruleName;
108: }
109:
110: public boolean getTestLiterals() {
111: return testLiterals;
112: }
113:
114: public boolean isLexerAutoGenRule() {
115: return ruleName.equals("nextToken");
116: }
117:
118: public Lookahead look(int k) {
119: return grammar.theLLkAnalyzer.look(k, this );
120: }
121:
122: public void prepareForAnalysis() {
123: super .prepareForAnalysis();
124: lock = new boolean[grammar.maxk + 1];
125: }
126:
127: // rule option values
128: public void setDefaultErrorHandler(boolean value) {
129: defaultErrorHandler = value;
130: }
131:
132: public void setEndElement(RuleEndElement re) {
133: endNode = re;
134: }
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.antlrTool
144: .error(
145: "Value for defaultErrorHandler must be true or false",
146: grammar.getFilename(), key.getLine(),
147: key.getColumn());
148: }
149: } else if (key.getText().equals("testLiterals")) {
150: if (!(grammar instanceof LexerGrammar)) {
151: grammar.antlrTool
152: .error(
153: "testLiterals option only valid for lexer rules",
154: grammar.getFilename(), key.getLine(),
155: key.getColumn());
156: } else {
157: if (value.getText().equals("true")) {
158: testLiterals = true;
159: } else if (value.getText().equals("false")) {
160: testLiterals = false;
161: } else {
162: grammar.antlrTool
163: .error(
164: "Value for testLiterals must be true or false",
165: grammar.getFilename(), key
166: .getLine(), key.getColumn());
167: }
168: }
169: } else if (key.getText().equals("ignore")) {
170: if (!(grammar instanceof LexerGrammar)) {
171: grammar.antlrTool.error(
172: "ignore option only valid for lexer rules",
173: grammar.getFilename(), key.getLine(), key
174: .getColumn());
175: } else {
176: ignoreRule = value.getText();
177: }
178: } else if (key.getText().equals("paraphrase")) {
179: if (!(grammar instanceof LexerGrammar)) {
180: grammar.antlrTool.error(
181: "paraphrase option only valid for lexer rules",
182: grammar.getFilename(), key.getLine(), key
183: .getColumn());
184: } else {
185: // find token def associated with this rule
186: TokenSymbol ts = grammar.tokenManager
187: .getTokenSymbol(ruleName);
188: if (ts == null) {
189: grammar.antlrTool
190: .panic("cannot find token associated with rule "
191: + ruleName);
192: }
193: ts.setParaphrase(value.getText());
194: }
195: } else if (key.getText().equals("generateAmbigWarnings")) {
196: if (value.getText().equals("true")) {
197: generateAmbigWarnings = true;
198: } else if (value.getText().equals("false")) {
199: generateAmbigWarnings = false;
200: } else {
201: grammar.antlrTool
202: .error(
203: "Value for generateAmbigWarnings must be true or false",
204: grammar.getFilename(), key.getLine(),
205: key.getColumn());
206: }
207: } else {
208: grammar.antlrTool.error("Invalid rule option: "
209: + key.getText(), grammar.getFilename(), key
210: .getLine(), key.getColumn());
211: }
212: }
213:
214: public String toString() {
215: String s = " FOLLOW={";
216: Lookahead cache[] = endNode.cache;
217: int k = grammar.maxk;
218: boolean allNull = true;
219: for (int j = 1; j <= k; j++) {
220: if (cache[j] == null)
221: continue;
222: s += cache[j].toString(",", grammar.tokenManager
223: .getVocabulary());
224: allNull = false;
225: if (j < k && cache[j + 1] != null)
226: s += ";";
227: }
228: s += "}";
229: if (allNull)
230: s = "";
231: return ruleName + ": " + super .toString() + " ;" + s;
232: }
233: }
|