Skip to content
Snippets Groups Projects
Select Git revision
  • 0bad1f8bf75f4126fce6ac86ade63cb0a3b41bcf
  • master default protected
  • ia2
  • adql2.1-ia2
  • private_rows
5 results

ParseException.java

Blame
  • ParseException.java 10.10 KiB
    /* Generated By:JavaCC: Do not edit this line. ParseException.java Version 6.0 */
    /* JavaCCOptions:KEEP_LINE_COL=null
     *
     * Modified by Grégory Mantelet (CDS), on March 2017
     * Modifications:
     *     - addition of a getPosition() function in order to get the exact location
     *       of the error in the original ADQL query
     *     - generate the error message at creation instead of doing that at each
     *       call of getMessage()
     *     - use of StringBuffer to build the error message
     *     - small other alterations of the generated error message
     *
     * Modified by Grégory Mantelet (ARI), on Sept. 2017
     * Modifications:
     *     - addition of a HINT in the error message when an ADQL or SQL reserved
     *       word is at the origin of the error (see initialise(...))
     *
     * Modified by Grégory Mantelet (CDS), on March 2019
     * Modifications:
     *     - addition of a constructor with a TokenMgrError which adds a piece of
     *       advice to fix the token issue (see buildExpandedMessage(...))
     *
     * Modified by Grégory Mantelet (ARI), on April 2019
     * Modifications:
     *     - change the way ADQL and SQL reserved keywords are identified for the
     *       generation of the appropriate HINT in the error message
     *
     * Modified by Grégory Mantelet (CDS), on Aug. 2019
     * Modifications:
     *     - change the package name
     *     - customize error message in function of the token: append an hint
     *       message or a possible cause in case of TokenMgrError
     *
     * /!\ DO NOT RE-GENERATE THIS FILE /!\
     * In case of re-generation, replace it by ParseException.java.backup (but maybe
     * after a diff in case of significant modifications have been done by a new
     * version of JavaCC).
     */
    package adql.parser.grammar;
    
    import adql.parser.ADQLParser.ADQLVersion;
    import adql.query.TextPosition;
    
    /**
     * This exception is thrown when parse errors are encountered.
     * You can explicitly create objects of this exception type by
     * calling the method generateParseException in the generated
     * parser.
     *
     * You can modify this class to customize your error reporting
     * mechanisms so long as you retain the public fields.
     *
     * @version 2.0 (08/2019)
     * @author JavaCC
     * @author Grégory Mantelet (CDS)
     */
    public class ParseException extends Exception {
    
    	/**
    	 * The version identifier for this Serializable class.
    	 * Increment only if the <i>serialized</i> form of the
    	 * class changes.
    	 */
    	private static final long serialVersionUID = 1L;
    
    	/**
    	 * This constructor is used by the method "generateParseException"
    	 * in the generated parser.  Calling this constructor generates
    	 * a new object of this type with the fields "currentToken",
    	 * "expectedTokenSequences", and "tokenImage" set.
    	 */
    	public ParseException(Token currentTokenVal, int[][] expectedTokenSequencesVal, String[] tokenImageVal) {
    		super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
    		currentToken = currentTokenVal;
    		expectedTokenSequences = expectedTokenSequencesVal;
    		tokenImage = tokenImageVal;
    
    		position = new TextPosition(currentToken.next);
    	}
    
    	/**
    	 * The following constructors are for use by you for whatever
    	 * purpose you can think of.  Constructing the exception in this
    	 * manner makes the exception behave in the normal way - i.e., as
    	 * documented in the class "Throwable".  The fields "errorToken",
    	 * "expectedTokenSequences", and "tokenImage" do not contain
    	 * relevant information.  The JavaCC generated code does not use
    	 * these constructors.
    	 */
    
    	public ParseException() {
    		super();
    	}
    
    	/** Constructor with message. */
    	public ParseException(String message) {
    		super(message);
    	}
    
    	public ParseException(String message, TextPosition errorPosition) {
    		this(message);
    		position = errorPosition;
    	}
    
    	public ParseException(TokenMgrError err) {
    		this(buildExpandedMessage(err), new TextPosition(err.getErrorLine(), err.getErrorColumn()));
    	}
    
    	private final static String buildExpandedMessage(final TokenMgrError err) {
    		if (err.getMessage().indexOf("<EOF>") > 0)
    			return err.getMessage() + "!" + eol + "Possible cause: a string between single or double quotes which is never closed (solution: well...just close it!).";
    		else
    			return err.getMessage() + "!" + eol + "Possible cause: a non-ASCI/UTF-8 character (solution: remove/replace it).";
    	}
    
    	/**
    	 * This is the last token that has been consumed successfully.  If
    	 * this object has been created due to a parse error, the token
    	 * followng this token will (therefore) be the first error token.
    	 */
    	public Token currentToken;
    
    	/**
    	 * Each entry in this array is an array of integers.  Each array
    	 * of integers represents a sequence of tokens (by their ordinal
    	 * values) that is expected at this point of the parse.
    	 */
    	public int[][] expectedTokenSequences;
    
    	/**
    	 * This is a reference to the "tokenImage" array of the generated
    	 * parser within which the parse error occurred.  This array is
    	 * defined in the generated ...Constants interface.
    	 */
    	public String[] tokenImage;
    
    	/** Line in the ADQL query where the exception occurs. */
    	protected TextPosition position = null;
    
    	/**
    	 * Gets the position in the ADQL query of the token which generates this exception.
    	 *
    	 * @return Position or <code>null</code> if unknown.
    	 */
    	public final TextPosition getPosition() {
    		return position;
    	}
    
    	/**
    	 * It uses "currentToken" and "expectedTokenSequences" to generate a parse
    	 * error message and returns it.  If this object has been created
    	 * due to a parse error, and you do not catch it (it gets thrown
    	 * from the parser) the correct error message
    	 * gets displayed.
    	 */
    	private static String initialise(Token currentToken, int[][] expectedTokenSequences, String[] tokenImage) {
    		int maxSize = 0;
    
    		// Build the list of expected tokens:
    		StringBuffer expected = new StringBuffer();
    		for(int i = 0; i < expectedTokenSequences.length; i++) {
    			if (maxSize < expectedTokenSequences[i].length) {
    				maxSize = expectedTokenSequences[i].length;
    			}
    			for(int j = 0; j < expectedTokenSequences[i].length; j++) {
    				expected.append(tokenImage[expectedTokenSequences[i][j]]);
    			}
    			expected.append(" ");
    		}
    
    		// Encountered token (s list):
    		StringBuffer msg = new StringBuffer();
    		msg.append(" Encountered \"");
    		Token tok = currentToken.next;
    		StringBuffer tokenName = new StringBuffer();
    		for(int i = 0; i < maxSize; i++) {
    			if (i != 0)
    				tokenName.append(' ');
    			if (tok.kind == 0) {
    				tokenName.append(tokenImage[0]);
    				break;
    			}
    			tokenName.append(add_escapes(tok.image));
    			tok = tok.next;
    		}
    		msg.append(tokenName.toString()).append("\".");
    
    		// Append the expected tokens list:
    		if (expectedTokenSequences.length == 1) {
    			msg.append(" Was expecting: ");
    		} else {
    			msg.append(" Was expecting one of: ");
    		}
    		msg.append(expected);
    
    		// Append a hint about reserved words if it is one:
    		if (maxSize == 1) {
    			tok = currentToken.next;
    			if (tok.adqlReserved)
    				msg.append(eol).append("(HINT: \"").append(tok.image).append("\" is a reserved ADQL word in " + currentToken.next.adqlVersion + ". To use it as a column/table/schema name/alias, write it between double quotes.)");
    			else if (tok.sqlReserved)
    				msg.append(eol).append("(HINT: \"").append(tok.image).append("\" is not supported in ADQL " + currentToken.next.adqlVersion + ", but is however a reserved word. To use it as a column/table/schema name/alias, write it between double quotes.)");
    			else if (tok.adqlVersion == ADQLVersion.V2_0 && tok.image.matches("[~^|&]"))
    				msg.append(eol).append("(HINT: \"").append(tok.image).append("\" bitwise operations are not supported in ADQL-2.0. You should migrate your ADQL parser to support at least ADQL-2.1.)");
    		}
    
    		return msg.toString();
    		/*String eol = System.getProperty("line.separator", "\n");
    		StringBuffer expected = new StringBuffer();
    		int maxSize = 0;
    		for(int i = 0; i < expectedTokenSequences.length; i++){
    			if (maxSize < expectedTokenSequences[i].length){
    				maxSize = expectedTokenSequences[i].length;
    			}
    			for(int j = 0; j < expectedTokenSequences[i].length; j++){
    				expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
    			}
    			if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0){
    				expected.append("...");
    			}
    			expected.append(eol).append("    ");
    		}
    		String retval = "Encountered \"";
    		Token tok = currentToken.next;
    		for(int i = 0; i < maxSize; i++){
    			if (i != 0) retval += " ";
    			if (tok.kind == 0){
    				retval += tokenImage[0];
    				break;
    			}
    			retval += " " + tokenImage[tok.kind];
    			retval += " \"";
    			retval += add_escapes(tok.image);
    			retval += " \"";
    			tok = tok.next;
    		}
    		retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
    		retval += "." + eol;
    		if (expectedTokenSequences.length == 1){
    			retval += "Was expecting:" + eol + "    ";
    		}else{
    			retval += "Was expecting one of:" + eol + "    ";
    		}
    		retval += expected.toString();
    		return retval;*/
    	}
    
    	/**
    	 * The end of line string for this machine.
    	 */
    	protected static String eol = System.getProperty("line.separator", "\n");
    
    	/**
    	 * Used to convert raw characters to their escaped version
    	 * when these raw version cannot be used as part of an ASCII
    	 * string literal.
    	 */
    	static String add_escapes(String str) {
    		StringBuffer retval = new StringBuffer();
    		char ch;
    		for(int i = 0; i < str.length(); i++) {
    			switch(str.charAt(i)) {
    				case 0:
    					continue;
    				case '\b':
    					retval.append("\\b");
    					continue;
    				case '\t':
    					retval.append("\\t");
    					continue;
    				case '\n':
    					retval.append("\\n");
    					continue;
    				case '\f':
    					retval.append("\\f");
    					continue;
    				case '\r':
    					retval.append("\\r");
    					continue;
    				case '\"':
    					retval.append("\\\"");
    					continue;
    				case '\'':
    					retval.append("\\\'");
    					continue;
    				case '\\':
    					retval.append("\\\\");
    					continue;
    				default:
    					if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
    						String s = "0000" + Integer.toString(ch, 16);
    						retval.append("\\u" + s.substring(s.length() - 4, s.length()));
    					} else {
    						retval.append(ch);
    					}
    					continue;
    			}
    		}
    		return retval.toString();
    	}
    
    }
    /* JavaCC - OriginalChecksum=ffea128e805df869244c5e22c2a37cbc (do not edit this line) */