/* * xtc - The eXTensible Compiler * Copyright (C) 2004-2007 Robert Grimm * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package xtc.parser; import java.util.Iterator; import xtc.Constants; import xtc.util.Runtime; /** * Visitor to eliminate dead productions. This visitor eliminates * productions that are not reachable from top-level productions. It * may perform faster if the grammar has previously been annotated * with its real root. * * @see RootFinder * * @author Robert Grimm * @version $Revision: 1.39 $ */ public class DeadProductionEliminator extends GrammarVisitor { /** * Create a new dead production eliminator. * * @param runtime The runtime. * @param analyzer The analyzer utility. */ public DeadProductionEliminator(Runtime runtime, Analyzer analyzer) { super(runtime, analyzer); } /** Visit the specified grammar. */ public Object visit(Module m) { // Initialize the per-grammar state. analyzer.register(this); analyzer.init(m); // Mark all productions reachable from the top-level nonterminals. if (m.hasProperty(Properties.ROOT)) { dispatch((NonTerminal)m.getProperty(Properties.ROOT)); } else { for (Production p : m.productions) { if (p.hasAttribute(Constants.ATT_PUBLIC)) { dispatch(p.name); } } } // Remove all productions that have not been marked. for(Iterator<Production> iter = m.productions.iterator(); iter.hasNext();) { Production p = iter.next(); if (! analyzer.isMarked(p.qName)) { if (runtime.test("optionVerbose")) { System.err.println("[Removing dead production " + p.qName + "]"); } analyzer.remove((FullProduction)p); iter.remove(); } } // Done. return null; } /** Visit the specified nonterminal. */ public Element visit(NonTerminal nt) { FullProduction p = analyzer.lookup(nt); if (! analyzer.isMarked(p.qName)) { analyzer.mark(p.qName); dispatch(p); } return nt; } }