home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / java / io / streamtokenizer.java < prev    next >
Text File  |  1995-08-11  |  10KB  |  392 lines

  1. /*
  2.  * @(#)StreamTokenizer.java    1.6 95/05/10
  3.  * 
  4.  * Copyright (c) 1995 Sun Microsystems, Inc.  All Rights reserved Permission to
  5.  * use, copy, modify, and distribute this software and its documentation for
  6.  * NON-COMMERCIAL purposes and without fee is hereby granted provided that
  7.  * this copyright notice appears in all copies. Please refer to the file
  8.  * copyright.html for further important copyright and licensing information.
  9.  * 
  10.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  11.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
  13.  * OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
  14.  * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
  15.  * ITS DERIVATIVES.
  16.  */
  17.  
  18. package java.io;
  19. import java.io.InputStream;
  20.  
  21. /**
  22.  * A class to turn an input stream into a stream of tokens.
  23.  * There are a number of methods that define the lexical
  24.  * syntax of tokens.
  25.  * @author  James Gosling
  26.  */
  27. public
  28. class StreamTokenizer {
  29.     private InputStream input;
  30.     private char buf[];
  31.     private int peekc = ' ';
  32.     private boolean pushedBack;
  33.     private boolean forceLower;
  34.     /** The line number of the last token read */
  35.     public int lineno = 1;
  36.  
  37.  
  38.     /** Set to true if end-of-lines are significant (TT_EOL will
  39.     be returned by nexttoken).  If false, they will be treated
  40.     as whitespace */
  41.     public boolean eolIsSignificant = false;
  42.     /** Set to true to recognize C++ style // comments */
  43.     public boolean slashSlashComments = false;
  44.     /** Set to true to recognize C style /* comments */
  45.     public boolean slashStarComments = false;
  46.  
  47.     /** If true, '#' starts a single line comment.  This is
  48.     here solely for compatibility with 1.0a1.  Use
  49.     commentChar('#') instead. */
  50.     public boolean hashComments = false;
  51.  
  52.     private byte ctype[] = new byte[256];
  53.     private static final byte CT_WHITESPACE = 1;
  54.     private static final byte CT_DIGIT = 2;
  55.     private static final byte CT_ALPHA = 4;
  56.     private static final byte CT_QUOTE = 8;
  57.     private static final byte CT_COMMENT = 16;
  58.  
  59.     /** The type of the last token returned.  It's value will either
  60.     be one of the following TT_* constants, or a single
  61.     character.  For example, if '+' is encountered and is
  62.     not a valid word character, ttype will be '+' */
  63.     public int ttype;
  64.     /** End of file token */
  65.     public static final int TT_EOF = -1;
  66.     /** End of line token */
  67.     public static final int TT_EOL = '\n';
  68.     /** Number token.  The value is in nval */
  69.     public static final int TT_NUMBER = -2;
  70.     /** Word token.  The value is in sval */
  71.     public static final int TT_WORD = -3;
  72.     public String sval;
  73.     public double nval;
  74.  
  75.     /** Create a stream tokenizer that parses the given input stream.
  76.     By default, it recognizes numbers, all the alphabetics are
  77.     valid word characters, and strings quoted with single and
  78.     double quote. */
  79.     public StreamTokenizer (InputStream I) {
  80.     input = I;
  81.     buf = new char[20];
  82.     byte ct[] = ctype;
  83.     int i;
  84.     wordChars('a', 'z');
  85.     wordChars('A', 'Z');
  86.     wordChars(128 + 32, 255);
  87.     whitespaceChars(0, ' ');
  88.     commentChar('/');
  89.     quoteChar('"');
  90.     quoteChar('\'');
  91.     parseNumbers();
  92.     }
  93.  
  94.     /** Reset the syntax table so that all characters are special */
  95.     public void resetSyntax() {
  96.     for (int i = ctype.length; --i >= 0;)
  97.         ctype[i] = 0;
  98.     }
  99.  
  100.     /** Specify that characters in this range are word characters */
  101.     public void wordChars(int low, int hi) {
  102.     if (low < 0)
  103.         low = 0;
  104.     if (hi > ctype.length)
  105.         hi = ctype.length;
  106.     while (low <= hi)
  107.         ctype[low++] |= CT_ALPHA;
  108.     }
  109.  
  110.     /** Specify that characters in this range are whitespace characters */
  111.     public void whitespaceChars(int low, int hi) {
  112.     if (low < 0)
  113.         low = 0;
  114.     if (hi > ctype.length)
  115.         hi = ctype.length;
  116.     while (low <= hi)
  117.         ctype[low++] = CT_WHITESPACE;
  118.     }
  119.  
  120.     /** Specify that characters in this range are 'ordinary': it removes any
  121.     significance as a word, comment, string, whitespace or number
  122.     character.  When encountered by the parser, they return a ttype
  123.     equal to the character. */
  124.     public void ordinaryChars(int low, int hi) {
  125.     if (low < 0)
  126.         low = 0;
  127.     if (hi > ctype.length)
  128.         hi = ctype.length;
  129.     while (low <= hi)
  130.         ctype[low++] = 0;
  131.     }
  132.  
  133.     /** Specify that this character is  'ordinary': it removes any
  134.     significance as a word, comment, string, whitespace or number
  135.     character.  When encountered by the parser, it returns a ttype
  136.     equal to the character. */
  137.     public void ordinaryChar(int ch) {
  138.     ctype[ch] = 0;
  139.     }
  140.  
  141.     /** Specify that this character starts a single line comment. */
  142.     public void commentChar(int ch) {
  143.     ctype[ch] = CT_COMMENT;
  144.     }
  145.  
  146.     /** Specify that matching pairs of this character delimit string
  147.     constants.  When a string constant is recognized ttype will be
  148.     the character that delimits the string, and sval will have
  149.     the body of the string. */
  150.     public void quoteChar(int ch) {
  151.     ctype[ch] = CT_QUOTE;
  152.     }
  153.  
  154.     /** Specify that numbers should be parsed.  It accepts double precision
  155.     floating point numbers and returns a ttype of TT_NUMBER with the
  156.     value in nval. */
  157.     public void parseNumbers() {
  158.     for (int i = '0'; i <= '9'; i++)
  159.         ctype[i] |= CT_DIGIT;
  160.     ctype['.'] |= CT_DIGIT;
  161.     ctype['-'] |= CT_DIGIT;
  162.     }
  163.  
  164.     /** When true TT_WORD tokens are forced to be lower case */
  165.     public void lowerCaseMode(boolean fl) {
  166.     forceLower = fl;
  167.     }
  168.  
  169.     /** Parse a token from the input stream.  The return value is
  170.     the same as the value of ttype.  Typical clients of this
  171.     class first set up the syntax tables and then sit in a loop
  172.     calling nextToken to parse successive tokens until TT_EOF
  173.     is returned. */
  174.     public int nextToken() {
  175.     if (pushedBack) {
  176.         pushedBack = false;
  177.         return ttype;
  178.     }
  179.     InputStream is = input;
  180.     byte ct[] = ctype;
  181.     int c = peekc;
  182.     sval = null;
  183.  
  184.     // XXX: this 'if' statement is here for alpha1.0 compatibility
  185.     // only and should be removed post-alpha2.
  186.     if (hashComments) {
  187.         hashComments = false;
  188.         commentChar('#');
  189.     }
  190.     if (c < 0)
  191.         return ttype = TT_EOF;
  192.     int ctype = c < 256 ? ct[c] : CT_ALPHA;
  193.     while ((ctype & CT_WHITESPACE) != 0) {
  194.         if (c == '\r') {
  195.         lineno++;
  196.         c = is.read();
  197.         if (c == '\n')
  198.             c = is.read();
  199.         if (eolIsSignificant) {
  200.             peekc = c;
  201.             return ttype = TT_EOL;
  202.         }
  203.         } else {
  204.         if (c == '\n') {
  205.             lineno++;
  206.             if (eolIsSignificant) {
  207.             peekc = ' ';
  208.             return ttype = TT_EOL;
  209.             }
  210.         }
  211.         c = is.read();
  212.         }
  213.         if (c < 0)
  214.         return ttype = TT_EOF;
  215.         ctype = c < 256 ? ct[c] : CT_ALPHA;
  216.     }
  217.     if ((ctype & CT_DIGIT) != 0) {
  218.         boolean neg = false;
  219.         if (c == '-') {
  220.         c = is.read();
  221.         if (c != '.' && (c < '0' || c > '9')) {
  222.             peekc = c;
  223.             return ttype = '-';
  224.         }
  225.         neg = true;
  226.         }
  227.         double v = 0;
  228.         int decexp = 0;
  229.         int seendot = 0;
  230.         while (true) {
  231.         if (c == '.' && seendot == 0)
  232.             seendot = 1;
  233.         else if ('0' <= c && c <= '9') {
  234.             v = v * 10 + (c - '0');
  235.             decexp += seendot;
  236.         } else
  237.             break;
  238.         c = is.read();
  239.         }
  240.         peekc = c;
  241.         if (decexp != 0) {
  242.         double denom = 10;
  243.         decexp--;
  244.         while (decexp > 0) {
  245.             denom *= 10;
  246.             decexp--;
  247.         }
  248.         /* do one division of a likely-to-be-more-accurate number */
  249.         v = v / denom;
  250.         }
  251.         nval = neg ? -v : v;
  252.         return ttype = TT_NUMBER;
  253.     }
  254.     if ((ctype & CT_ALPHA) != 0) {
  255.         int i = 0;
  256.         do {
  257.         if (i >= buf.length) {
  258.             char nb[] = new char[buf.length * 2];
  259.             System.arraycopy(buf, 0, nb, 0, buf.length);
  260.             buf = nb;
  261.         }
  262.         buf[i++] = (char) c;
  263.         c = is.read();
  264.         ctype = c < 0 ? CT_WHITESPACE : c < 256 ? ct[c] : CT_ALPHA;
  265.         } while ((ctype & (CT_ALPHA | CT_DIGIT)) != 0);
  266.         peekc = c;
  267.         sval = String.copyValueOf(buf, 0, i);
  268.         if (forceLower)
  269.         sval = sval.toLowerCase();
  270.         return ttype = TT_WORD;
  271.     }
  272.     if ((ctype & CT_COMMENT) != 0) {
  273.         while ((c = is.read()) != '\n' && c != '\r' && c >= 0);
  274.         peekc = c;
  275.         return nextToken();
  276.     }
  277.     if ((ctype & CT_QUOTE) != 0) {
  278.         ttype = c;
  279.         int i = 0;
  280.         while ((c = is.read()) >= 0 && c != ttype && c != '\n' && c != '\r') {
  281.         if (c == '\\')
  282.             switch (c = is.read()) {
  283.               case 'a':
  284.             c = 0x7;
  285.             break;
  286.               case 'b':
  287.             c = '\b';
  288.             break;
  289.               case 'f':
  290.             c = 0xC;
  291.             break;
  292.               case 'n':
  293.             c = '\n';
  294.             break;
  295.               case 'r':
  296.             c = '\r';
  297.             break;
  298.               case 't':
  299.             c = '\t';
  300.             break;
  301.               case 'v':
  302.             c = 0xB;
  303.             break;
  304.               case '0':
  305.               case '1':
  306.               case '2':
  307.               case '3':
  308.               case '4':
  309.               case '5':
  310.               case '6':
  311.               case '7':
  312.             c = c - '0';
  313.             int c2 = is.read();
  314.             if ('0' <= c2 && c2 <= '7') {
  315.                 c = (c << 3) + (c2 - '0');
  316.                 c2 = is.read();
  317.                 if ('0' <= c2 && c2 <= '7')
  318.                 c = (c << 3) + (c2 - '0');
  319.                 else
  320.                 peekc = c;
  321.             } else
  322.                 peekc = c;
  323.             break;
  324.             }
  325.         if (i >= buf.length) {
  326.             char nb[] = new char[buf.length * 2];
  327.             System.arraycopy(buf, 0, nb, 0, buf.length);
  328.             buf = nb;
  329.         }
  330.         buf[i++] = (char) c;
  331.         }
  332.         peekc = ' ';
  333.         sval = String.copyValueOf(buf, 0, i);
  334.         return ttype;
  335.     }
  336.     if (c == '/' && (slashSlashComments || slashStarComments)) {
  337.         c = is.read();
  338.         if (c == '*' && slashStarComments) {
  339.         int prevc = 0;
  340.         while ((c = is.read()) != '/' || prevc != '*') {
  341.             if (c == '\n')
  342.             lineno++;
  343.             if (c < 0)
  344.             return ttype = TT_EOF;
  345.             prevc = c;
  346.         }
  347.         peekc = ' ';
  348.         return nextToken();
  349.         } else if (c == '/' && slashSlashComments) {
  350.         while ((c = is.read()) != '\n' && c != '\r' && c >= 0);
  351.         peekc = c;
  352.         return nextToken();
  353.         } else {
  354.         peekc = c;
  355.         return ttype = '/';
  356.         }
  357.     }
  358.     peekc = ' ';
  359.     return ttype = c;
  360.     }
  361.  
  362.     public void pushBack() {
  363.     pushedBack = true;
  364.     }
  365.  
  366.     public String toString() {
  367.     String ret;
  368.     switch (ttype) {
  369.       case TT_EOF:
  370.         ret = "EOF";
  371.         break;
  372.       case TT_EOL:
  373.         ret = "EOL";
  374.         break;
  375.       case TT_WORD:
  376.         ret = sval;
  377.         break;
  378.       case TT_NUMBER:
  379.         ret = "n=" + nval;
  380.         break;
  381.       default:{
  382.         char s[] = new char[3];
  383.         s[0] = s[2] = '\'';
  384.         s[1] = (char) ttype;
  385.         ret = new String(s);
  386.         break;
  387.         }
  388.     }
  389.     return "Token[" + ret + "], line " + lineno;
  390.     }
  391. }
  392.