View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3.parser;
18  
19  /**
20   * Token Manager Error.
21   */
22  public class TokenMgrException extends RuntimeException implements JavaccError {
23      /**
24       * The version identifier for this Serializable class.
25       * Increment only if the <i>serialized</i> form of the
26       * class changes.
27       */
28      private static final long serialVersionUID = 1L;
29  
30      /*
31       * Ordinals for various reasons why an Error of this type can be thrown.
32       */
33      /**
34       * Lexical error occurred.
35       */
36      public static final int LEXICAL_ERROR = 0;
37      /**
38       * An attempt was made to create a second instance of a static token manager.
39       */
40      public static final int STATIC_LEXER_ERROR = 1;
41      /**
42       * Tried to change to an invalid lexical state.
43       */
44      public static final int INVALID_LEXICAL_STATE = 2;
45      /**
46       * Detected (and bailed out of) an infinite loop in the token manager.
47       */
48      public static final int LOOP_DETECTED = 3;
49      /**
50       * Indicates the reason why the exception is thrown. It will have
51       * one of the above 4 values.
52       */
53      private final int errorCode;
54      /**
55       * The lexer state.
56       */
57      @SuppressWarnings("unused") // not read currently
58      private int state;
59      /**
60       * The current character.
61       */
62      private char current;
63      /**
64       * Last correct input before error occurs.
65       */
66      private String after;
67      /**
68       * Whether eof was reached whilst expecting more input.
69       */
70      private boolean eof;
71      /**
72       * Error line.
73       */
74      private int line;
75      /**
76       * Error column.
77       */
78      private int column;
79  
80      /**
81       * Returns a detailed message for the Error when it is thrown by the
82       * token manager to indicate a lexical error.
83       * @return the message
84       */
85      @Override
86      public String getMessage() {
87          return ("Lexical error at line "
88                  + line + ", column "
89                  + column + ".  Encountered: "
90                  + (eof ? "<EOF> "
91                     : (StringParser.escapeString(String.valueOf(current), '"')) + " (" + (int) current + "), ")
92                  + "after : " + StringParser.escapeString(after, '"'));
93      }
94  
95  
96      /** Constructor with message and reason. */
97      public TokenMgrException(final String message, final int reason) {
98          super(message);
99          errorCode = reason;
100     }
101 
102     /** Full Constructor. */
103     public TokenMgrException(final boolean EOFSeen, final int lexState, final int errorLine, final int errorColumn, final String errorAfter, final int curChar, final int reason) {
104         eof = EOFSeen;
105         state = lexState;
106         line = errorLine;
107         column = errorColumn;
108         after = errorAfter;
109         current = (char) curChar;
110         errorCode = reason;
111     }
112 
113     /**
114      * Gets the reason why the exception is thrown.
115      * @return one of the 4 lexical error codes
116      */
117     public int getErrorCode() {
118         return errorCode;
119     }
120 
121     @Override
122     public int getLine() {
123         return line;
124     }
125 
126     @Override
127     public int getColumn() {
128         return column;
129     }
130 
131     @Override
132     public String getAfter() {
133         return after;
134     }
135 
136      /***
137       * Replaces unprintable characters by their espaced (or unicode escaped)
138       * equivalents in the given string
139       */
140      protected static String addEscapes(final String str) {
141         final StringBuilder retval = new StringBuilder();
142         char ch;
143         for (int i = 0; i < str.length(); i++) {
144           switch (str.charAt(i))
145           {
146              case 0 :
147                 continue;
148              case '\b':
149                 retval.append("//b");
150                 continue;
151              case '\t':
152                 retval.append("//t");
153                 continue;
154              case '\n':
155                 retval.append("//n");
156                 continue;
157              case '\f':
158                 retval.append("//f");
159                 continue;
160              case '\r':
161                 retval.append("//r");
162                 continue;
163              case '\"':
164                 retval.append("//\"");
165                 continue;
166              case '\'':
167                 retval.append("//\'");
168                 continue;
169              case '/':
170                 retval.append("////");
171                 continue;
172              default:
173                 if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
174                    final String s = "0000" + Integer.toString(ch, 16);
175                    retval.append("//u").append(s.substring(s.length() - 4));
176                 } else {
177                    retval.append(ch);
178                 }
179                 continue;
180           }
181         }
182         return retval.toString();
183      }
184 }