Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2969311D99 for ; Tue, 15 Jul 2014 17:06:39 +0000 (UTC) Received: (qmail 47542 invoked by uid 500); 15 Jul 2014 17:06:38 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 47512 invoked by uid 500); 15 Jul 2014 17:06:38 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 47501 invoked by uid 99); 15 Jul 2014 17:06:38 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Jul 2014 17:06:38 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 92CD494DD86; Tue, 15 Jul 2014 17:06:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: tylerhobbs@apache.org To: commits@cassandra.apache.org Message-Id: <4209bedc0768444ebd081f6a993c536c@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: Include snippet of query in SyntaxError messages Date: Tue, 15 Jul 2014 17:06:38 +0000 (UTC) Repository: cassandra Updated Branches: refs/heads/cassandra-2.1 52c6dfb8f -> 8a2d8a138 Include snippet of query in SyntaxError messages Patch by Benjamin Lerer; reviewed by Tyler Hobbs for CASSANDRA-7111 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/8a2d8a13 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/8a2d8a13 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/8a2d8a13 Branch: refs/heads/cassandra-2.1 Commit: 8a2d8a138d5ac1fc38b24bc7fd7513f6dbe86b24 Parents: 52c6dfb Author: blerer Authored: Tue Jul 15 12:05:47 2014 -0500 Committer: Tyler Hobbs Committed: Tue Jul 15 12:05:47 2014 -0500 ---------------------------------------------------------------------- CHANGES.txt | 1 + src/java/org/apache/cassandra/cql3/Cql.g | 41 ++-- .../apache/cassandra/cql3/ErrorCollector.java | 242 +++++++++++++++++++ .../apache/cassandra/cql3/ErrorListener.java | 44 ++++ .../apache/cassandra/cql3/QueryProcessor.java | 11 +- .../apache/cassandra/cql3/CqlParserTest.java | 90 +++++++ .../cassandra/cql3/ErrorCollectorTest.java | 218 +++++++++++++++++ 7 files changed, 621 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 1781ef3..89f9b7c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -6,6 +6,7 @@ * Adjust MT depth based on # of partition validating (CASSANDRA-5263) * Optimise NativeCell comparisons (CASSANDRA-6755) * Configurable client timeout for cqlsh (CASSANDRA-7516) + * Include snippet of CQL query near syntax error in messages (CASSANDRA-7111) 2.1.0-final http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/src/java/org/apache/cassandra/cql3/Cql.g ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g index 948cd5e..9dcc268 100644 --- a/src/java/org/apache/cassandra/cql3/Cql.g +++ b/src/java/org/apache/cassandra/cql3/Cql.g @@ -51,7 +51,7 @@ options { } @members { - private final List recognitionErrors = new ArrayList(); + private final List listeners = new ArrayList(); private final List bindVariables = new ArrayList(); public static final Set reservedTypeNames = new HashSet() @@ -94,27 +94,26 @@ options { return marker; } - public void displayRecognitionError(String[] tokenNames, RecognitionException e) + public void addErrorListener(ErrorListener listener) { - String hdr = getErrorHeader(e); - String msg = getErrorMessage(e, tokenNames); - recognitionErrors.add(hdr + " " + msg); + this.listeners.add(listener); } - public void addRecognitionError(String msg) + public void removeErrorListener(ErrorListener listener) { - recognitionErrors.add(msg); + this.listeners.remove(listener); } - public List getRecognitionErrors() + public void displayRecognitionError(String[] tokenNames, RecognitionException e) { - return recognitionErrors; + for (int i = 0, m = listeners.size(); i < m; i++) + listeners.get(i).syntaxError(this, tokenNames, e); } - public void throwLastRecognitionError() throws SyntaxException + private void addRecognitionError(String msg) { - if (recognitionErrors.size() > 0) - throw new SyntaxException(recognitionErrors.get((recognitionErrors.size()-1))); + for (int i = 0, m = listeners.size(); i < m; i++) + listeners.get(i).syntaxError(this, msg); } public Map convertPropertyMap(Maps.Literal map) @@ -189,24 +188,22 @@ options { return tokens.remove(0); } - private List recognitionErrors = new ArrayList(); + private final List listeners = new ArrayList(); - public void displayRecognitionError(String[] tokenNames, RecognitionException e) + public void addErrorListener(ErrorListener listener) { - String hdr = getErrorHeader(e); - String msg = getErrorMessage(e, tokenNames); - recognitionErrors.add(hdr + " " + msg); + this.listeners.add(listener); } - public List getRecognitionErrors() + public void removeErrorListener(ErrorListener listener) { - return recognitionErrors; + this.listeners.remove(listener); } - public void throwLastRecognitionError() throws SyntaxException + public void displayRecognitionError(String[] tokenNames, RecognitionException e) { - if (recognitionErrors.size() > 0) - throw new SyntaxException(recognitionErrors.get((recognitionErrors.size()-1))); + for (int i = 0, m = listeners.size(); i < m; i++) + listeners.get(i).syntaxError(this, tokenNames, e); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/src/java/org/apache/cassandra/cql3/ErrorCollector.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/ErrorCollector.java b/src/java/org/apache/cassandra/cql3/ErrorCollector.java new file mode 100644 index 0000000..41536f5 --- /dev/null +++ b/src/java/org/apache/cassandra/cql3/ErrorCollector.java @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.cql3; + +import java.util.LinkedList; + +import org.antlr.runtime.BaseRecognizer; +import org.antlr.runtime.Parser; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.Token; +import org.antlr.runtime.TokenStream; +import org.apache.cassandra.exceptions.SyntaxException; + +/** + * ErrorListener that collect and enhance the errors send by the CQL lexer and parser. + */ +public final class ErrorCollector implements ErrorListener +{ + /** + * The offset of the first token of the snippet. + */ + private static final int FIRST_TOKEN_OFFSET = 10; + + /** + * The offset of the last token of the snippet. + */ + private static final int LAST_TOKEN_OFFSET = 2; + + /** + * The CQL query. + */ + private final String query; + + /** + * The error messages. + */ + private final LinkedList errorMsgs = new LinkedList<>(); + + /** + * Creates a new ErrorCollector instance to collect the syntax errors associated to the specified CQL + * query. + * + * @param query the CQL query that will be parsed + */ + public ErrorCollector(String query) + { + this.query = query; + } + + /** + * {@inheritDoc} + */ + @Override + public void syntaxError(BaseRecognizer recognizer, String[] tokenNames, RecognitionException e) + { + String hdr = recognizer.getErrorHeader(e); + String msg = recognizer.getErrorMessage(e, tokenNames); + + StringBuilder builder = new StringBuilder().append(hdr) + .append(' ') + .append(msg); + + if (recognizer instanceof Parser) + appendQuerySnippet((Parser) recognizer, builder); + + errorMsgs.add(builder.toString()); + } + + /** + * {@inheritDoc} + */ + @Override + public void syntaxError(BaseRecognizer recognizer, String errorMsg) + { + errorMsgs.add(errorMsg); + } + + /** + * Throws the last syntax error found by the lexer or the parser if it exists. + * + * @throws SyntaxException the syntax error. + */ + public void throwLastSyntaxError() throws SyntaxException + { + if (!errorMsgs.isEmpty()) + throw new SyntaxException(errorMsgs.getLast()); + } + + /** + * Appends a query snippet to the message to help the user to understand the problem. + * + * @param parser the parser used to parse the query + * @param builder the StringBuilder used to build the error message + */ + private void appendQuerySnippet(Parser parser, StringBuilder builder) + { + TokenStream tokenStream = parser.getTokenStream(); + int index = tokenStream.index(); + int size = tokenStream.size(); + + Token from = tokenStream.get(getSnippetFirstTokenIndex(index)); + Token to = tokenStream.get(getSnippetLastTokenIndex(index, size)); + Token offending = tokenStream.get(index); + + appendSnippet(builder, from, to, offending); + } + + /** + * Appends a query snippet to the message to help the user to understand the problem. + * + * @param from the first token to include within the snippet + * @param to the last token to include within the snippet + * @param offending the token which is responsible for the error + */ + final void appendSnippet(StringBuilder builder, + Token from, + Token to, + Token offending) + { + String[] lines = query.split("\n"); + + boolean includeQueryStart = (from.getLine() == 1) && (from.getCharPositionInLine() == 0); + boolean includeQueryEnd = (to.getLine() == lines.length) + && (getLastCharPositionInLine(to) == lines[lines.length - 1].length()); + + builder.append(" ("); + + if (!includeQueryStart) + builder.append("..."); + + lines[lineIndex(to)] = lines[lineIndex(to)].substring(0, getLastCharPositionInLine(to)); + lines[lineIndex(offending)] = highlightToken(lines[lineIndex(offending)], offending); + lines[lineIndex(from)] = lines[lineIndex(from)].substring(from.getCharPositionInLine()); + + for (int i = lineIndex(from), m = lineIndex(to); i <= m; i++) + builder.append(lines[i]); + + if (!includeQueryEnd) + builder.append("..."); + + builder.append(")"); + } + + /** + * Puts the specified token within square brackets. + * + * @param line the line containing the token + * @param token the token to put within square brackets + */ + private static String highlightToken(String line, Token token) + { + String newLine = insertChar(line, getLastCharPositionInLine(token), ']'); + return insertChar(newLine, token.getCharPositionInLine(), '['); + } + + /** + * Returns the index of the last character relative to the beginning of the line 0..n-1 + * + * @param token the token + * @return the index of the last character relative to the beginning of the line 0..n-1 + */ + private static int getLastCharPositionInLine(Token token) + { + return token.getCharPositionInLine() + getLength(token); + } + + /** + * Return the token length. + * + * @param token the token + * @return the token length + */ + private static int getLength(Token token) + { + return token.getText().length(); + } + + /** + * Inserts a character at a given position within a String. + * + * @param s the String in which the character must be inserted + * @param index the position where the character must be inserted + * @param c the character to insert + * @return the modified String + */ + private static String insertChar(String s, int index, char c) + { + return new StringBuilder().append(s.substring(0, index)) + .append(c) + .append(s.substring(index)) + .toString(); + } + + /** + * Returns the index of the line number on which this token was matched; index=0..n-1 + * + * @param token the token + * @return the index of the line number on which this token was matched; index=0..n-1 + */ + private static int lineIndex(Token token) + { + return token.getLine() - 1; + } + + /** + * Returns the index of the last token which is part of the snippet. + * + * @param index the index of the token causing the error + * @param size the total number of tokens + * @return the index of the last token which is part of the snippet. + */ + private static int getSnippetLastTokenIndex(int index, int size) + { + return Math.min(size - 1, index + LAST_TOKEN_OFFSET); + } + + /** + * Returns the index of the first token which is part of the snippet. + * + * @param index the index of the token causing the error + * @return the index of the first token which is part of the snippet. + */ + private static int getSnippetFirstTokenIndex(int index) + { + return Math.max(0, index - FIRST_TOKEN_OFFSET); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/src/java/org/apache/cassandra/cql3/ErrorListener.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/ErrorListener.java b/src/java/org/apache/cassandra/cql3/ErrorListener.java new file mode 100644 index 0000000..0bf891a --- /dev/null +++ b/src/java/org/apache/cassandra/cql3/ErrorListener.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.cql3; + +import org.antlr.runtime.BaseRecognizer; +import org.antlr.runtime.RecognitionException; + +/** + * Listener used to collect the syntax errors emitted by the Lexer and Parser. + */ +public interface ErrorListener +{ + /** + * Invoked when a syntax error occurs. + * + * @param recognizer the parser or lexer that emitted the error + * @param tokenNames the token names + * @param e the exception + */ + void syntaxError(BaseRecognizer recognizer, String[] tokenNames, RecognitionException e); + + /** + * Invoked when a syntax error with a specified message occurs. + * + * @param recognizer the parser or lexer that emitted the error + * @param errorMsg the error message + */ + void syntaxError(BaseRecognizer recognizer, String errorMsg); +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/src/java/org/apache/cassandra/cql3/QueryProcessor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java index 86362f7..4994342 100644 --- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java +++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java @@ -442,18 +442,21 @@ public class QueryProcessor implements QueryHandler try { // Lexer and parser + ErrorCollector errorCollector = new ErrorCollector(queryStr); CharStream stream = new ANTLRStringStream(queryStr); CqlLexer lexer = new CqlLexer(stream); + lexer.addErrorListener(errorCollector); + TokenStream tokenStream = new CommonTokenStream(lexer); CqlParser parser = new CqlParser(tokenStream); + parser.addErrorListener(errorCollector); // Parse the query string to a statement instance ParsedStatement statement = parser.query(); - // The lexer and parser queue up any errors they may have encountered - // along the way, if necessary, we turn them into exceptions here. - lexer.throwLastRecognitionError(); - parser.throwLastRecognitionError(); + // The errorCollector has queue up any errors that the lexer and parser may have encountered + // along the way, if necessary, we turn the last error into exceptions here. + errorCollector.throwLastSyntaxError(); return statement; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/test/unit/org/apache/cassandra/cql3/CqlParserTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/CqlParserTest.java b/test/unit/org/apache/cassandra/cql3/CqlParserTest.java new file mode 100644 index 0000000..d122eb5 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/CqlParserTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.cql3; + +import org.junit.Test; + +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.BaseRecognizer; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.TokenStream; + +import static org.junit.Assert.*; + +public class CqlParserTest +{ + @Test + public void testAddErrorListener() throws Exception + { + SyntaxErrorCounter firstCounter = new SyntaxErrorCounter(); + SyntaxErrorCounter secondCounter = new SyntaxErrorCounter(); + + CharStream stream = new ANTLRStringStream("SELECT * FORM test;"); + CqlLexer lexer = new CqlLexer(stream); + + TokenStream tokenStream = new CommonTokenStream(lexer); + CqlParser parser = new CqlParser(tokenStream); + parser.addErrorListener(firstCounter); + parser.addErrorListener(secondCounter); + + parser.query(); + + assertEquals(1, firstCounter.count); + assertEquals(1, secondCounter.count); + } + + @Test + public void testRemoveErrorListener() throws Exception + { + SyntaxErrorCounter firstCounter = new SyntaxErrorCounter(); + SyntaxErrorCounter secondCounter = new SyntaxErrorCounter(); + + CharStream stream = new ANTLRStringStream("SELECT * FORM test;"); + CqlLexer lexer = new CqlLexer(stream); + + TokenStream tokenStream = new CommonTokenStream(lexer); + CqlParser parser = new CqlParser(tokenStream); + parser.addErrorListener(firstCounter); + parser.addErrorListener(secondCounter); + parser.removeErrorListener(secondCounter); + + parser.query(); + + assertEquals(1, firstCounter.count); + assertEquals(0, secondCounter.count); + } + + private static final class SyntaxErrorCounter implements ErrorListener + { + private int count; + + @Override + public void syntaxError(BaseRecognizer recognizer, String[] tokenNames, RecognitionException e) + { + count++; + } + + @Override + public void syntaxError(BaseRecognizer recognizer, String errorMsg) + { + count++; + } + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/8a2d8a13/test/unit/org/apache/cassandra/cql3/ErrorCollectorTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/ErrorCollectorTest.java b/test/unit/org/apache/cassandra/cql3/ErrorCollectorTest.java new file mode 100644 index 0000000..4f5db34 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/ErrorCollectorTest.java @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.cql3; + +import org.antlr.runtime.CharStream; +import org.antlr.runtime.Token; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ErrorCollectorTest +{ + @Test + public void testAppendSnippetWithEmptyQuery() + { + String query = ";"; + + ErrorCollector collector = new ErrorCollector(query); + + StringBuilder builder = new StringBuilder(); + + Token from = new MockToken(1, 0, ";"); + Token to = new MockToken(1, 0, ";"); + Token offending = new MockToken(1, 0, ";"); + + collector.appendSnippet(builder, from, to, offending); + + String expected = " ([;])"; + + assertEquals(expected, builder.toString()); + } + + @Test + public void testAppendSnippetWithOneLines() + { + String query = "select * from users where user_name = ''test'';"; + + ErrorCollector collector = new ErrorCollector(query); + + StringBuilder builder = new StringBuilder(); + + Token from = new MockToken(1, 25, " "); + Token to = new MockToken(1, 46, ";"); + Token offending = new MockToken(1, 40, "test"); + + collector.appendSnippet(builder, from, to, offending); + + String expected = " (... user_name = ''[test]'';)"; + + assertEquals(expected, builder.toString()); + } + + @Test + public void testAppendSnippetOnSecondLine() + { + String query = "select * from users\n" + + "where user_name = ''test'';"; + + ErrorCollector collector = new ErrorCollector(query); + + StringBuilder builder = new StringBuilder(); + + Token from = new MockToken(2, 5, " "); + Token to = new MockToken(2, 26, ";"); + Token offending = new MockToken(2, 20, "test"); + + collector.appendSnippet(builder, from, to, offending); + + String expected = " (... user_name = ''[test]'';)"; + + assertEquals(expected, builder.toString()); + } + + @Test + public void testAppendSnippetWithSnippetOverTwoLines() + { + String query = "select * from users where user_name \n" + + "= ''test'';"; + + ErrorCollector collector = new ErrorCollector(query); + + StringBuilder builder = new StringBuilder(); + + Token from = new MockToken(1, 20, "where"); + Token to = new MockToken(2, 9, "'"); + Token offending = new MockToken(2, 4, "test"); + + collector.appendSnippet(builder, from, to, offending); + + String expected = " (...where user_name = ''[test]''...)"; + + assertEquals(expected, builder.toString()); + } + + private final static class MockToken implements Token + { + /** + * The line number on which this token was matched; line=1..n + */ + private int line; + + /** + * The index of the first character relative to the beginning of the line 0..n-1 + */ + private int charPositionInLine; + + /** + * The text of the token + */ + private String text; + + public MockToken(int line, int charPositionInLine, String text) + { + this.line = line; + this.charPositionInLine = charPositionInLine; + this.text = text; + } + + @Override + public int getChannel() + { + throw new UnsupportedOperationException(); + } + + @Override + public int getCharPositionInLine() + { + return charPositionInLine; + } + + @Override + public CharStream getInputStream() + { + throw new UnsupportedOperationException(); + } + + @Override + public int getLine() + { + return line; + } + + @Override + public String getText() + { + return text; + } + + @Override + public int getTokenIndex() + { + throw new UnsupportedOperationException(); + } + + @Override + public int getType() + { + throw new UnsupportedOperationException(); + } + + @Override + public void setChannel(int channel) + { + throw new UnsupportedOperationException(); + } + + @Override + public void setCharPositionInLine(int charPositionInLine) + { + this.charPositionInLine = charPositionInLine; + } + + @Override + public void setInputStream(CharStream inputStream) + { + throw new UnsupportedOperationException(); + } + + @Override + public void setLine(int line) + { + this.line = line; + } + + @Override + public void setText(String text) + { + this.text = text; + } + + @Override + public void setTokenIndex(int tokenIndex) + { + throw new UnsupportedOperationException(); + } + + @Override + public void setType(int type) + { + throw new UnsupportedOperationException(); + } + } +}