001: package antlr.preprocessor;
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.IndexedVector;
009:
010: import java.util.Hashtable;
011: import java.util.Enumeration;
012: import java.io.IOException;
013:
014: class Grammar {
015: protected String name;
016: protected String fileName; // where does it come from?
017: protected String super Grammar; // null if no super class
018: protected String type; // lexer? parser? tree parser?
019: protected IndexedVector rules; // text of rules as they were read in
020: protected IndexedVector options;// rule options
021: protected String tokenSection; // the tokens{} stuff
022: protected String preambleAction;// action right before grammar
023: protected String memberAction; // action inside grammar
024: protected Hierarchy hier; // hierarchy of grammars
025: protected boolean predefined = false; // one of the predefined grammars?
026: protected boolean alreadyExpanded = false;
027: protected boolean specifiedVocabulary = false; // found importVocab option?
028:
029: /** if not derived from another grammar, might still specify a non-ANTLR
030: * class to derive from like this "class T extends Parser(MyParserClass);"
031: */
032: protected String super Class = null;
033:
034: protected String importVocab = null;
035: protected String exportVocab = null;
036: protected antlr.Tool antlrTool;
037:
038: public Grammar(antlr.Tool tool, String name, String super Grammar,
039: IndexedVector rules) {
040: this .name = name;
041: this .super Grammar = super Grammar;
042: this .rules = rules;
043: this .antlrTool = tool;
044: }
045:
046: public void addOption(Option o) {
047: if (options == null) { // if not already there, create it
048: options = new IndexedVector();
049: }
050: options.appendElement(o.getName(), o);
051: }
052:
053: public void addRule(Rule r) {
054: rules.appendElement(r.getName(), r);
055: }
056:
057: /** Copy all nonoverridden rules, vocabulary, and options into this grammar from
058: * supergrammar chain. The change is made in place; e.g., this grammar's vector
059: * of rules gets bigger. This has side-effects: all grammars on path to
060: * root of hierarchy are expanded also.
061: */
062: public void expandInPlace() {
063: // if this grammar already expanded, just return
064: if (alreadyExpanded) {
065: return;
066: }
067:
068: // Expand super grammar first (unless it's a predefined or subgrammar of predefined)
069: Grammar super G = getSuperGrammar();
070: if (super G == null)
071: return; // error (didn't provide superclass)
072: if (exportVocab == null) {
073: // if no exportVocab for this grammar, make it same as grammar name
074: exportVocab = getName();
075: }
076: if (super G.isPredefined())
077: return; // can't expand Lexer, Parser, ...
078: super G.expandInPlace();
079:
080: // expand current grammar now.
081: alreadyExpanded = true;
082: // track whether a grammar file needed to have a grammar expanded
083: GrammarFile gf = hier.getFile(getFileName());
084: gf.setExpanded(true);
085:
086: // Copy rules from supergrammar into this grammar
087: IndexedVector inhRules = super G.getRules();
088: for (Enumeration e = inhRules.elements(); e.hasMoreElements();) {
089: Rule r = (Rule) e.nextElement();
090: inherit(r, super G);
091: }
092:
093: // Copy options from supergrammar into this grammar
094: // Modify tokdef options so that they point to dir of enclosing grammar
095: IndexedVector inhOptions = super G.getOptions();
096: if (inhOptions != null) {
097: for (Enumeration e = inhOptions.elements(); e
098: .hasMoreElements();) {
099: Option o = (Option) e.nextElement();
100: inherit(o, super G);
101: }
102: }
103:
104: // add an option to load the superGrammar's output vocab
105: if ((options != null && options.getElement("importVocab") == null)
106: || options == null) {
107: // no importVocab found, add one that grabs superG's output vocab
108: Option inputV = new Option("importVocab",
109: super G.exportVocab + ";", this );
110: addOption(inputV);
111: // copy output vocab file to current dir
112: String originatingGrFileName = super G.getFileName();
113: String path = antlrTool.pathToFile(originatingGrFileName);
114: String super ExportVocabFileName = path + super G.exportVocab
115: + antlr.CodeGenerator.TokenTypesFileSuffix
116: + antlr.CodeGenerator.TokenTypesFileExt;
117: String newImportVocabFileName = antlrTool
118: .fileMinusPath(super ExportVocabFileName);
119: if (path.equals("." + System.getProperty("file.separator"))) {
120: // don't copy tokdef file onto itself (must be current directory)
121: // System.out.println("importVocab file same dir; leaving as " + superExportVocabFileName);
122: } else {
123: try {
124: antlrTool.copyFile(super ExportVocabFileName,
125: newImportVocabFileName);
126: } catch (IOException io) {
127: antlrTool
128: .toolError("cannot find/copy importVocab file "
129: + super ExportVocabFileName);
130: return;
131: }
132: }
133: }
134:
135: // copy member action from supergrammar into this grammar
136: inherit(super G.memberAction, super G);
137: }
138:
139: public String getFileName() {
140: return fileName;
141: }
142:
143: public String getName() {
144: return name;
145: }
146:
147: public IndexedVector getOptions() {
148: return options;
149: }
150:
151: public IndexedVector getRules() {
152: return rules;
153: }
154:
155: public Grammar getSuperGrammar() {
156: if (super Grammar == null)
157: return null;
158: Grammar g = (Grammar) hier.getGrammar(super Grammar);
159: return g;
160: }
161:
162: public String getSuperGrammarName() {
163: return super Grammar;
164: }
165:
166: public String getType() {
167: return type;
168: }
169:
170: public void inherit(Option o, Grammar super G) {
171: // do NOT inherit importVocab/exportVocab options under any circumstances
172: if (o.getName().equals("importVocab")
173: || o.getName().equals("exportVocab")) {
174: return;
175: }
176:
177: Option overriddenOption = null;
178: if (options != null) { // do we even have options?
179: overriddenOption = (Option) options.getElement(o.getName());
180: }
181: // if overridden, do not add to this grammar
182: if (overriddenOption == null) { // not overridden
183: addOption(o); // copy option into this grammar--not overridden
184: }
185: }
186:
187: public void inherit(Rule r, Grammar super G) {
188: // if overridden, do not add to this grammar
189: Rule overriddenRule = (Rule) rules.getElement(r.getName());
190: if (overriddenRule != null) {
191: // rule is overridden in this grammar.
192: if (!overriddenRule.sameSignature(r)) {
193: // warn if different sig
194: antlrTool.warning("rule " + getName() + "."
195: + overriddenRule.getName()
196: + " has different signature than "
197: + super G.getName() + "."
198: + overriddenRule.getName());
199: }
200: } else { // not overridden, copy rule into this
201: addRule(r);
202: }
203: }
204:
205: public void inherit(String memberAction, Grammar super G) {
206: if (this .memberAction != null)
207: return; // do nothing if already have member action
208: if (memberAction != null) { // don't have one here, use supergrammar's action
209: this .memberAction = memberAction;
210: }
211: }
212:
213: public boolean isPredefined() {
214: return predefined;
215: }
216:
217: public void setFileName(String f) {
218: fileName = f;
219: }
220:
221: public void setHierarchy(Hierarchy hier) {
222: this .hier = hier;
223: }
224:
225: public void setMemberAction(String a) {
226: memberAction = a;
227: }
228:
229: public void setOptions(IndexedVector options) {
230: this .options = options;
231: }
232:
233: public void setPreambleAction(String a) {
234: preambleAction = a;
235: }
236:
237: public void setPredefined(boolean b) {
238: predefined = b;
239: }
240:
241: public void setTokenSection(String tk) {
242: tokenSection = tk;
243: }
244:
245: public void setType(String t) {
246: type = t;
247: }
248:
249: public String toString() {
250: StringBuffer s = new StringBuffer(10000);
251: if (preambleAction != null) {
252: s.append(preambleAction);
253: }
254: if (super Grammar == null) {
255: return "class " + name + ";";
256: }
257: if (super Class != null) {
258: // replace with specified superclass not actual grammar
259: // user must make sure that the superclass derives from super grammar class
260: s.append("class " + name + " extends " + super Class + ";");
261: } else {
262: s.append("class " + name + " extends " + type + ";");
263: }
264: s.append(System.getProperty("line.separator")
265: + System.getProperty("line.separator"));
266: if (options != null) {
267: s.append(Hierarchy.optionsToString(options));
268: }
269: if (tokenSection != null) {
270: s.append(tokenSection + "\n");
271: }
272: if (memberAction != null) {
273: s.append(memberAction
274: + System.getProperty("line.separator"));
275: }
276: for (int i = 0; i < rules.size(); i++) {
277: Rule r = (Rule) rules.elementAt(i);
278: if (!getName().equals(r.enclosingGrammar.getName())) {
279: s.append("// inherited from grammar "
280: + r.enclosingGrammar.getName()
281: + System.getProperty("line.separator"));
282: }
283: s.append(r + System.getProperty("line.separator")
284: + System.getProperty("line.separator"));
285: }
286: return s.toString();
287: }
288: }
|