1. /*
  2. * @(#)StreamTokenizer.java 1.32 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. /**
  9. * The <code>StreamTokenizer</code> class takes an input stream and
  10. * parses it into "tokens", allowing the tokens to be
  11. * read one at a time. The parsing process is controlled by a table
  12. * and a number of flags that can be set to various states. The
  13. * stream tokenizer can recognize identifiers, numbers, quoted
  14. * strings, and various comment styles.
  15. * <p>
  16. * Each byte read from the input stream is regarded as a character
  17. * in the range <code>'\u0000'</code> through <code>'\u00FF'</code>.
  18. * The character value is used to look up five possible attributes of
  19. * the character: <i>white space</i>, <i>alphabetic</i>,
  20. * <i>numeric</i>, <i>string quote</i>, and <i>comment character</i>.
  21. * Each character can have zero or more of these attributes.
  22. * <p>
  23. * In addition, an instance has four flags. These flags indicate:
  24. * <ul>
  25. * <li>Whether line terminators are to be returned as tokens or treated
  26. * as white space that merely separates tokens.
  27. * <li>Whether C-style comments are to be recognized and skipped.
  28. * <li>Whether C++-style comments are to be recognized and skipped.
  29. * <li>Whether the characters of identifiers are converted to lowercase.
  30. * </ul>
  31. * <p>
  32. * A typical application first constructs an instance of this class,
  33. * sets up the syntax tables, and then repeatedly loops calling the
  34. * <code>nextToken</code> method in each iteration of the loop until
  35. * it returns the value <code>TT_EOF</code>.
  36. *
  37. * @author James Gosling
  38. * @version 1.32, 11/29/01
  39. * @see java.io.StreamTokenizer#nextToken()
  40. * @see java.io.StreamTokenizer#TT_EOF
  41. * @since JDK1.0
  42. */
  43. public class StreamTokenizer {
  44. /* Only one of these will be non-null */
  45. private Reader reader = null;
  46. private InputStream input = null;
  47. private char buf[] = new char[20];
  48. /**
  49. * The next character to be considered by the nextToken method. May also
  50. * be NEED_CHAR to indicate that a new character should be read, or SKIP_LF
  51. * to indicate that a new character should be read and, if it is a '\n'
  52. * character, it should be discarded and a second new character should be
  53. * read.
  54. */
  55. private int peekc = NEED_CHAR;
  56. private static final int NEED_CHAR = Integer.MAX_VALUE;
  57. private static final int SKIP_LF = Integer.MAX_VALUE - 1;
  58. private boolean pushedBack;
  59. private boolean forceLower;
  60. /** The line number of the last token read */
  61. private int LINENO = 1;
  62. private boolean eolIsSignificantP = false;
  63. private boolean slashSlashCommentsP = false;
  64. private boolean slashStarCommentsP = false;
  65. private byte ctype[] = new byte[256];
  66. private static final byte CT_WHITESPACE = 1;
  67. private static final byte CT_DIGIT = 2;
  68. private static final byte CT_ALPHA = 4;
  69. private static final byte CT_QUOTE = 8;
  70. private static final byte CT_COMMENT = 16;
  71. /**
  72. * After a call to the <code>nextToken</code> method, this field
  73. * contains the type of the token just read. For a single character
  74. * token, its value is the single character, converted to an integer.
  75. * For a quoted string token (see , its value is the quote character.
  76. * Otherwise, its value is one of the following:
  77. * <ul>
  78. * <li><code>TT_WORD</code> indicates that the token is a word.
  79. * <li><code>TT_NUMBER</code> indicates that the token is a number.
  80. * <li><code>TT_EOL</code> indicates that the end of line has been read.
  81. * The field can only have this value if the
  82. * <code>eolIsSignificant</code> method has been called with the
  83. * argument <code>true</code>.
  84. * <li><code>TT_EOF</code> indicates that the end of the input stream
  85. * has been reached.
  86. * </ul>
  87. *
  88. * @see java.io.StreamTokenizer#eolIsSignificant(boolean)
  89. * @see java.io.StreamTokenizer#nextToken()
  90. * @see java.io.StreamTokenizer#quoteChar(int)
  91. * @see java.io.StreamTokenizer#TT_EOF
  92. * @see java.io.StreamTokenizer#TT_EOL
  93. * @see java.io.StreamTokenizer#TT_NUMBER
  94. * @see java.io.StreamTokenizer#TT_WORD
  95. */
  96. public int ttype = TT_NOTHING;
  97. /**
  98. * A constant indicating that the end of the stream has been read.
  99. */
  100. public static final int TT_EOF = -1;
  101. /**
  102. * A constant indicating that the end of the line has been read.
  103. */
  104. public static final int TT_EOL = '\n';
  105. /**
  106. * A constant indicating that a number token has been read.
  107. */
  108. public static final int TT_NUMBER = -2;
  109. /**
  110. * A constant indicating that a word token has been read.
  111. */
  112. public static final int TT_WORD = -3;
  113. /* A constant indicating that no token has been read, used for
  114. * initializing ttype. FIXME This could be made public and
  115. * made available as the part of the API in a future release.
  116. */
  117. private static final int TT_NOTHING = -4;
  118. /**
  119. * If the current token is a word token, this field contains a
  120. * string giving the characters of the word token. When the current
  121. * token is a quoted string token, this field contains the body of
  122. * the string.
  123. * <p>
  124. * The current token is a word when the value of the
  125. * <code>ttype</code> field is <code>TT_WORD</code>. The current token is
  126. * a quoted string token when the value of the <code>ttype</code> field is
  127. * a quote character.
  128. *
  129. * @see java.io.StreamTokenizer#quoteChar(int)
  130. * @see java.io.StreamTokenizer#TT_WORD
  131. * @see java.io.StreamTokenizer#ttype
  132. */
  133. public String sval;
  134. /**
  135. * If the current token is a number, this field contains the value
  136. * of that number. The current token is a number when the value of
  137. * the <code>ttype</code> field is <code>TT_NUMBER</code>.
  138. *
  139. * @see java.io.StreamTokenizer#TT_NUMBER
  140. * @see java.io.StreamTokenizer#ttype
  141. */
  142. public double nval;
  143. /** Private constructor that initializes everything except the streams. */
  144. private StreamTokenizer() {
  145. wordChars('a', 'z');
  146. wordChars('A', 'Z');
  147. wordChars(128 + 32, 255);
  148. whitespaceChars(0, ' ');
  149. commentChar('/');
  150. quoteChar('"');
  151. quoteChar('\'');
  152. parseNumbers();
  153. }
  154. /**
  155. * Creates a stream tokenizer that parses the specified input
  156. * stream. The stream tokenizer is initialized to the following
  157. * default state:
  158. * <ul>
  159. * <li>All byte values <code>'A'</code> through <code>'Z'</code>,
  160. * <code>'a'</code> through <code>'z'</code>, and
  161. * <code>'\u00A0'</code> through <code>'\u00FF'</code> are
  162. * considered to be alphabetic.
  163. * <li>All byte values <code>'\u0000'</code> through
  164. * <code>'\u0020'</code> are considered to be white space.
  165. * <li><code>'/'</code> is a comment character.
  166. * <li>Single quote <code>'\''</code> and double quote <code>'"'</code>
  167. * are string quote characters.
  168. * <li>Numbers are parsed.
  169. * <li>Ends of lines are treated as white space, not as separate tokens.
  170. * <li>C-style and C++-style comments are not recognized.
  171. * </ul>
  172. *
  173. * @deprecated As of JDK version 1.1, the preferred way to tokenize an
  174. * input stream is to convert it into a character stream, for example:
  175. * <blockquote><pre>
  176. * Reader r = new BufferedReader(new InputStreamReader(is));
  177. * StreamTokenizer st = new StreamTokenizer(r);
  178. * </pre></blockquote>
  179. *
  180. * @param is an input stream.
  181. * @see java.io.BufferedReader
  182. * @see java.io.InputStreamReader
  183. * @see java.io.StreamTokenizer#StreamTokenizer(java.io.Reader)
  184. */
  185. public StreamTokenizer(InputStream is) {
  186. this();
  187. if (is == null) {
  188. throw new NullPointerException();
  189. }
  190. input = is;
  191. }
  192. /**
  193. * Create a tokenizer that parses the given character stream.
  194. * @since JDK1.1
  195. */
  196. public StreamTokenizer(Reader r) {
  197. this();
  198. if (r == null) {
  199. throw new NullPointerException();
  200. }
  201. reader = r;
  202. }
  203. /**
  204. * Resets this tokenizer's syntax table so that all characters are
  205. * "ordinary." See the <code>ordinaryChar</code> method
  206. * for more information on a character being ordinary.
  207. *
  208. * @see java.io.StreamTokenizer#ordinaryChar(int)
  209. */
  210. public void resetSyntax() {
  211. for (int i = ctype.length; --i >= 0;)
  212. ctype[i] = 0;
  213. }
  214. /**
  215. * Specifies that all characters <i>c</i> in the range
  216. * <code>low <= <i>c</i> <= high</code>
  217. * are word constituents. A word token consists of a word constituent
  218. * followed by zero or more word constituents or number constituents.
  219. *
  220. * @param low the low end of the range.
  221. * @param hi the high end of the range.
  222. */
  223. public void wordChars(int low, int hi) {
  224. if (low < 0)
  225. low = 0;
  226. if (hi >= ctype.length)
  227. hi = ctype.length - 1;
  228. while (low <= hi)
  229. ctype[low++] |= CT_ALPHA;
  230. }
  231. /**
  232. * Specifies that all characters <i>c</i> in the range
  233. * <code>low <= <i>c</i> <= high</code>
  234. * are white space characters. White space characters serve only to
  235. * separate tokens in the input stream.
  236. *
  237. * @param low the low end of the range.
  238. * @param hi the high end of the range.
  239. */
  240. public void whitespaceChars(int low, int hi) {
  241. if (low < 0)
  242. low = 0;
  243. if (hi >= ctype.length)
  244. hi = ctype.length - 1;
  245. while (low <= hi)
  246. ctype[low++] = CT_WHITESPACE;
  247. }
  248. /**
  249. * Specifies that all characters <i>c</i> in the range
  250. * <code>low <= <i>c</i> <= high</code>
  251. * are "ordinary" in this tokenizer. See the
  252. * <code>ordinaryChar</code> method for more information on a
  253. * character being ordinary.
  254. *
  255. * @param low the low end of the range.
  256. * @param hi the high end of the range.
  257. * @see java.io.StreamTokenizer#ordinaryChar(int)
  258. */
  259. public void ordinaryChars(int low, int hi) {
  260. if (low < 0)
  261. low = 0;
  262. if (hi >= ctype.length)
  263. hi = ctype.length - 1;
  264. while (low <= hi)
  265. ctype[low++] = 0;
  266. }
  267. /**
  268. * Specifies that the character argument is "ordinary"
  269. * in this tokenizer. It removes any special significance the
  270. * character has as a comment character, word component, string
  271. * delimiter, white space, or number character. When such a character
  272. * is encountered by the parser, the parser treates it as a
  273. * single-character token and sets <code>ttype</code> field to the
  274. * character value.
  275. *
  276. * @param ch the character.
  277. * @see java.io.StreamTokenizer#ttype
  278. */
  279. public void ordinaryChar(int ch) {
  280. if (ch >= 0 && ch < ctype.length)
  281. ctype[ch] = 0;
  282. }
  283. /**
  284. * Specified that the character argument starts a single-line
  285. * comment. All characters from the comment character to the end of
  286. * the line are ignored by this stream tokenizer.
  287. *
  288. * @param ch the character.
  289. */
  290. public void commentChar(int ch) {
  291. if (ch >= 0 && ch < ctype.length)
  292. ctype[ch] = CT_COMMENT;
  293. }
  294. /**
  295. * Specifies that matching pairs of this character delimit string
  296. * constants in this tokenizer.
  297. * <p>
  298. * When the <code>nextToken</code> method encounters a string
  299. * constant, the <code>ttype</code> field is set to the string
  300. * delimiter and the <code>sval</code> field is set to the body of
  301. * the string.
  302. * <p>
  303. * If a string quote character is encountered, then a string is
  304. * recognized, consisting of all characters after (but not including)
  305. * the string quote character, up to (but not including) the next
  306. * occurrence of that same string quote character, or a line
  307. * terminator, or end of file. The usual escape sequences such as
  308. * <code>"\n"</code> and <code>"\t"</code> are recognized and
  309. * converted to single characters as the string is parsed.
  310. *
  311. * @param ch the character.
  312. * @see java.io.StreamTokenizer#nextToken()
  313. * @see java.io.StreamTokenizer#sval
  314. * @see java.io.StreamTokenizer#ttype
  315. */
  316. public void quoteChar(int ch) {
  317. if (ch >= 0 && ch < ctype.length)
  318. ctype[ch] = CT_QUOTE;
  319. }
  320. /**
  321. * Specifies that numbers should be parsed by this tokenizer. The
  322. * syntax table of this tokenizer is modified so that each of the twelve
  323. * characters:
  324. * <blockquote><pre>
  325. * 0 1 2 3 4 5 6 7 8 9 . -
  326. * </pre></blockquote>
  327. * <p>
  328. * has the "numeric" attribute.
  329. * <p>
  330. * When the parser encounters a word token that has the format of a
  331. * double precision floating-point number, it treats the token as a
  332. * number rather than a word, by setting the the <code>ttype</code>
  333. * field to the value <code>TT_NUMBER</code> and putting the numeric
  334. * value of the token into the <code>nval</code> field.
  335. *
  336. * @see java.io.StreamTokenizer#nval
  337. * @see java.io.StreamTokenizer#TT_NUMBER
  338. * @see java.io.StreamTokenizer#ttype
  339. */
  340. public void parseNumbers() {
  341. for (int i = '0'; i <= '9'; i++)
  342. ctype[i] |= CT_DIGIT;
  343. ctype['.'] |= CT_DIGIT;
  344. ctype['-'] |= CT_DIGIT;
  345. }
  346. /**
  347. * Determines whether or not ends of line are treated as tokens.
  348. * If the flag argument is true, this tokenizer treats end of lines
  349. * as tokens; the <code>nextToken</code> method returns
  350. * <code>TT_EOL</code> and also sets the <code>ttype</code> field to
  351. * this value when an end of line is read.
  352. * <p>
  353. * A line is a sequence of characters ending with either a
  354. * carriage-return character (<code>'\r'</code>) or a newline
  355. * character (<code>'\n'</code>). In addition, a carriage-return
  356. * character followed immediately by a newline character is treated
  357. * as a single end-of-line token.
  358. * <p>
  359. * If the <code>flag</code> is false, end-of-line characters are
  360. * treated as white space and serve only to separate tokens.
  361. *
  362. * @param flag <code>true</code> indicates that end-of-line characters
  363. * are separate tokens; <code>false</code> indicates that
  364. * end-of-line characters are white space.
  365. * @see java.io.StreamTokenizer#nextToken()
  366. * @see java.io.StreamTokenizer#ttype
  367. * @see java.io.StreamTokenizer#TT_EOL
  368. */
  369. public void eolIsSignificant(boolean flag) {
  370. eolIsSignificantP = flag;
  371. }
  372. /**
  373. * Determines whether or not the tokenizer recognizes C-style comments.
  374. * If the flag argument is <code>true</code>, this stream tokenizer
  375. * recognizes C-style comments. All text between successive
  376. * occurrences of <code>/*</code> and <code>*/</code> are discarded.
  377. * <p>
  378. * If the flag argument is <code>false</code>, then C-style comments
  379. * are not treated specially.
  380. *
  381. * @param flag <code>true</code> indicates to recognize and ignore
  382. * C-style comments.
  383. */
  384. public void slashStarComments(boolean flag) {
  385. slashStarCommentsP = flag;
  386. }
  387. /**
  388. * Determines whether or not the tokenizer recognizes C++-style comments.
  389. * If the flag argument is <code>true</code>, this stream tokenizer
  390. * recognizes C++-style comments. Any occurrence of two consecutive
  391. * slash characters (<code>'/'</code>) is treated as the beginning of
  392. * a comment that extends to the end of the line.
  393. * <p>
  394. * If the flag argument is <code>false</code>, then C++-style
  395. * comments are not treated specially.
  396. *
  397. * @param flag <code>true</code> indicates to recognize and ignore
  398. * C++-style comments.
  399. */
  400. public void slashSlashComments(boolean flag) {
  401. slashSlashCommentsP = flag;
  402. }
  403. /**
  404. * Determines whether or not word token are automatically lowercased.
  405. * If the flag argument is <code>true</code>, then the value in the
  406. * <code>sval</code> field is lowercased whenever a word token is
  407. * returned (the <code>ttype</code> field has the
  408. * value <code>TT_WORD</code> by the <code>nextToken</code> method
  409. * of this tokenizer.
  410. * <p>
  411. * If the flag argument is <code>false</code>, then the
  412. * <code>sval</code> field is not modified.
  413. *
  414. * @param fl <code>true</code> indicates that all word tokens should
  415. * be lowercased.
  416. * @see java.io.StreamTokenizer#nextToken()
  417. * @see java.io.StreamTokenizer#ttype
  418. * @see java.io.StreamTokenizer#TT_WORD
  419. */
  420. public void lowerCaseMode(boolean fl) {
  421. forceLower = fl;
  422. }
  423. /** Read the next character */
  424. private int read() throws IOException {
  425. if (reader != null)
  426. return reader.read();
  427. else if (input != null)
  428. return input.read();
  429. else
  430. throw new IllegalStateException();
  431. }
  432. /**
  433. * Parses the next token from the input stream of this tokenizer.
  434. * The type of the next token is returned in the <code>ttype</code>
  435. * field. Additional information about the token may be in the
  436. * <code>nval</code> field or the <code>sval</code> field of this
  437. * tokenizer.
  438. * <p>
  439. * Typical clients of this
  440. * class first set up the syntax tables and then sit in a loop
  441. * calling nextToken to parse successive tokens until TT_EOF
  442. * is returned.
  443. *
  444. * @return the value of the <code>ttype</code> field.
  445. * @exception IOException if an I/O error occurs.
  446. * @see java.io.StreamTokenizer#nval
  447. * @see java.io.StreamTokenizer#sval
  448. * @see java.io.StreamTokenizer#ttype
  449. */
  450. public int nextToken() throws IOException {
  451. if (pushedBack) {
  452. pushedBack = false;
  453. return ttype;
  454. }
  455. byte ct[] = ctype;
  456. sval = null;
  457. int c = peekc;
  458. if (c < 0)
  459. c = NEED_CHAR;
  460. if (c == SKIP_LF) {
  461. c = read();
  462. if (c < 0)
  463. return ttype = TT_EOF;
  464. if (c == '\n')
  465. c = NEED_CHAR;
  466. }
  467. if (c == NEED_CHAR) {
  468. c = read();
  469. if (c < 0)
  470. return ttype = TT_EOF;
  471. }
  472. ttype = c; /* Just to be safe */
  473. /* Set peekc so that the next invocation of nextToken will read
  474. * another character unless peekc is reset in this invocation
  475. */
  476. peekc = NEED_CHAR;
  477. int ctype = c < 256 ? ct[c] : CT_ALPHA;
  478. while ((ctype & CT_WHITESPACE) != 0) {
  479. if (c == '\r') {
  480. LINENO++;
  481. if (eolIsSignificantP) {
  482. peekc = SKIP_LF;
  483. return ttype = TT_EOL;
  484. }
  485. c = read();
  486. if (c == '\n')
  487. c = read();
  488. } else {
  489. if (c == '\n') {
  490. LINENO++;
  491. if (eolIsSignificantP) {
  492. return ttype = TT_EOL;
  493. }
  494. }
  495. c = read();
  496. }
  497. if (c < 0)
  498. return ttype = TT_EOF;
  499. ctype = c < 256 ? ct[c] : CT_ALPHA;
  500. }
  501. if ((ctype & CT_DIGIT) != 0) {
  502. boolean neg = false;
  503. if (c == '-') {
  504. c = read();
  505. if (c != '.' && (c < '0' || c > '9')) {
  506. peekc = c;
  507. return ttype = '-';
  508. }
  509. neg = true;
  510. }
  511. double v = 0;
  512. int decexp = 0;
  513. int seendot = 0;
  514. while (true) {
  515. if (c == '.' && seendot == 0)
  516. seendot = 1;
  517. else if ('0' <= c && c <= '9') {
  518. v = v * 10 + (c - '0');
  519. decexp += seendot;
  520. } else
  521. break;
  522. c = read();
  523. }
  524. peekc = c;
  525. if (decexp != 0) {
  526. double denom = 10;
  527. decexp--;
  528. while (decexp > 0) {
  529. denom *= 10;
  530. decexp--;
  531. }
  532. /* Do one division of a likely-to-be-more-accurate number */
  533. v = v / denom;
  534. }
  535. nval = neg ? -v : v;
  536. return ttype = TT_NUMBER;
  537. }
  538. if ((ctype & CT_ALPHA) != 0) {
  539. int i = 0;
  540. do {
  541. if (i >= buf.length) {
  542. char nb[] = new char[buf.length * 2];
  543. System.arraycopy(buf, 0, nb, 0, buf.length);
  544. buf = nb;
  545. }
  546. buf[i++] = (char) c;
  547. c = read();
  548. ctype = c < 0 ? CT_WHITESPACE : c < 256 ? ct[c] : CT_ALPHA;
  549. } while ((ctype & (CT_ALPHA | CT_DIGIT)) != 0);
  550. peekc = c;
  551. sval = String.copyValueOf(buf, 0, i);
  552. if (forceLower)
  553. sval = sval.toLowerCase();
  554. return ttype = TT_WORD;
  555. }
  556. if ((ctype & CT_QUOTE) != 0) {
  557. ttype = c;
  558. int i = 0;
  559. /* Invariants (because \Octal needs a lookahead):
  560. * (i) c contains char value
  561. * (ii) d contains the lookahead
  562. */
  563. int d = read();
  564. while (d >= 0 && d != ttype && d != '\n' && d != '\r') {
  565. if (d == '\\') {
  566. c = read();
  567. int first = c; /* To allow \377, but not \477 */
  568. if (c >= '0' && c <= '7') {
  569. c = c - '0';
  570. int c2 = read();
  571. if ('0' <= c2 && c2 <= '7') {
  572. c = (c << 3) + (c2 - '0');
  573. c2 = read();
  574. if ('0' <= c2 && c2 <= '7' && first <= '3') {
  575. c = (c << 3) + (c2 - '0');
  576. d = read();
  577. } else
  578. d = c2;
  579. } else
  580. d = c2;
  581. } else {
  582. switch (c) {
  583. case 'a':
  584. c = 0x7;
  585. break;
  586. case 'b':
  587. c = '\b';
  588. break;
  589. case 'f':
  590. c = 0xC;
  591. break;
  592. case 'n':
  593. c = '\n';
  594. break;
  595. case 'r':
  596. c = '\r';
  597. break;
  598. case 't':
  599. c = '\t';
  600. break;
  601. case 'v':
  602. c = 0xB;
  603. break;
  604. }
  605. d = read();
  606. }
  607. } else {
  608. c = d;
  609. d = read();
  610. }
  611. if (i >= buf.length) {
  612. char nb[] = new char[buf.length * 2];
  613. System.arraycopy(buf, 0, nb, 0, buf.length);
  614. buf = nb;
  615. }
  616. buf[i++] = (char)c;
  617. }
  618. /* If we broke out of the loop because we found a matching quote
  619. * character then arrange to read a new character next time
  620. * around; otherwise, save the character.
  621. */
  622. peekc = (d == ttype) ? NEED_CHAR : d;
  623. sval = String.copyValueOf(buf, 0, i);
  624. return ttype;
  625. }
  626. if (c == '/' && (slashSlashCommentsP || slashStarCommentsP)) {
  627. c = read();
  628. if (c == '*' && slashStarCommentsP) {
  629. int prevc = 0;
  630. while ((c = read()) != '/' || prevc != '*') {
  631. if (c == '\r') {
  632. LINENO++;
  633. c = read();
  634. if (c == '\n') {
  635. c = read();
  636. }
  637. } else {
  638. if (c == '\n') {
  639. LINENO++;
  640. c = read();
  641. }
  642. }
  643. if (c < 0)
  644. return ttype = TT_EOF;
  645. prevc = c;
  646. }
  647. return nextToken();
  648. } else if (c == '/' && slashSlashCommentsP) {
  649. while ((c = read()) != '\n' && c != '\r' && c >= 0);
  650. peekc = c;
  651. return nextToken();
  652. } else {
  653. /* Now see if it is still a single line comment */
  654. if ((ct['/'] & CT_COMMENT) != 0) {
  655. while ((c = read()) != '\n' && c != '\r' && c >= 0);
  656. peekc = c;
  657. return nextToken();
  658. } else {
  659. peekc = c;
  660. return ttype = '/';
  661. }
  662. }
  663. }
  664. if ((ctype & CT_COMMENT) != 0) {
  665. while ((c = read()) != '\n' && c != '\r' && c >= 0);
  666. peekc = c;
  667. return nextToken();
  668. }
  669. return ttype = c;
  670. }
  671. /**
  672. * Causes the next call to the <code>nextToken</code> method of this
  673. * tokenizer to return the current value in the <code>ttype</code>
  674. * field, and not to modify the value in the <code>nval</code> or
  675. * <code>sval</code> field.
  676. *
  677. * @see java.io.StreamTokenizer#nextToken()
  678. * @see java.io.StreamTokenizer#nval
  679. * @see java.io.StreamTokenizer#sval
  680. * @see java.io.StreamTokenizer#ttype
  681. */
  682. public void pushBack() {
  683. if (ttype != TT_NOTHING) /* No-op if nextToken() not called */
  684. pushedBack = true;
  685. }
  686. /**
  687. * Return the current line number.
  688. *
  689. * @return the current line number of this stream tokenizer.
  690. */
  691. public int lineno() {
  692. return LINENO;
  693. }
  694. /**
  695. * Returns the string representation of the current stream token.
  696. *
  697. * @return a string representation of the token specified by the
  698. * <code>ttype</code>, <code>nval</code>, and <code>sval</code>
  699. * fields.
  700. * @see java.io.StreamTokenizer#nval
  701. * @see java.io.StreamTokenizer#sval
  702. * @see java.io.StreamTokenizer#ttype
  703. */
  704. public String toString() {
  705. String ret;
  706. switch (ttype) {
  707. case TT_EOF:
  708. ret = "EOF";
  709. break;
  710. case TT_EOL:
  711. ret = "EOL";
  712. break;
  713. case TT_WORD:
  714. ret = sval;
  715. break;
  716. case TT_NUMBER:
  717. ret = "n=" + nval;
  718. break;
  719. case TT_NOTHING:
  720. ret = "NOTHING";
  721. break;
  722. default:{
  723. char s[] = new char[3];
  724. s[0] = s[2] = '\'';
  725. s[1] = (char) ttype;
  726. ret = new String(s);
  727. break;
  728. }
  729. }
  730. return "Token[" + ret + "], line " + LINENO;
  731. }
  732. }