/*******************************************************************************
* Copyright (c) 2008 Scott Stanchfield.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Based on the ANTLR parser generator by Terence Parr, http://antlr.org
* Ric Klaren <klaren@cs.utwente.nl>
* Scott Stanchfield - Modifications for XML Parsing
*******************************************************************************/
package com.javadude.antxr.preprocessor;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import com.javadude.antxr.ANTXRException;
import com.javadude.antxr.TokenStreamException;
import com.javadude.antxr.Tool;
import com.javadude.antxr.collections.impl.IndexedVector;
public class Hierarchy {
protected Grammar LexerRoot = null;
protected Grammar ParserRoot = null;
protected Grammar TreeParserRoot = null;
protected Map<String, Grammar> symbols; // table of grammars
protected Map<String, GrammarFile> files; // table of grammar files read in
protected Tool antxrTool;
public Hierarchy(Tool tool) {
this.antxrTool = tool;
LexerRoot = new Grammar(tool, "Lexer", null, null);
ParserRoot = new Grammar(tool, "Parser", null, null);
TreeParserRoot = new Grammar(tool, "TreeParser", null, null);
symbols = new HashMap<String, Grammar>();
files = new HashMap<String, GrammarFile>();
LexerRoot.setPredefined(true);
ParserRoot.setPredefined(true);
TreeParserRoot.setPredefined(true);
symbols.put(LexerRoot.getName(), LexerRoot);
symbols.put(ParserRoot.getName(), ParserRoot);
symbols.put(TreeParserRoot.getName(), TreeParserRoot);
}
public void addGrammar(Grammar gr) {
gr.setHierarchy(this);
// add grammar to hierarchy
symbols.put(gr.getName(), gr);
// add grammar to file.
GrammarFile f = getFile(gr.getFileName());
f.addGrammar(gr);
}
public void addGrammarFile(GrammarFile gf) {
files.put(gf.getName(), gf);
}
public void expandGrammarsInFile(String fileName) {
GrammarFile f = getFile(fileName);
for (Grammar g : f.getGrammars()) {
g.expandInPlace();
}
}
public Grammar findRoot(Grammar g) {
if (g.getSuperGrammarName() == null) { // at root
return g;
}
// return root of super.
Grammar sg = g.getSuperGrammar();
if (sg == null) {
return g; // return this grammar if super missing
}
return findRoot(sg);
}
public GrammarFile getFile(String fileName) {
return files.get(fileName);
}
public Grammar getGrammar(String gr) {
return symbols.get(gr);
}
public static String optionsToString(IndexedVector<Option> options) {
String s = "options {" + System.getProperty("line.separator");
for (Option o : options) {
s += o + System.getProperty("line.separator");
}
s += "}" +
System.getProperty("line.separator") +
System.getProperty("line.separator");
return s;
}
public void readGrammarFile(String file) throws FileNotFoundException {
Reader grStream = new BufferedReader(new FileReader(file));
addGrammarFile(new GrammarFile(antxrTool, file));
// Create the simplified grammar lexer/parser
PreprocessorLexer ppLexer = new PreprocessorLexer(grStream);
ppLexer.setFilename(file);
Preprocessor pp = new Preprocessor(ppLexer);
pp.setTool(antxrTool);
pp.setFilename(file);
// populate the hierarchy with class(es) read in
try {
pp.grammarFile(this, file);
}
catch (TokenStreamException io) {
antxrTool.toolError("Token stream error reading grammar(s):\n" + io);
}
catch (ANTXRException se) {
antxrTool.toolError("error reading grammar(s):\n" + se);
}
}
/** Return true if hierarchy is complete, false if not */
public boolean verifyThatHierarchyIsComplete() {
boolean complete = true;
// Make a pass to ensure all grammars are defined
for (Grammar c : symbols.values()) {
if (c.getSuperGrammarName() == null) {
continue; // at root: ignore predefined roots
}
Grammar superG = c.getSuperGrammar();
if (superG == null) {
antxrTool.toolError("grammar " + c.getSuperGrammarName() + " not defined");
complete = false;
symbols.remove(c.getName()); // super not defined, kill sub
}
}
if (!complete) {
return false;
}
// Make another pass to set the 'type' field of each grammar
// This makes it easy later to ask a grammar what its type
// is w/o having to search hierarchy.
for (Grammar c : symbols.values()) {
if (c.getSuperGrammarName() == null) {
continue; // ignore predefined roots
}
c.setType(findRoot(c).getName());
}
return true;
}
public Tool getTool() {
return antxrTool;
}
public void setTool(Tool antxrTool) {
this.antxrTool = antxrTool;
}
}