All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javacc.parser.LookaheadCalc Maven / Gradle / Ivy

There is a newer version: 4.1.5
Show newest version
/* Copyright (c) 2006, Sun Microsystems, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Sun Microsystems, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.javacc.parser;

import java.util.ArrayList;
import java.util.List;

public class LookaheadCalc extends JavaCCGlobals
{

  static MatchInfo overlap (final List v1, final List v2)
  {
    MatchInfo m1, m2, m3;
    int size;
    boolean diff;
    for (int i = 0; i < v1.size (); i++)
    {
      m1 = (MatchInfo) v1.get (i);
      for (int j = 0; j < v2.size (); j++)
      {
        m2 = (MatchInfo) v2.get (j);
        size = m1.firstFreeLoc;
        m3 = m1;
        if (size > m2.firstFreeLoc)
        {
          size = m2.firstFreeLoc;
          m3 = m2;
        }
        if (size == 0)
          return null;
        // we wish to ignore empty expansions and the JAVACODE stuff here.
        diff = false;
        for (int k = 0; k < size; k++)
        {
          if (m1.match[k] != m2.match[k])
          {
            diff = true;
            break;
          }
        }
        if (!diff)
          return m3;
      }
    }
    return null;
  }

  static boolean javaCodeCheck (final List v)
  {
    for (int i = 0; i < v.size (); i++)
    {
      if (((MatchInfo) v.get (i)).firstFreeLoc == 0)
      {
        return true;
      }
    }
    return false;
  }

  static String image (final MatchInfo m)
  {
    String ret = "";
    for (int i = 0; i < m.firstFreeLoc; i++)
    {
      if (m.match[i] == 0)
      {
        ret += " ";
      }
      else
      {
        final RegularExpression re = (RegularExpression) rexps_of_tokens.get (new Integer (m.match[i]));
        if (re instanceof RStringLiteral)
        {
          ret += " \"" + add_escapes (((RStringLiteral) re).image) + "\"";
        }
        else
          if (re.label != null && !re.label.equals (""))
          {
            ret += " <" + re.label + ">";
          }
          else
          {
            ret += " ";
          }
      }
    }
    if (m.firstFreeLoc == 0)
    {
      return "";
    }
    else
    {
      return ret.substring (1);
    }
  }

  public static void choiceCalc (final Choice ch)
  {
    final int first = firstChoice (ch);
    // dbl[i] and dbr[i] are lists of size limited matches for choice i
    // of ch. dbl ignores matches with semantic lookaheads (when force_la_check
    // is false), while dbr ignores semantic lookahead.
    final List [] dbl = new ArrayList [ch.getChoices ().size ()];
    final List [] dbr = new ArrayList [ch.getChoices ().size ()];
    final int [] minLA = new int [ch.getChoices ().size () - 1];
    final MatchInfo [] overlapInfo = new MatchInfo [ch.getChoices ().size () - 1];
    final int [] other = new int [ch.getChoices ().size () - 1];
    MatchInfo m;
    List v;
    boolean overlapDetected;
    for (int la = 1; la <= Options.getChoiceAmbiguityCheck (); la++)
    {
      MatchInfo.laLimit = la;
      LookaheadWalk.considerSemanticLA = !Options.getForceLaCheck ();
      for (int i = first; i < ch.getChoices ().size () - 1; i++)
      {
        LookaheadWalk.sizeLimitedMatches = new ArrayList ();
        m = new MatchInfo ();
        m.firstFreeLoc = 0;
        v = new ArrayList ();
        v.add (m);
        LookaheadWalk.genFirstSet (v, (Expansion) ch.getChoices ().get (i));
        dbl[i] = LookaheadWalk.sizeLimitedMatches;
      }
      LookaheadWalk.considerSemanticLA = false;
      for (int i = first + 1; i < ch.getChoices ().size (); i++)
      {
        LookaheadWalk.sizeLimitedMatches = new ArrayList ();
        m = new MatchInfo ();
        m.firstFreeLoc = 0;
        v = new ArrayList ();
        v.add (m);
        LookaheadWalk.genFirstSet (v, (Expansion) ch.getChoices ().get (i));
        dbr[i] = LookaheadWalk.sizeLimitedMatches;
      }
      if (la == 1)
      {
        for (int i = first; i < ch.getChoices ().size () - 1; i++)
        {
          final Expansion exp = (Expansion) ch.getChoices ().get (i);
          if (Semanticize.emptyExpansionExists (exp))
          {
            JavaCCErrors.warning (exp, "This choice can expand to the empty token sequence "
                                       + "and will therefore always be taken in favor of the choices appearing later.");
            break;
          }
          else
            if (javaCodeCheck (dbl[i]))
            {
              JavaCCErrors.warning (exp, "JAVACODE non-terminal will force this choice to be taken "
                                         + "in favor of the choices appearing later.");
              break;
            }
        }
      }
      overlapDetected = false;
      for (int i = first; i < ch.getChoices ().size () - 1; i++)
      {
        for (int j = i + 1; j < ch.getChoices ().size (); j++)
        {
          if ((m = overlap (dbl[i], dbr[j])) != null)
          {
            minLA[i] = la + 1;
            overlapInfo[i] = m;
            other[i] = j;
            overlapDetected = true;
            break;
          }
        }
      }
      if (!overlapDetected)
      {
        break;
      }
    }
    for (int i = first; i < ch.getChoices ().size () - 1; i++)
    {
      if (explicitLA ((Expansion) ch.getChoices ().get (i)) && !Options.getForceLaCheck ())
      {
        continue;
      }
      if (minLA[i] > Options.getChoiceAmbiguityCheck ())
      {
        JavaCCErrors.warning ("Choice conflict involving two expansions at");
        System.err.print ("         line " + ((Expansion) ch.getChoices ().get (i)).getLine ());
        System.err.print (", column " + ((Expansion) ch.getChoices ().get (i)).getColumn ());
        System.err.print (" and line " + ((Expansion) ch.getChoices ().get (other[i])).getLine ());
        System.err.print (", column " + ((Expansion) ch.getChoices ().get (other[i])).getColumn ());
        System.err.println (" respectively.");
        System.err.println ("         A common prefix is: " + image (overlapInfo[i]));
        System.err.println ("         Consider using a lookahead of " + minLA[i] + " or more for earlier expansion.");
      }
      else
        if (minLA[i] > 1)
        {
          JavaCCErrors.warning ("Choice conflict involving two expansions at");
          System.err.print ("         line " + ((Expansion) ch.getChoices ().get (i)).getLine ());
          System.err.print (", column " + ((Expansion) ch.getChoices ().get (i)).getColumn ());
          System.err.print (" and line " + ((Expansion) ch.getChoices ().get (other[i])).getLine ());
          System.err.print (", column " + ((Expansion) ch.getChoices ().get (other[i])).getColumn ());
          System.err.println (" respectively.");
          System.err.println ("         A common prefix is: " + image (overlapInfo[i]));
          System.err.println ("         Consider using a lookahead of " + minLA[i] + " for earlier expansion.");
        }
    }
  }

  static boolean explicitLA (final Expansion exp)
  {
    if (!(exp instanceof Sequence))
    {
      return false;
    }
    final Sequence seq = (Sequence) exp;
    final Object obj = seq.units.get (0);
    if (!(obj instanceof Lookahead))
    {
      return false;
    }
    final Lookahead la = (Lookahead) obj;
    return la.isExplicit ();
  }

  static int firstChoice (final Choice ch)
  {
    if (Options.getForceLaCheck ())
    {
      return 0;
    }
    for (int i = 0; i < ch.getChoices ().size (); i++)
    {
      if (!explicitLA ((Expansion) ch.getChoices ().get (i)))
      {
        return i;
      }
    }
    return ch.getChoices ().size ();
  }

  private static String image (final Expansion exp)
  {
    if (exp instanceof OneOrMore)
    {
      return "(...)+";
    }
    else
      if (exp instanceof ZeroOrMore)
      {
        return "(...)*";
      }
      else
      /* if (exp instanceof ZeroOrOne) */{
        return "[...]";
      }
  }

  public static void ebnfCalc (final Expansion exp, final Expansion nested)
  {
    // exp is one of OneOrMore, ZeroOrMore, ZeroOrOne
    MatchInfo m, m1 = null;
    List v, first, follow;
    int la;
    for (la = 1; la <= Options.getOtherAmbiguityCheck (); la++)
    {
      MatchInfo.laLimit = la;
      LookaheadWalk.sizeLimitedMatches = new ArrayList ();
      m = new MatchInfo ();
      m.firstFreeLoc = 0;
      v = new ArrayList ();
      v.add (m);
      LookaheadWalk.considerSemanticLA = !Options.getForceLaCheck ();
      LookaheadWalk.genFirstSet (v, nested);
      first = LookaheadWalk.sizeLimitedMatches;
      LookaheadWalk.sizeLimitedMatches = new ArrayList ();
      LookaheadWalk.considerSemanticLA = false;
      LookaheadWalk.genFollowSet (v, exp, Expansion.nextGenerationIndex++);
      follow = LookaheadWalk.sizeLimitedMatches;
      if (la == 1)
      {
        if (javaCodeCheck (first))
        {
          JavaCCErrors.warning (nested, "JAVACODE non-terminal within " +
                                        image (exp) +
                                        " construct will force this construct to be entered in favor of " +
                                        "expansions occurring after construct.");
        }
      }
      if ((m = overlap (first, follow)) == null)
      {
        break;
      }
      m1 = m;
    }
    if (la > Options.getOtherAmbiguityCheck ())
    {
      JavaCCErrors.warning ("Choice conflict in " +
                            image (exp) +
                            " construct " +
                            "at line " +
                            exp.getLine () +
                            ", column " +
                            exp.getColumn () +
                            ".");
      System.err.println ("         Expansion nested within construct and expansion following construct");
      System.err.println ("         have common prefixes, one of which is: " + image (m1));
      System.err.println ("         Consider using a lookahead of " + la + " or more for nested expansion.");
    }
    else
      if (la > 1)
      {
        JavaCCErrors.warning ("Choice conflict in " +
                              image (exp) +
                              " construct " +
                              "at line " +
                              exp.getLine () +
                              ", column " +
                              exp.getColumn () +
                              ".");
        System.err.println ("         Expansion nested within construct and expansion following construct");
        System.err.println ("         have common prefixes, one of which is: " + image (m1));
        System.err.println ("         Consider using a lookahead of " + la + " for nested expansion.");
      }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy