1	package antlr.preprocessor;
2	
3	import antlr.collections.impl.IndexedVector;
4	import java.util.Hashtable;
5	import java.util.Enumeration;
6	import java.io.*;
7	import antlr.*;
8	import antlr.preprocessor.Grammar;
9	
10	public class Hierarchy {
11		protected static Grammar LexerRoot = new Grammar("Lexer", null, null);
12		protected static Grammar ParserRoot = new Grammar("Parser", null, null);
13		protected static Grammar TreeParserRoot = new Grammar("TreeParser", null, null);
14		protected Hashtable symbols;	// table of grammars
15		protected Hashtable files;	// table of grammar files read in
16	
17		public Hierarchy() {
18			symbols = new Hashtable(10);
19			files = new Hashtable(10);
20			
21			LexerRoot.setPredefined(true);
22			ParserRoot.setPredefined(true);
23			TreeParserRoot.setPredefined(true);
24			
25			symbols.put(LexerRoot.getName(), LexerRoot);
26			symbols.put(ParserRoot.getName(), ParserRoot);
27			symbols.put(TreeParserRoot.getName(), TreeParserRoot);
28		}
29		public void addGrammar(Grammar gr) {
30			gr.setHierarchy(this);
31			// add grammar to hierarchy
32			symbols.put(gr.getName(), gr);
33			// add grammar to file.
34			GrammarFile f = getFile(gr.getFileName());
35			f.addGrammar(gr);
36		}
37		public void addGrammarFile(GrammarFile gf) {
38			files.put(gf.getName(), gf);
39		}
40		public void expandGrammarsInFile(String fileName) {
41			GrammarFile f = getFile(fileName);
42			for (Enumeration e=f.getGrammars().elements(); e.hasMoreElements(); ) {
43				Grammar g = (Grammar)e.nextElement();
44				g.expandInPlace();
45			}	
46		}
47		public Grammar findRoot(Grammar g) {
48			if ( g.getSuperGrammarName()==null ) {		// at root
49				return g;
50			}
51			// return root of super.
52			Grammar sg = g.getSuperGrammar();
53			if ( sg==null ) return g;		// return this grammar if super missing
54			return findRoot(sg);
55		}
56		public GrammarFile getFile(String fileName) {
57			return (GrammarFile)files.get(fileName);
58		}
59		public Grammar getGrammar(String gr) {
60			return (Grammar)symbols.get(gr);
61		}
62		public static String optionsToString(IndexedVector options) {
63			String s = "options {"+System.getProperty("line.separator");
64			for (Enumeration e = options.elements() ; e.hasMoreElements() ;) {
65				s += (Option)e.nextElement()+System.getProperty("line.separator");
66			}
67			s += "}"+
68				System.getProperty("line.separator")+
69				System.getProperty("line.separator");
70			return s;
71		}
72		public void readGrammarFile(String file) throws FileNotFoundException {
73			FileReader grStream = new FileReader(file);
74			addGrammarFile(new GrammarFile(file));
75			
76			// Create the simplified grammar lexer/parser
77			PreprocessorLexer ppLexer = new PreprocessorLexer(grStream);
78			Preprocessor pp = new Preprocessor(ppLexer);
79	
80			// populate the hierarchy with class(es) read in
81			try {
82				pp.grammarFile(this, file);
83			}
84			catch (ANTLRException se) {
85				antlr.Tool.toolError("error reading grammar(s):"+se);
86			}
87			catch (IOException io) {
88				antlr.Tool.toolError("IO error reading grammar(s):"+io);
89			}
90		}
91		/** Return true if hierarchy is complete, false if not */
92		public boolean verifyThatHierarchyIsComplete() {
93			boolean complete = true;
94			// Make a pass to ensure all grammars are defined
95			for (Enumeration e = symbols.elements() ; e.hasMoreElements() ;) {
96				Grammar c = (Grammar)e.nextElement();
97				if ( c.getSuperGrammarName()==null ) {
98					continue;		// at root: ignore predefined roots
99				}
100				Grammar superG = c.getSuperGrammar();
101				if ( superG == null ) {
102					antlr.Tool.toolError("grammar "+c.getSuperGrammarName()+" not defined");
103					complete = false;
104					symbols.remove(c.getName()); // super not defined, kill sub
105				}
106			}
107		
108			if ( !complete ) return false;
109			
110			// Make another pass to set the 'type' field of each grammar
111			// This makes it easy later to ask a grammar what its type
112			// is w/o having to search hierarchy.
113			for (Enumeration e = symbols.elements() ; e.hasMoreElements() ;) {
114				Grammar c = (Grammar)e.nextElement();
115				if ( c.getSuperGrammarName()==null ) {
116					continue;		// ignore predefined roots
117				}
118				c.setType(findRoot(c).getName());
119			}
120			
121			return true;
122		}
123	}
124