01: /*
02: * xtc - The eXTensible Compiler
03: * Copyright (C) 2004-2007 Robert Grimm
04: *
05: * This program is free software; you can redistribute it and/or
06: * modify it under the terms of the GNU General Public License
07: * version 2 as published by the Free Software Foundation.
08: *
09: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with this program; if not, write to the Free Software
16: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17: * USA.
18: */
19: package xtc.parser;
20:
21: import java.util.Iterator;
22:
23: import xtc.Constants;
24:
25: import xtc.util.Runtime;
26:
27: /**
28: * Visitor to eliminate dead productions. This visitor eliminates
29: * productions that are not reachable from top-level productions. It
30: * may perform faster if the grammar has previously been annotated
31: * with its real root.
32: *
33: * @see RootFinder
34: *
35: * @author Robert Grimm
36: * @version $Revision: 1.39 $
37: */
38: public class DeadProductionEliminator extends GrammarVisitor {
39:
40: /**
41: * Create a new dead production eliminator.
42: *
43: * @param runtime The runtime.
44: * @param analyzer The analyzer utility.
45: */
46: public DeadProductionEliminator(Runtime runtime, Analyzer analyzer) {
47: super (runtime, analyzer);
48: }
49:
50: /** Visit the specified grammar. */
51: public Object visit(Module m) {
52: // Initialize the per-grammar state.
53: analyzer.register(this );
54: analyzer.init(m);
55:
56: // Mark all productions reachable from the top-level nonterminals.
57: if (m.hasProperty(Properties.ROOT)) {
58: dispatch((NonTerminal) m.getProperty(Properties.ROOT));
59:
60: } else {
61: for (Production p : m.productions) {
62: if (p.hasAttribute(Constants.ATT_PUBLIC)) {
63: dispatch(p.name);
64: }
65: }
66: }
67:
68: // Remove all productions that have not been marked.
69: for (Iterator<Production> iter = m.productions.iterator(); iter
70: .hasNext();) {
71: Production p = iter.next();
72:
73: if (!analyzer.isMarked(p.qName)) {
74: if (runtime.test("optionVerbose")) {
75: System.err.println("[Removing dead production "
76: + p.qName + "]");
77: }
78:
79: analyzer.remove((FullProduction) p);
80: iter.remove();
81: }
82: }
83:
84: // Done.
85: return null;
86: }
87:
88: /** Visit the specified nonterminal. */
89: public Element visit(NonTerminal nt) {
90: FullProduction p = analyzer.lookup(nt);
91:
92: if (!analyzer.isMarked(p.qName)) {
93: analyzer.mark(p.qName);
94: dispatch(p);
95: }
96: return nt;
97: }
98:
99: }
|