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