diff --git a/pmd/bin/build.xml b/pmd/bin/build.xml index 932713e57b..991ee51bfa 100644 --- a/pmd/bin/build.xml +++ b/pmd/bin/build.xml @@ -185,10 +185,7 @@ - - - - + diff --git a/pmd/etc/changelog.txt b/pmd/etc/changelog.txt index 9cd2d602e4..d7602212c2 100644 --- a/pmd/etc/changelog.txt +++ b/pmd/etc/changelog.txt @@ -14,9 +14,10 @@ Fixed bug 1522054 - BooleanInstantiation now detects instantiations inside metho Fixed bug 1522056 - UseStringBufferForStringAppends now flags appends which occur in static initializers and constructors Fixed bug 1526530 - SingularField now finds fields which are hidden at the method or static level Fixed bug 1529805 - UnusedModifier no longer throws NPEs on JDK 1.5 enums. -Fixed bug 1531593 - UnnecessaryConversionTemporary no longer reports false positives when toString() is invoked inside the call to 'new Long/Integer/etc()'. +Fixed bug 1531593 - UnnecessaryConversionTemporary no longer reports false positives when toString() is invoked inside the call to 'new Long/Integer/etc()'. Fixed a bug in AvoidProtectedFieldInFinalClass - it no longer reports false positives for protected fields in inner classes. Fixed a bug in the C++ grammar - the tokenizer now properly recognizes macro definitions which are followed by a multiline comment. +Modified C++ tokenizer to use the JavaCC STATIC option; this results in about a 30% speedup in tokenizing. Also improved error messages. Implemented RFE 1501850 - UnusedFormalParameter now catches cases where a parameter is assigned to but not used. Applied patch 1481024 (implementing RFE 1490181)- NOPMD messages can now be reported with a user specified msg, e.g., //NOPMD - this is expected Added JSP support to the copy/paste detector. diff --git a/pmd/etc/grammar/cpp.jj b/pmd/etc/grammar/cpp.jj index 0c55117357..95459237da 100644 --- a/pmd/etc/grammar/cpp.jj +++ b/pmd/etc/grammar/cpp.jj @@ -24,7 +24,6 @@ * */ options { - STATIC=false; BUILD_PARSER=false; CACHE_TOKENS=true; } @@ -129,6 +128,16 @@ public final class CPPParser { PARSER_END(CPPParser) +TOKEN_MGR_DECLS : { + private static String filename; + public static void setFileName(String name) { + filename = name; + } + public static String getFileName() { + return filename; + } +} + SKIP : { " " diff --git a/pmd/src/net/sourceforge/pmd/RuleSet.java b/pmd/src/net/sourceforge/pmd/RuleSet.java index 3588ca5284..2ca890fa79 100644 --- a/pmd/src/net/sourceforge/pmd/RuleSet.java +++ b/pmd/src/net/sourceforge/pmd/RuleSet.java @@ -98,42 +98,6 @@ public class RuleSet { } } - /** - * Gives the name of this ruleset - * - * @return a String representing the name - */ - public String getName() { - return name; - } - - /** - * Set the name of this ruleset - * - * @param name a String representing the name - */ - public void setName(String name) { - this.name = name; - } - - /** - * Gives the description of this ruleset - * - * @return a String representing the description - */ - public String getDescription() { - return description; - } - - /** - * Set the description of this ruleset - * - * @param description a String representing the description - */ - public void setDescription(String description) { - this.description = description; - } - /** * @see java.lang.Object#equals(java.lang.Object) */ @@ -157,17 +121,28 @@ public class RuleSet { return this.getName().hashCode() + 13 * this.getRules().hashCode(); } - /** - * @return Returns the language. - */ public Language getLanguage() { return language; } - /** - * @param language The language to set. - */ public void setLanguage(Language language) { this.language = language; } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + } diff --git a/pmd/src/net/sourceforge/pmd/RuleSets.java b/pmd/src/net/sourceforge/pmd/RuleSets.java index 31e5dd1bae..2006b3bf25 100644 --- a/pmd/src/net/sourceforge/pmd/RuleSets.java +++ b/pmd/src/net/sourceforge/pmd/RuleSets.java @@ -54,6 +54,10 @@ public class RuleSets { return (RuleSet[]) ruleSets.toArray(new RuleSet[0]); } + public Iterator getRuleSetsIterator() { + return ruleSets.iterator(); + } + /** * Return all rules from all rulesets. * diff --git a/pmd/src/net/sourceforge/pmd/cpd/CPPTokenizer.java b/pmd/src/net/sourceforge/pmd/cpd/CPPTokenizer.java index b5c417f8d6..116263f113 100644 --- a/pmd/src/net/sourceforge/pmd/cpd/CPPTokenizer.java +++ b/pmd/src/net/sourceforge/pmd/cpd/CPPTokenizer.java @@ -15,14 +15,28 @@ import java.util.List; public class CPPTokenizer implements Tokenizer { protected String EOL = System.getProperty("line.separator", "\n"); + private static SimpleCharStream charStream; public void tokenize(SourceCode sourceCode, Tokens tokenEntries) { StringBuffer sb = sourceCode.getCodeBuffer(); try { - CPPParserTokenManager tokenManager = new CPPParserTokenManager(new SimpleCharStream(new StringReader(sb.toString()))); - Token currToken = tokenManager.getNextToken(); +/* + if (c == null) { + c = new SimpleCharStream(new StringReader(sb.toString())); + } else { + c.ReInit(new StringReader(sb.toString())); + } +*/ + if (charStream == null) { + charStream = new SimpleCharStream(new StringReader(sb.toString())); + } else { + charStream.ReInit(new StringReader(sb.toString())); + } + CPPParserTokenManager.ReInit(charStream); + CPPParserTokenManager.setFileName(sourceCode.getFileName()); + Token currToken = CPPParserTokenManager.getNextToken(); while (currToken.image.length() > 0) { tokenEntries.add(new TokenEntry(currToken.image, sourceCode.getFileName(), currToken.beginLine)); - currToken = tokenManager.getNextToken(); + currToken = CPPParserTokenManager.getNextToken(); } tokenEntries.add(TokenEntry.getEOF()); System.out.println("Added " + sourceCode.getFileName()); diff --git a/pmd/src/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java b/pmd/src/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java index faadc1a43f..f9d0854118 100644 --- a/pmd/src/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java +++ b/pmd/src/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java @@ -3,9 +3,16 @@ package net.sourceforge.pmd.cpd.cppast; public class CPPParserTokenManager implements CPPParserConstants { - public java.io.PrintStream debugStream = System.out; - public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } -private final int jjStopStringLiteralDfa_0(int pos, long active0, long active1, long active2) + private static String filename; + public static void setFileName(String name) { + filename = name; + } + public static String getFileName() { + return filename; + } + public static java.io.PrintStream debugStream = System.out; + public static void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private static final int jjStopStringLiteralDfa_0(int pos, long active0, long active1, long active2) { switch (pos) { @@ -105,17 +112,17 @@ private final int jjStopStringLiteralDfa_0(int pos, long active0, long active1, return -1; } } -private final int jjStartNfa_0(int pos, long active0, long active1, long active2) +private static final int jjStartNfa_0(int pos, long active0, long active1, long active2) { return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1, active2), pos + 1); } -private final int jjStopAtPos(int pos, int kind) +static private final int jjStopAtPos(int pos, int kind) { jjmatchedKind = kind; jjmatchedPos = pos; return pos + 1; } -private final int jjStartNfaWithStates_0(int pos, int kind, int state) +static private final int jjStartNfaWithStates_0(int pos, int kind, int state) { jjmatchedKind = kind; jjmatchedPos = pos; @@ -123,7 +130,7 @@ private final int jjStartNfaWithStates_0(int pos, int kind, int state) catch(java.io.IOException e) { return pos + 1; } return jjMoveNfa_0(state, pos + 1); } -private final int jjMoveStringLiteralDfa0_0() +static private final int jjMoveStringLiteralDfa0_0() { switch(curChar) { @@ -233,7 +240,7 @@ private final int jjMoveStringLiteralDfa0_0() return jjMoveNfa_0(28, 0); } } -private final int jjMoveStringLiteralDfa1_0(long active0, long active1, long active2) +static private final int jjMoveStringLiteralDfa1_0(long active0, long active1, long active2) { try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { @@ -365,7 +372,7 @@ private final int jjMoveStringLiteralDfa1_0(long active0, long active1, long act } return jjStartNfa_0(0, active0, active1, active2); } -private final int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1, long old2, long active2) +static private final int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1, long old2, long active2) { if (((active0 &= old0) | (active1 &= old1) | (active2 &= old2)) == 0L) return jjStartNfa_0(0, old0, old1, old2); @@ -441,7 +448,7 @@ private final int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, } return jjStartNfa_0(1, active0, active1, active2); } -private final int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1, long old2, long active2) +static private final int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1, long old2, long active2) { if (((active0 &= old0) | (active1 &= old1) | (active2 &= old2)) == 0L) return jjStartNfa_0(1, old0, old1, old2); @@ -511,7 +518,7 @@ private final int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, } return jjStartNfa_0(2, 0L, active1, active2); } -private final int jjMoveStringLiteralDfa4_0(long old1, long active1, long old2, long active2) +static private final int jjMoveStringLiteralDfa4_0(long old1, long active1, long old2, long active2) { if (((active1 &= old1) | (active2 &= old2)) == 0L) return jjStartNfa_0(2, 0L, old1, old2); @@ -579,7 +586,7 @@ private final int jjMoveStringLiteralDfa4_0(long old1, long active1, long old2, } return jjStartNfa_0(3, 0L, active1, active2); } -private final int jjMoveStringLiteralDfa5_0(long old1, long active1, long old2, long active2) +static private final int jjMoveStringLiteralDfa5_0(long old1, long active1, long old2, long active2) { if (((active1 &= old1) | (active2 &= old2)) == 0L) return jjStartNfa_0(3, 0L, old1, old2); @@ -639,7 +646,7 @@ private final int jjMoveStringLiteralDfa5_0(long old1, long active1, long old2, } return jjStartNfa_0(4, 0L, active1, active2); } -private final int jjMoveStringLiteralDfa6_0(long old1, long active1, long old2, long active2) +static private final int jjMoveStringLiteralDfa6_0(long old1, long active1, long old2, long active2) { if (((active1 &= old1) | (active2 &= old2)) == 0L) return jjStartNfa_0(4, 0L, old1, old2); @@ -681,7 +688,7 @@ private final int jjMoveStringLiteralDfa6_0(long old1, long active1, long old2, } return jjStartNfa_0(5, 0L, active1, active2); } -private final int jjMoveStringLiteralDfa7_0(long old1, long active1, long old2, long active2) +static private final int jjMoveStringLiteralDfa7_0(long old1, long active1, long old2, long active2) { if (((active1 &= old1) | (active2 &= old2)) == 0L) return jjStartNfa_0(5, 0L, old1, old2); @@ -715,7 +722,7 @@ private final int jjMoveStringLiteralDfa7_0(long old1, long active1, long old2, } return jjStartNfa_0(6, 0L, active1, 0L); } -private final int jjMoveStringLiteralDfa8_0(long old1, long active1) +static private final int jjMoveStringLiteralDfa8_0(long old1, long active1) { if (((active1 &= old1)) == 0L) return jjStartNfa_0(6, 0L, old1, 0L); @@ -737,7 +744,7 @@ private final int jjMoveStringLiteralDfa8_0(long old1, long active1) } return jjStartNfa_0(7, 0L, active1, 0L); } -private final int jjMoveStringLiteralDfa9_0(long old1, long active1) +static private final int jjMoveStringLiteralDfa9_0(long old1, long active1) { if (((active1 &= old1)) == 0L) return jjStartNfa_0(7, 0L, old1, 0L); @@ -757,7 +764,7 @@ private final int jjMoveStringLiteralDfa9_0(long old1, long active1) } return jjStartNfa_0(8, 0L, active1, 0L); } -private final void jjCheckNAdd(int state) +static private final void jjCheckNAdd(int state) { if (jjrounds[state] != jjround) { @@ -765,24 +772,24 @@ private final void jjCheckNAdd(int state) jjrounds[state] = jjround; } } -private final void jjAddStates(int start, int end) +static private final void jjAddStates(int start, int end) { do { jjstateSet[jjnewStateCnt++] = jjnextStates[start]; } while (start++ != end); } -private final void jjCheckNAddTwoStates(int state1, int state2) +static private final void jjCheckNAddTwoStates(int state1, int state2) { jjCheckNAdd(state1); jjCheckNAdd(state2); } -private final void jjCheckNAddStates(int start, int end) +static private final void jjCheckNAddStates(int start, int end) { do { jjCheckNAdd(jjnextStates[start]); } while (start++ != end); } -private final void jjCheckNAddStates(int start) +static private final void jjCheckNAddStates(int start) { jjCheckNAdd(jjnextStates[start]); jjCheckNAdd(jjnextStates[start + 1]); @@ -790,7 +797,7 @@ private final void jjCheckNAddStates(int start) static final long[] jjbitVec0 = { 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL }; -private final int jjMoveNfa_0(int startState, int curPos) +static private final int jjMoveNfa_0(int startState, int curPos) { int[] nextStates; int startsAt = 0; @@ -1294,7 +1301,7 @@ private final int jjMoveNfa_0(int startState, int curPos) catch(java.io.IOException e) { return curPos; } } } -private final int jjMoveStringLiteralDfa0_1() +static private final int jjMoveStringLiteralDfa0_1() { switch(curChar) { @@ -1304,7 +1311,7 @@ private final int jjMoveStringLiteralDfa0_1() return 1; } } -private final int jjMoveStringLiteralDfa0_4() +static private final int jjMoveStringLiteralDfa0_4() { switch(curChar) { @@ -1318,7 +1325,7 @@ private final int jjMoveStringLiteralDfa0_4() return 1; } } -private final int jjMoveStringLiteralDfa1_4(long active0) +static private final int jjMoveStringLiteralDfa1_4(long active0) { try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { @@ -1341,7 +1348,7 @@ private final int jjMoveStringLiteralDfa1_4(long active0) } return 2; } -private final int jjMoveStringLiteralDfa2_4(long old0, long active0) +static private final int jjMoveStringLiteralDfa2_4(long old0, long active0) { if (((active0 &= old0)) == 0L) return 2; @@ -1360,7 +1367,7 @@ private final int jjMoveStringLiteralDfa2_4(long old0, long active0) } return 3; } -private final int jjMoveStringLiteralDfa0_3() +static private final int jjMoveStringLiteralDfa0_3() { switch(curChar) { @@ -1370,7 +1377,7 @@ private final int jjMoveStringLiteralDfa0_3() return 1; } } -private final int jjMoveStringLiteralDfa1_3(long active0) +static private final int jjMoveStringLiteralDfa1_3(long active0) { try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { @@ -1387,7 +1394,7 @@ private final int jjMoveStringLiteralDfa1_3(long active0) } return 2; } -private final int jjMoveStringLiteralDfa0_2() +static private final int jjMoveStringLiteralDfa0_2() { switch(curChar) { @@ -1397,7 +1404,7 @@ private final int jjMoveStringLiteralDfa0_2() return 1; } } -private final int jjMoveStringLiteralDfa1_2(long active0) +static private final int jjMoveStringLiteralDfa1_2(long active0) { try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { @@ -1469,39 +1476,39 @@ static final long[] jjtoSkip = { static final long[] jjtoMore = { 0x71400L, 0x0L, 0x0L, }; -protected SimpleCharStream input_stream; -private final int[] jjrounds = new int[78]; -private final int[] jjstateSet = new int[156]; -protected char curChar; +static protected SimpleCharStream input_stream; +static private final int[] jjrounds = new int[78]; +static private final int[] jjstateSet = new int[156]; +static protected char curChar; public CPPParserTokenManager(SimpleCharStream stream){ - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + if (input_stream != null) + throw new TokenMgrError("ERROR: Second call to constructor of static lexer. You must use ReInit() to initialize the static variables.", TokenMgrError.STATIC_LEXER_ERROR); input_stream = stream; } public CPPParserTokenManager(SimpleCharStream stream, int lexState){ this(stream); SwitchTo(lexState); } -public void ReInit(SimpleCharStream stream) +static public void ReInit(SimpleCharStream stream) { jjmatchedPos = jjnewStateCnt = 0; curLexState = defaultLexState; input_stream = stream; ReInitRounds(); } -private final void ReInitRounds() +static private final void ReInitRounds() { int i; jjround = 0x80000001; for (i = 78; i-- > 0;) jjrounds[i] = 0x80000000; } -public void ReInit(SimpleCharStream stream, int lexState) +static public void ReInit(SimpleCharStream stream, int lexState) { ReInit(stream); SwitchTo(lexState); } -public void SwitchTo(int lexState) +static public void SwitchTo(int lexState) { if (lexState >= 5 || lexState < 0) throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); @@ -1509,7 +1516,7 @@ public void SwitchTo(int lexState) curLexState = lexState; } -protected Token jjFillToken() +static protected Token jjFillToken() { Token t = Token.newToken(jjmatchedKind); t.kind = jjmatchedKind; @@ -1522,14 +1529,14 @@ protected Token jjFillToken() return t; } -int curLexState = 0; -int defaultLexState = 0; -int jjnewStateCnt; -int jjround; -int jjmatchedPos; -int jjmatchedKind; +static int curLexState = 0; +static int defaultLexState = 0; +static int jjnewStateCnt; +static int jjround; +static int jjmatchedPos; +static int jjmatchedKind; -public Token getNextToken() +public static Token getNextToken() { int kind; Token specialToken = null; diff --git a/pmd/src/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java b/pmd/src/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java index 6b0369f9eb..3bc5bbe821 100644 --- a/pmd/src/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java +++ b/pmd/src/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java @@ -8,32 +8,32 @@ package net.sourceforge.pmd.cpd.cppast; public class SimpleCharStream { - public static final boolean staticFlag = false; - int bufsize; - int available; - int tokenBegin; - public int bufpos = -1; - protected int bufline[]; - protected int bufcolumn[]; + public static final boolean staticFlag = true; + static int bufsize; + static int available; + static int tokenBegin; + static public int bufpos = -1; + static protected int bufline[]; + static protected int bufcolumn[]; - protected int column = 0; - protected int line = 1; + static protected int column = 0; + static protected int line = 1; - protected boolean prevCharIsCR = false; - protected boolean prevCharIsLF = false; + static protected boolean prevCharIsCR = false; + static protected boolean prevCharIsLF = false; - protected java.io.Reader inputStream; + static protected java.io.Reader inputStream; - protected char[] buffer; - protected int maxNextCharInd = 0; - protected int inBuf = 0; - protected int tabSize = 8; + static protected char[] buffer; + static protected int maxNextCharInd = 0; + static protected int inBuf = 0; + static protected int tabSize = 8; - protected void setTabSize(int i) { tabSize = i; } - protected int getTabSize(int i) { return tabSize; } + static protected void setTabSize(int i) { tabSize = i; } + static protected int getTabSize(int i) { return tabSize; } - protected void ExpandBuff(boolean wrapAround) + static protected void ExpandBuff(boolean wrapAround) { char[] newbuffer = new char[bufsize + 2048]; int newbufline[] = new int[bufsize + 2048]; @@ -83,7 +83,7 @@ public class SimpleCharStream tokenBegin = 0; } - protected void FillBuff() throws java.io.IOException + static protected void FillBuff() throws java.io.IOException { if (maxNextCharInd == available) { @@ -128,7 +128,7 @@ public class SimpleCharStream } } - public char BeginToken() throws java.io.IOException + static public char BeginToken() throws java.io.IOException { tokenBegin = -1; char c = readChar(); @@ -137,7 +137,7 @@ public class SimpleCharStream return c; } - protected void UpdateLineColumn(char c) + static protected void UpdateLineColumn(char c) { column++; @@ -177,7 +177,7 @@ public class SimpleCharStream bufcolumn[bufpos] = column; } - public char readChar() throws java.io.IOException + static public char readChar() throws java.io.IOException { if (inBuf > 0) { @@ -203,7 +203,7 @@ public class SimpleCharStream * @see #getEndColumn */ - public int getColumn() { + static public int getColumn() { return bufcolumn[bufpos]; } @@ -212,27 +212,27 @@ public class SimpleCharStream * @see #getEndLine */ - public int getLine() { + static public int getLine() { return bufline[bufpos]; } - public int getEndColumn() { + static public int getEndColumn() { return bufcolumn[bufpos]; } - public int getEndLine() { + static public int getEndLine() { return bufline[bufpos]; } - public int getBeginColumn() { + static public int getBeginColumn() { return bufcolumn[tokenBegin]; } - public int getBeginLine() { + static public int getBeginLine() { return bufline[tokenBegin]; } - public void backup(int amount) { + static public void backup(int amount) { inBuf += amount; if ((bufpos -= amount) < 0) @@ -242,6 +242,10 @@ public class SimpleCharStream public SimpleCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { + if (inputStream != null) + throw new Error("\n ERROR: Second call to the constructor of a static SimpleCharStream. You must\n" + + " either use ReInit() or set the JavaCC option STATIC to false\n" + + " during the generation of this class."); inputStream = dstream; line = startline; column = startcolumn - 1; @@ -356,7 +360,7 @@ public class SimpleCharStream { ReInit(dstream, startline, startcolumn, 4096); } - public String GetImage() + static public String GetImage() { if (bufpos >= tokenBegin) return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); @@ -365,7 +369,7 @@ public class SimpleCharStream new String(buffer, 0, bufpos + 1); } - public char[] GetSuffix(int len) + static public char[] GetSuffix(int len) { char[] ret = new char[len]; @@ -381,7 +385,7 @@ public class SimpleCharStream return ret; } - public void Done() + static public void Done() { buffer = null; bufline = null; @@ -391,7 +395,7 @@ public class SimpleCharStream /** * Method to adjust line and column numbers for the start of a token. */ - public void adjustBeginLineColumn(int newLine, int newCol) + static public void adjustBeginLineColumn(int newLine, int newCol) { int start = tokenBegin; int len; diff --git a/pmd/src/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java b/pmd/src/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java index b50be4fa6a..d2833b092e 100644 --- a/pmd/src/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java +++ b/pmd/src/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java @@ -95,7 +95,7 @@ public class TokenMgrError extends Error * Note: You can customize the lexical error message by modifying this method. */ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { - return("Lexical error at line " + + return("Lexical error in file " + CPPParserTokenManager.getFileName() + " at line " + errorLine + ", column " + errorColumn + ". Encountered: " + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +