/*
 * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * California 95054, U.S.A. All rights reserved.  Sun Microsystems, Inc. has
 * intellectual property rights relating to technology embodied in the product
 * that is described in this document. In particular, and without limitation,
 * these intellectual property rights may include one or more of the U.S.
 * patents listed at http://www.sun.com/patents and one or more additional
 * patents or pending patent applications in the U.S. and in other countries.
 * U.S. Government Rights - Commercial software. Government users are subject
 * to the Sun Microsystems, Inc. standard license agreement and applicable
 * provisions of the FAR and its supplements.  Use is subject to license terms.
 * Sun,  Sun Microsystems,  the Sun logo and  Java are trademarks or registered
 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.  This
 * product is covered and controlled by U.S. Export Control laws and may be
 * subject to the export or import laws in other countries.  Nuclear, missile,
 * chemical biological weapons or nuclear maritime end uses or end users,
 * whether direct or indirect, are strictly prohibited.  Export or reexport
 * to countries subject to U.S. embargo or to entities identified on U.S.
 * export exclusion lists, including, but not limited to, the denied persons
 * and specially designated nationals lists is strictly prohibited.
 */

package org.javacc.parser;
import java.util.Vector;

/**
 * Describes regular expressions which are choices from
 * from among included regular expressions.
 */

public class RChoice extends RegularExpression {

  /**
   * The list of choices of this regular expression.  Each
   * Vector component will narrow to RegularExpression.
   */
  public java.util.Vector choices = new java.util.Vector();

  public Nfa GenerateNfa(boolean ignoreCase)
  {
     CompressCharLists();

     if (choices.size() == 1)
        return ((RegularExpression)choices.elementAt(0)).GenerateNfa(ignoreCase);

     Nfa retVal = new Nfa();
     NfaState startState = retVal.start;
     NfaState finalState = retVal.end;

     for (int i = 0; i < choices.size(); i++)
     {
        Nfa temp;
        RegularExpression curRE = (RegularExpression)choices.elementAt(i);

        temp = curRE.GenerateNfa(ignoreCase);

        startState.AddMove(temp.start);
        temp.end.AddMove(finalState);
     }

     return retVal;
  }

  void CompressCharLists()
  { 
     CompressChoices(); // Unroll nested choices
     RegularExpression curRE;
     RCharacterList curCharList = null;

     for (int i = 0; i < choices.size(); i++)
     {
        curRE = (RegularExpression)choices.elementAt(i);

        while (curRE instanceof RJustName)
           curRE = ((RJustName)curRE).regexpr;

        if (curRE instanceof RStringLiteral &&
            ((RStringLiteral)curRE).image.length() == 1)
           choices.setElementAt(curRE = new RCharacterList(
                      ((RStringLiteral)curRE).image.charAt(0)), i);

        if (curRE instanceof RCharacterList)
        {
           if (((RCharacterList)curRE).negated_list)
              ((RCharacterList)curRE).RemoveNegation();

           Vector tmp = ((RCharacterList)curRE).descriptors;

           if (curCharList == null)
              choices.setElementAt(curRE = curCharList =
                                    new RCharacterList(), i);
           else
              choices.removeElementAt(i--);

           for (int j = tmp.size(); j-- > 0;)
              curCharList.descriptors.addElement(tmp.elementAt(j));
         }

     }
  }

  void CompressChoices()
  {
     RegularExpression curRE;

     for (int i = 0; i < choices.size(); i++)
     {
        curRE = (RegularExpression)choices.elementAt(i);

        while (curRE instanceof RJustName)
           curRE = ((RJustName)curRE).regexpr;

        if (curRE instanceof RChoice)
        {
           choices.removeElementAt(i--);
           for (int j = ((RChoice)curRE).choices.size(); j-- > 0;)
              choices.addElement(((RChoice)curRE).choices.elementAt(j));
        }
     }
  }

  public void CheckUnmatchability()
  {
     RegularExpression curRE;
     int numStrings = 0;

     for (int i = 0; i < choices.size(); i++)
     {
        if (!(curRE = (RegularExpression)choices.elementAt(i)).private_rexp &&
            //curRE instanceof RJustName &&
            curRE.ordinal > 0 && curRE.ordinal < ordinal &&
            LexGen.lexStates[curRE.ordinal] == LexGen.lexStates[ordinal])
        {
           if (label != null)
              JavaCCErrors.warning(this, "Regular Expression choice : " +
                 curRE.label + " can never be matched as : " + label);
           else
              JavaCCErrors.warning(this, "Regular Expression choice : " +
                 curRE.label + " can never be matched as token of kind : " +
                                                                      ordinal);
        }

        if (!curRE.private_rexp && curRE instanceof RStringLiteral)
           numStrings++;
     }
  }

}
