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        * Replaces unprintable characters by their espaced (or unicode escaped)
51        * equivalents in the given string
52        */
53       protected static String addEscapes(final String str) {
54          final StringBuilder retval = new StringBuilder();
55          char ch;
56          for (int i = 0; i < str.length(); i++) {
57            switch (str.charAt(i))
58            {
59               case 0 :
60                  continue;
61               case '\b':
62                  retval.append("//b");
63                  continue;
64               case '\t':
65                  retval.append("//t");
66                  continue;
67               case '\n':
68                  retval.append("//n");
69                  continue;
70               case '\f':
71                  retval.append("//f");
72                  continue;
73               case '\r':
74                  retval.append("//r");
75                  continue;
76               case '\"':
77                  retval.append("//\"");
78                  continue;
79               case '\'':
80                  retval.append("//\'");
81                  continue;
82               case '/':
83                  retval.append("////");
84                  continue;
85               default:
86                  if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
87                     final String s = "0000" + Integer.toString(ch, 16);
88                     retval.append("//u").append(s.substring(s.length() - 4));
89                  } else {
90                     retval.append(ch);
91                  }
92                  continue;
93            }
94          }
95          return retval.toString();
96       }
97      /**
98       * Indicates the reason why the exception is thrown. It will have
99       * one of the above 4 values.
100      */
101     private final int errorCode;
102     /**
103      * The lexer state.
104      */
105     @SuppressWarnings("unused") // not read currently
106     private int state;
107     /**
108      * The current character.
109      */
110     private char current;
111     /**
112      * Last correct input before error occurs.
113      */
114     private String after;
115     /**
116      * Whether eof was reached whilst expecting more input.
117      */
118     private boolean eof;
119     /**
120      * Error line.
121      */
122     private int line;
123 
124     /**
125      * Error column.
126      */
127     private int column;
128 
129     /** Full Constructor. */
130     public TokenMgrException(final boolean EOFSeen, final int lexState, final int errorLine, final int errorColumn, final String errorAfter, final int curChar, final int reason) {
131         eof = EOFSeen;
132         state = lexState;
133         line = errorLine;
134         column = errorColumn;
135         after = errorAfter;
136         current = (char) curChar;
137         errorCode = reason;
138     }
139 
140     /** Constructor with message and reason. */
141     public TokenMgrException(final String message, final int reason) {
142         super(message);
143         errorCode = reason;
144     }
145 
146     @Override
147     public String getAfter() {
148         return after;
149     }
150 
151     @Override
152     public int getColumn() {
153         return column;
154     }
155 
156     /**
157      * Gets the reason why the exception is thrown.
158      * @return one of the 4 lexical error codes
159      */
160     public int getErrorCode() {
161         return errorCode;
162     }
163 
164     @Override
165     public int getLine() {
166         return line;
167     }
168 
169      /**
170      * Returns a detailed message for the Error when it is thrown by the
171      * token manager to indicate a lexical error.
172      * @return the message
173      */
174     @Override
175     public String getMessage() {
176         return "Lexical error at line "
177                 + line + ", column "
178                 + column + ".  Encountered: "
179                 + (eof ? "<EOF> "
180                    : StringParser.escapeString(String.valueOf(current), '"') + " (" + (int) current + "), ")
181                 + "after : " + StringParser.escapeString(after, '"');
182     }
183 }