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