/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.tools.expression.internal.antlr; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.Token; /** * Listener for errors in the expression parser. Stores the error line and its message. * * @author Gisa Schaefer * */ class ExpressionErrorListener extends BaseErrorListener { private String errorMessage; private int line; @Override public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { super.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); this.line = line; if (recognizer.getInputStream() instanceof CommonTokenStream) { StringBuilder errorBuilder = new StringBuilder(msg); CommonTokenStream tokenStream = (CommonTokenStream) recognizer.getInputStream(); errorBuilder.append("\n"); String expression = tokenStream.getTokenSource().getInputStream().toString(); String[] split = expression.split("(\r\n|\n)"); String error = null; if (split.length > 0) { if (line - 1 >= 0 && line - 1 < split.length) { error = split[line - 1].replace("\t", " "); } else { error = split[split.length - 1].replace("\t", " "); } errorBuilder.append(error); errorBuilder.append("\n"); } else { errorBuilder.append(expression); errorBuilder.append("\n"); } for (int i = 0; i < charPositionInLine; i++) { errorBuilder.append(" "); } if (offendingSymbol instanceof Token) { Token token = (Token) offendingSymbol; int startIndex = token.getStartIndex(); int stopIndex = token.getStopIndex(); if (startIndex >= 0 && stopIndex >= 0 && startIndex <= stopIndex) { for (int i = token.getStartIndex(); i <= token.getStopIndex(); i++) { errorBuilder.append("^"); } } else { errorBuilder.append("^"); } } else { errorBuilder.append("^"); } errorMessage = errorBuilder.toString(); } else { errorMessage = msg; } } /** * @return the message describing the syntax error */ String getErrorMessage() { return errorMessage; } /** * @return the line containing the error, starting with 1 */ int getErrorLine() { return line; } /** * @return {@code true} if a syntax error occurred */ boolean containsError() { return errorMessage != null; } }