/* * xtc - The eXTensible Compiler * Copyright (C) 2004-2006 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.util.Runtime; /** * Visitor to combine common prefixes into a single sequence with an * embedded choice. Note that the different alternatives in an * ordered choice must have been normalized into sequences. * * @author Robert Grimm * @version $Revision: 1.18 $ */ public class PrefixFolder extends GrammarVisitor { /** * Create a new prefix folder. * * @param runtime The runtime. * @param analyzer The analyzer utility. */ public PrefixFolder(Runtime runtime, Analyzer analyzer) { super(runtime, analyzer); } /** Visit the specified ordered choice. */ public Element visit(OrderedChoice c) { // First, see if we can find any common prefixes across several // alternatives. for (int i=0; i<c.alternatives.size(); i++) { Sequence s = c.alternatives.get(i); // Are there more with the same prefix? int j; for (j=i+1; j<c.alternatives.size(); j++) { if (! analyzer.haveCommonPrefix(s, c.alternatives.get(j))) { break; } } if (i != j-1) { // There are alternatives to optimize. Normalize them first. for (int k=i+1; k<j; k++) { c.alternatives.set(k, analyzer.normalizePrefix(s, c.alternatives.get(k))); } Element result = null; for (int k=i; k<j; k++) { result = analyzer.joinPrefixes(c.alternatives.get(k), result); } // Replace old alternatives with result. c.alternatives.subList(i, j).clear(); if (result instanceof Sequence) { c.alternatives.add(i, (Sequence)result); // Continue processing with i+1. } else { OrderedChoice choice = (OrderedChoice)result; c.alternatives.addAll(i, choice.alternatives); i += (choice.alternatives.size() - 1); } if (runtime.test("optionVerbose")) { System.err.println("[Folding prefixes in " + analyzer.current().qName + "]"); } } } // Next, process the alternatives individually. Note that the // number of alternatives may have changed. final int length = c.alternatives.size(); for (int i=0; i<length; i++) { c.alternatives.set(i, (Sequence)dispatch(c.alternatives.get(i))); } return c; } /** Visit the specified predicate. */ public Element visit(Predicate p) { // Ignore the element. In general, prefix folding may lead to // embedded ordered choices, which are not (yet) supported by the // code generator. return p; } }