    001    /* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
    002    package org.apache.commons.jxpath.ri.parser;
    003
    004    /**
    005     * This exception is thrown when parse errors are encountered.
    006     * You can explicitly create objects of this exception type by
    007     * calling the method generateParseException in the generated
    008     * parser.
    009     *
    010     * You can modify this class to customize your error reporting
    011     * mechanisms so long as you retain the public fields.
    012     */
    013    public class ParseException extends Exception {
    014
    015      /**
    016       * This constructor is used by the method "generateParseException"
    017       * in the generated parser.  Calling this constructor generates
    018       * a new object of this type with the fields "currentToken",
    019       * "expectedTokenSequences", and "tokenImage" set.  The boolean
    020       * flag "specialConstructor" is also set to true to indicate that
    021       * this constructor was used to create this object.
    022       * This constructor calls its super class with the empty string
    023       * to force the "toString" method of parent class "Throwable" to
    024       * print the error message in the form:
    025       *     ParseException: <result of getMessage>
    026       */
    027      public ParseException(Token currentTokenVal,
    028                            int[][] expectedTokenSequencesVal,
    029                            String[] tokenImageVal
    030                           )
    031      {
    032        super("");
    033        specialConstructor = true;
    034        currentToken = currentTokenVal;
    035        expectedTokenSequences = expectedTokenSequencesVal;
    036        tokenImage = tokenImageVal;
    037      }
    038
    039      /**
    040       * The following constructors are for use by you for whatever
    041       * purpose you can think of.  Constructing the exception in this
    042       * manner makes the exception behave in the normal way - i.e., as
    043       * documented in the class "Throwable".  The fields "errorToken",
    044       * "expectedTokenSequences", and "tokenImage" do not contain
    045       * relevant information.  The JavaCC generated code does not use
    046       * these constructors.
    047       */
    048
    049      public ParseException() {
    050        super();
    051        specialConstructor = false;
    052      }
    053
    054      public ParseException(String message) {
    055        super(message);
    056        specialConstructor = false;
    057      }
    058
    059      /**
    060       * This variable determines which constructor was used to create
    061       * this object and thereby affects the semantics of the
    062       * "getMessage" method (see below).
    063       */
    064      protected boolean specialConstructor;
    065
    066      /**
    067       * This is the last token that has been consumed successfully.  If
    068       * this object has been created due to a parse error, the token
    069       * followng this token will (therefore) be the first error token.
    070       */
    071      public Token currentToken;
    072
    073      /**
    074       * Each entry in this array is an array of integers.  Each array
    075       * of integers represents a sequence of tokens (by their ordinal
    076       * values) that is expected at this point of the parse.
    077       */
    078      public int[][] expectedTokenSequences;
    079
    080      /**
    081       * This is a reference to the "tokenImage" array of the generated
    082       * parser within which the parse error occurred.  This array is
    083       * defined in the generated ...Constants interface.
    084       */
    085      public String[] tokenImage;
    086
    087      /**
    088       * This method has the standard behavior when this object has been
    089       * created using the standard constructors.  Otherwise, it uses
    090       * "currentToken" and "expectedTokenSequences" to generate a parse
    091       * error message and returns it.  If this object has been created
    092       * due to a parse error, and you do not catch it (it gets thrown
    093       * from the parser), then this method is called during the printing
    094       * of the final stack trace, and hence the correct error message
    095       * gets displayed.
    096       */
    097      public String getMessage() {
    098        if (!specialConstructor) {
    099          return super.getMessage();
    100        }
    101        String expected = "";
    102        int maxSize = 0;
    103        for (int i = 0; i < expectedTokenSequences.length; i++) {
    104          if (maxSize < expectedTokenSequences[i].length) {
    105            maxSize = expectedTokenSequences[i].length;
    106          }
    107          for (int j = 0; j < expectedTokenSequences[i].length; j++) {
    108            expected += tokenImage[expectedTokenSequences[i][j]] + " ";
    109          }
    110          if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
    111            expected += "...";
    112          }
    113          expected += eol + "    ";
    114        }
    115        String retval = "Encountered \"";
    116        Token tok = currentToken.next;
    117        for (int i = 0; i < maxSize; i++) {
    118          if (i != 0) retval += " ";
    119          if (tok.kind == 0) {
    120            retval += tokenImage[0];
    121            break;
    122          }
    123          retval += add_escapes(tok.image);
    124          tok = tok.next;
    125        }
    126        retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
    127        retval += "." + eol;
    128        if (expectedTokenSequences.length == 1) {
    129          retval += "Was expecting:" + eol + "    ";
    130        } else {
    131          retval += "Was expecting one of:" + eol + "    ";
    132        }
    133        retval += expected;
    134        return retval;
    135      }
    136
    137      /**
    138       * The end of line string for this machine.
    139       */
    140      protected String eol = System.getProperty("line.separator", "\n");
    141
    142      /**
    143       * Used to convert raw characters to their escaped version
    144       * when these raw version cannot be used as part of an ASCII
    145       * string literal.
    146       */
    147      protected String add_escapes(String str) {
    148          StringBuffer retval = new StringBuffer();
    149          char ch;
    150          for (int i = 0; i < str.length(); i++) {
    151            switch (str.charAt(i))
    152            {
    153               case 0 :
    154                  continue;
    155               case '\b':
    156                  retval.append("\\b");
    157                  continue;
    158               case '\t':
    159                  retval.append("\\t");
    160                  continue;
    161               case '\n':
    162                  retval.append("\\n");
    163                  continue;
    164               case '\f':
    165                  retval.append("\\f");
    166                  continue;
    167               case '\r':
    168                  retval.append("\\r");
    169                  continue;
    170               case '\"':
    171                  retval.append("\\\"");
    172                  continue;
    173               case '\'':
    174                  retval.append("\\\'");
    175                  continue;
    176               case '\\':
    177                  retval.append("\\\\");
    178                  continue;
    179               default:
    180                  if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
    181                     String s = "0000" + Integer.toString(ch, 16);
    182                     retval.append("\\u" + s.substring(s.length() - 4, s.length()));
    183                  } else {
    184                     retval.append(ch);
    185                  }
    186                  continue;
    187            }
    188          }
    189          return retval.toString();
    190       }
    191
    192    }