/* * xtc - The eXTensible Compiler * Copyright (C) 2007-2008 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 xtc.tree.Visitor; import xtc.util.Runtime; /** * Visitor to ensure that every alternative is reachable. * * @author Robert Grimm * @version $Revision: 1.4 $ */ public class ReachabilityChecker extends Visitor { /** The runtime. */ protected Runtime runtime; /** The analyzer. */ protected Analyzer analyzer; /** * Create a new reachability checker. * * @param runtime The runtime. * @param analyzer The analyzer. */ public ReachabilityChecker(Runtime runtime, Analyzer analyzer) { this.runtime = runtime; this.analyzer = analyzer; } /** Visit the specified grammar. */ public void visit(Grammar g) { // Initialize the per-grammar state. analyzer.register(this); analyzer.init(g); // Process the modules and productions. for (Module m : g.modules) { analyzer.process(m); for (Production p : m.productions) { if (p.isFull()) { analyzer.process(p); } } } } /** Visit the specified module. */ public void visit(Module m) { // Initialize the per-grammar state. analyzer.register(this); analyzer.init(m); // Process the productions. for (Production p : m.productions) analyzer.process(p); } /** Visit the specified full production. */ public void visit(FullProduction p) { dispatch(p.choice); } /** Visit the specified choice. */ public void visit(OrderedChoice c) { final int size = c.alternatives.size(); for (int i=0; i<size; i++) { Sequence s = c.alternatives.get(i); if (! analyzer.restrictsInput(s) && (i < size-1)) { runtime.error("unreachable alternative", c.alternatives.get(i+1)); break; } else { dispatch(s); } } } /** Visit the specified sequence. */ public void visit(Sequence s) { for (Element e : s.elements) dispatch(e); } /** Visit the specified unary operator. */ public void visit(UnaryOperator op) { dispatch(op.element); } /** Visit the specified character switch. */ public void visit(CharSwitch s) { for (CharCase kase : s.cases) { dispatch(kase.element); } dispatch(s.base); } /** Visit the specified element. */ public void visit(Element e) { // Nothing to do. } }