/** * Read the next token from 'this.line' and append it to 'this.buf'. Tokens are separated by * Pattern_White_Space. Tokens may also be delimited by double or single quotes. The closing quote * must match the opening quote. If a '#' is encountered, the rest of the line is ignored, unless * it is backslash-escaped or within quotes. * * @param position the offset into the string * @return offset to the next character to read from line, or if the end of the line is reached * without scanning a valid token, -1 */ private int nextToken(int position) { position = PatternProps.skipWhiteSpace(line, position); if (position == line.length()) { return -1; } int startpos = position; char c = line.charAt(position++); char quote = 0; switch (c) { case '"': case '\'': quote = c; break; case '#': return -1; default: buf.append(c); break; } int[] posref = null; while (position < line.length()) { c = line.charAt(position); // 16-bit ok if (c == '\\') { if (posref == null) { posref = new int[1]; } posref[0] = position + 1; int c32 = Utility.unescapeAt(line, posref); if (c32 < 0) { throw new RuntimeException( "Invalid escape at " + reader.describePosition() + ':' + position); } UTF16.append(buf, c32); position = posref[0]; } else if ((quote != 0 && c == quote) || (quote == 0 && PatternProps.isWhiteSpace(c))) { return ++position; } else if (quote == 0 && c == '#') { return position; // do NOT increment } else { buf.append(c); ++position; } } if (quote != 0) { throw new RuntimeException( "Unterminated quote at " + reader.describePosition() + ':' + startpos); } return position; }
/** * Return a string description of the position of the last line returned by readLine() or * readLineSkippingComments(). */ public String describePosition() { return reader.describePosition() + ':' + (lastpos + 1); }