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 <em>serialized</em> 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 /**
130 * Constructs a new instance.
131 */
132 public TokenMgrException(final boolean EOFSeen, final int lexState, final int errorLine, final int errorColumn,
133 final String errorAfter, final int curChar, final int reason) {
134 eof = EOFSeen;
135 state = lexState;
136 line = errorLine;
137 column = errorColumn;
138 after = errorAfter;
139 current = (char) curChar;
140 errorCode = reason;
141 }
142
143 /** Constructor with message and reason. */
144 public TokenMgrException(final String message, final int reason) {
145 super(message);
146 errorCode = reason;
147 }
148
149 @Override
150 public String getAfter() {
151 return after;
152 }
153
154 @Override
155 public int getColumn() {
156 return column;
157 }
158
159 /**
160 * Gets the reason why the exception is thrown.
161 * @return one of the 4 lexical error codes
162 */
163 public int getErrorCode() {
164 return errorCode;
165 }
166
167 @Override
168 public int getLine() {
169 return line;
170 }
171
172 /**
173 * Returns a detailed message for the Error when it is thrown by the
174 * token manager to indicate a lexical error.
175 * @return the message
176 */
177 @Override
178 public String getMessage() {
179 return "Lexical error at line "
180 + line + ", column "
181 + column + ". Encountered: "
182 + (eof ? "<EOF> "
183 : StringParser.escapeString(String.valueOf(current), '"') + " (" + (int) current + "), ")
184 + "after : " + StringParser.escapeString(after, '"');
185 }
186 }