home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / sybase / starbuck / java.z / StreamTokenizer.java < prev    next >
Text File  |  1996-05-03  |  11KB  |  469 lines

  1. /*
  2.  * @(#)StreamTokenizer.java    1.10 95/08/15
  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.  * @version 1.10, 15 Aug 1995
  26.  * @author  James Gosling
  27.  */
  28. public
  29. class StreamTokenizer {
  30.     private InputStream input;
  31.     private char buf[];
  32.     private int peekc = ' ';
  33.     private boolean pushedBack;
  34.     private boolean forceLower;
  35.     /** The line number of the last token read */
  36.     private int LINENO = 1;
  37.  
  38.     private boolean eolIsSignificantP = false;
  39.     private boolean slashSlashCommentsP = false;
  40.     private boolean slashStarCommentsP = false;
  41.  
  42.  
  43.     private byte ctype[] = new byte[256];
  44.     private static final byte CT_WHITESPACE = 1;
  45.     private static final byte CT_DIGIT = 2;
  46.     private static final byte CT_ALPHA = 4;
  47.     private static final byte CT_QUOTE = 8;
  48.     private static final byte CT_COMMENT = 16;
  49.  
  50.     /** 
  51.      * The type of the last token returned.  It's value will either
  52.      * be one of the following TT_* constants, or a single
  53.      * character.  For example, if '+' is encountered and is
  54.      * not a valid word character, ttype will be '+' 
  55.      */
  56.     public int ttype;
  57.  
  58.     /** 
  59.      * The End-of-file token. 
  60.      */
  61.     public static final int TT_EOF = -1;
  62.  
  63.     /** 
  64.      * The End-of-line token. 
  65.      */
  66.     public static final int TT_EOL = '\n';
  67.  
  68.     /** 
  69.      * The number token.  This value is in nval. 
  70.      */
  71.     public static final int TT_NUMBER = -2;
  72.  
  73.     /** 
  74.      * The word token.  This value is in sval. 
  75.      */
  76.     public static final int TT_WORD = -3;
  77.  
  78.     /**
  79.      * The Stream value.
  80.      */
  81.     public String sval;
  82.  
  83.     /**
  84.      * The number value.
  85.      */
  86.     public double nval;
  87.  
  88.     /** 
  89.      * Creates a stream tokenizer that parses the specified input
  90.      * stream.
  91.      * By default, it recognizes numbers, Strings quoted with 
  92.      * single and double quotes, and all the alphabetics.
  93.      * @param I the input stream 
  94.      */
  95.     public StreamTokenizer (InputStream I) {
  96.     input = I;
  97.     buf = new char[20];
  98.     byte ct[] = ctype;
  99.     int i;
  100.     wordChars('a', 'z');
  101.     wordChars('A', 'Z');
  102.     wordChars(128 + 32, 255);
  103.     whitespaceChars(0, ' ');
  104.     commentChar('/');
  105.     quoteChar('"');
  106.     quoteChar('\'');
  107.     parseNumbers();
  108.     }
  109.  
  110.     /** 
  111.      * Resets the syntax table so that all characters are special. 
  112.      */
  113.     public void resetSyntax() {
  114.     for (int i = ctype.length; --i >= 0;)
  115.         ctype[i] = 0;
  116.     }
  117.  
  118.     /** 
  119.      * Specifies that characters in this range are word characters.
  120.      * @param low the low end of the range
  121.      * @param hi the high end of the range 
  122.      */
  123.     public void wordChars(int low, int hi) {
  124.     if (low < 0)
  125.         low = 0;
  126.     if (hi > ctype.length)
  127.         hi = ctype.length;
  128.     while (low <= hi)
  129.         ctype[low++] |= CT_ALPHA;
  130.     }
  131.  
  132.     /** 
  133.      * Specifies that characters in this range are whitespace 
  134.      * characters.
  135.      * @param low the low end of the range
  136.      * @param hi the high end of the range 
  137.      */
  138.     public void whitespaceChars(int low, int hi) {
  139.     if (low < 0)
  140.         low = 0;
  141.     if (hi > ctype.length)
  142.         hi = ctype.length;
  143.     while (low <= hi)
  144.         ctype[low++] = CT_WHITESPACE;
  145.     }
  146.  
  147.     /** 
  148.      * Specifies that characters in this range are 'ordinary'.
  149.      * Ordinary characters mean that any significance as words, 
  150.      * comments, strings, whitespaces or number characters are removed.
  151.      * When these characters are encountered by the 
  152.      * parser, they return a ttype equal to the character.
  153.      * @param low the low end of the range
  154.      * @param hi the high end of the range 
  155.      */
  156.     public void ordinaryChars(int low, int hi) {
  157.     if (low < 0)
  158.         low = 0;
  159.     if (hi > ctype.length)
  160.         hi = ctype.length;
  161.     while (low <= hi)
  162.         ctype[low++] = 0;
  163.     }
  164.  
  165.     /** 
  166.      * Specifies that this character is 'ordinary': it removes any
  167.      * significance as a word, comment, string, whitespace or number
  168.      * character.  When encountered by the parser, it returns a ttype
  169.      * equal to the character. 
  170.      * @param ch the character
  171.      */
  172.     public void ordinaryChar(int ch) {
  173.     ctype[ch] = 0;
  174.     }
  175.  
  176.     /** 
  177.      * Specifies that this character starts a single line comment.
  178.      * @param ch the character 
  179.      */
  180.     public void commentChar(int ch) {
  181.     ctype[ch] = CT_COMMENT;
  182.     }
  183.  
  184.     /** 
  185.      * Specifies that matching pairs of this character delimit String
  186.      * constants.  When a String constant is recognized, ttype will be
  187.      * the character that delimits the String, and sval will have
  188.      * the body of the String.
  189.      * @param ch the character 
  190.      */
  191.     public void quoteChar(int ch) {
  192.     ctype[ch] = CT_QUOTE;
  193.     }
  194.  
  195.     /** 
  196.      * Specifies that numbers should be parsed.  This method accepts 
  197.      * double precision floating point numbers and returns a ttype of 
  198.      * TT_NUMBER with the value in nval. 
  199.      */
  200.     public void parseNumbers() {
  201.     for (int i = '0'; i <= '9'; i++)
  202.         ctype[i] |= CT_DIGIT;
  203.     ctype['.'] |= CT_DIGIT;
  204.     ctype['-'] |= CT_DIGIT;
  205.     }
  206.  
  207.     /**
  208.      * If the flag is true, end-of-lines are significant (TT_EOL will
  209.      * be returned by nexttoken).  If false, they will be treated
  210.      * as whitespace. 
  211.      */
  212.     public void eolIsSignificant(boolean flag) {
  213.     eolIsSignificantP = flag;
  214.     }
  215.  
  216.     /** 
  217.      * If the flag is true, recognize C style( /* ) comments. 
  218.      */
  219.     public void slashStarComments(boolean flag) {
  220.     slashStarCommentsP = flag;
  221.     }
  222.  
  223.     /** 
  224.      * If the flag is true, recognize C++ style( // ) comments. 
  225.      */
  226.     public void slashSlashComments(boolean flag) {
  227.     slashSlashCommentsP = flag;
  228.     }
  229.  
  230.     /**
  231.      * Examines a boolean to decide whether TT_WORD tokens are
  232.      * forced to be lower case.
  233.      * @param fl the boolean flag  
  234.      */
  235.     public void lowerCaseMode(boolean fl) {
  236.     forceLower = fl;
  237.     }
  238.  
  239.     /** 
  240.      * Parses a token from the input stream.  The return value is
  241.      * the same as the value of ttype.  Typical clients of this
  242.      * class first set up the syntax tables and then sit in a loop
  243.      * calling nextToken to parse successive tokens until TT_EOF
  244.      * is returned. 
  245.      */
  246.     public int nextToken() throws IOException {
  247.     if (pushedBack) {
  248.         pushedBack = false;
  249.         return ttype;
  250.     }
  251.     InputStream is = input;
  252.     byte ct[] = ctype;
  253.     int c = peekc;
  254.     sval = null;
  255.  
  256.     if (c < 0)
  257.         return ttype = TT_EOF;
  258.     int ctype = c < 256 ? ct[c] : CT_ALPHA;
  259.     while ((ctype & CT_WHITESPACE) != 0) {
  260.         if (c == '\r') {
  261.         LINENO++;
  262.         c = is.read();
  263.         if (c == '\n')
  264.             c = is.read();
  265.         if (eolIsSignificantP) {
  266.             peekc = c;
  267.             return ttype = TT_EOL;
  268.         }
  269.         } else {
  270.         if (c == '\n') {
  271.             LINENO++;
  272.             if (eolIsSignificantP) {
  273.             peekc = ' ';
  274.             return ttype = TT_EOL;
  275.             }
  276.         }
  277.         c = is.read();
  278.         }
  279.         if (c < 0)
  280.         return ttype = TT_EOF;
  281.         ctype = c < 256 ? ct[c] : CT_ALPHA;
  282.     }
  283.     if ((ctype & CT_DIGIT) != 0) {
  284.         boolean neg = false;
  285.         if (c == '-') {
  286.         c = is.read();
  287.         if (c != '.' && (c < '0' || c > '9')) {
  288.             peekc = c;
  289.             return ttype = '-';
  290.         }
  291.         neg = true;
  292.         }
  293.         double v = 0;
  294.         int decexp = 0;
  295.         int seendot = 0;
  296.         while (true) {
  297.         if (c == '.' && seendot == 0)
  298.             seendot = 1;
  299.         else if ('0' <= c && c <= '9') {
  300.             v = v * 10 + (c - '0');
  301.             decexp += seendot;
  302.         } else
  303.             break;
  304.         c = is.read();
  305.         }
  306.         peekc = c;
  307.         if (decexp != 0) {
  308.         double denom = 10;
  309.         decexp--;
  310.         while (decexp > 0) {
  311.             denom *= 10;
  312.             decexp--;
  313.         }
  314.         /* do one division of a likely-to-be-more-accurate number */
  315.         v = v / denom;
  316.         }
  317.         nval = neg ? -v : v;
  318.         return ttype = TT_NUMBER;
  319.     }
  320.     if ((ctype & CT_ALPHA) != 0) {
  321.         int i = 0;
  322.         do {
  323.         if (i >= buf.length) {
  324.             char nb[] = new char[buf.length * 2];
  325.             System.arraycopy(buf, 0, nb, 0, buf.length);
  326.             buf = nb;
  327.         }
  328.         buf[i++] = (char) c;
  329.         c = is.read();
  330.         ctype = c < 0 ? CT_WHITESPACE : c < 256 ? ct[c] : CT_ALPHA;
  331.         } while ((ctype & (CT_ALPHA | CT_DIGIT)) != 0);
  332.         peekc = c;
  333.         sval = String.copyValueOf(buf, 0, i);
  334.         if (forceLower)
  335.         sval = sval.toLowerCase();
  336.         return ttype = TT_WORD;
  337.     }
  338.     if ((ctype & CT_COMMENT) != 0) {
  339.         while ((c = is.read()) != '\n' && c != '\r' && c >= 0);
  340.         peekc = c;
  341.         return nextToken();
  342.     }
  343.     if ((ctype & CT_QUOTE) != 0) {
  344.         ttype = c;
  345.         int i = 0;
  346.         while ((c = is.read()) >= 0 && c != ttype && c != '\n' && c != '\r') {
  347.         if (c == '\\')
  348.             switch (c = is.read()) {
  349.               case 'a':
  350.             c = 0x7;
  351.             break;
  352.               case 'b':
  353.             c = '\b';
  354.             break;
  355.               case 'f':
  356.             c = 0xC;
  357.             break;
  358.               case 'n':
  359.             c = '\n';
  360.             break;
  361.               case 'r':
  362.             c = '\r';
  363.             break;
  364.               case 't':
  365.             c = '\t';
  366.             break;
  367.               case 'v':
  368.             c = 0xB;
  369.             break;
  370.               case '0':
  371.               case '1':
  372.               case '2':
  373.               case '3':
  374.               case '4':
  375.               case '5':
  376.               case '6':
  377.               case '7':
  378.             c = c - '0';
  379.             int c2 = is.read();
  380.             if ('0' <= c2 && c2 <= '7') {
  381.                 c = (c << 3) + (c2 - '0');
  382.                 c2 = is.read();
  383.                 if ('0' <= c2 && c2 <= '7')
  384.                 c = (c << 3) + (c2 - '0');
  385.                 else
  386.                 peekc = c;
  387.             } else
  388.                 peekc = c;
  389.             break;
  390.             }
  391.         if (i >= buf.length) {
  392.             char nb[] = new char[buf.length * 2];
  393.             System.arraycopy(buf, 0, nb, 0, buf.length);
  394.             buf = nb;
  395.         }
  396.         buf[i++] = (char) c;
  397.         }
  398.         peekc = ' ';
  399.         sval = String.copyValueOf(buf, 0, i);
  400.         return ttype;
  401.     }
  402.     if (c == '/' && (slashSlashCommentsP || slashStarCommentsP)) {
  403.         c = is.read();
  404.         if (c == '*' && slashStarCommentsP) {
  405.         int prevc = 0;
  406.         while ((c = is.read()) != '/' || prevc != '*') {
  407.             if (c == '\n')
  408.             LINENO++;
  409.             if (c < 0)
  410.             return ttype = TT_EOF;
  411.             prevc = c;
  412.         }
  413.         peekc = ' ';
  414.         return nextToken();
  415.         } else if (c == '/' && slashSlashCommentsP) {
  416.         while ((c = is.read()) != '\n' && c != '\r' && c >= 0);
  417.         peekc = c;
  418.         return nextToken();
  419.         } else {
  420.         peekc = c;
  421.         return ttype = '/';
  422.         }
  423.     }
  424.     peekc = ' ';
  425.     return ttype = c;
  426.     }
  427.  
  428.     /**
  429.      * Pushes back a stream token.
  430.      */
  431.     public void pushBack() {
  432.     pushedBack = true;
  433.     }
  434.  
  435.     /** Return the current line number. */
  436.     public int lineno() {
  437.     return LINENO;
  438.     }
  439.  
  440.     /**
  441.      * Returns the String representation of the stream token.
  442.      */
  443.     public String toString() {
  444.     String ret;
  445.     switch (ttype) {
  446.       case TT_EOF:
  447.         ret = "EOF";
  448.         break;
  449.       case TT_EOL:
  450.         ret = "EOL";
  451.         break;
  452.       case TT_WORD:
  453.         ret = sval;
  454.         break;
  455.       case TT_NUMBER:
  456.         ret = "n=" + nval;
  457.         break;
  458.       default:{
  459.         char s[] = new char[3];
  460.         s[0] = s[2] = '\'';
  461.         s[1] = (char) ttype;
  462.         ret = new String(s);
  463.         break;
  464.         }
  465.     }
  466.     return "Token[" + ret + "], line " + LINENO;
  467.     }
  468. }
  469.