home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / javafile / ch06 / Cell.java < prev    next >
Text File  |  1998-12-14  |  6KB  |  363 lines

  1. import java.awt.*;
  2.  
  3. /*
  4.  * Defines an individual cell
  5.  */
  6. public class Cell {
  7.  
  8. /*
  9.  * Token types returned by Lex()
  10.  */
  11. static final int NUMBER = 1;
  12. static final int EQUALS = 2;
  13. static final int PLUS = 3;
  14. static final int MINUS = 4;
  15. static final int STAR = 5;
  16. static final int SLASH = 6;
  17. static final int TEXT = 7;
  18. static final int EOT = 8;
  19. static final int LEFT = 9;
  20. static final int RIGHT = 10;
  21. static final int UNKN = 11;
  22. static final int FORMULA = 12;
  23. static final int REFERENCE = 13; 
  24.  
  25. /*
  26.  * What is in this cell
  27.  */
  28. int type;
  29.  
  30. /*
  31.  * The numeric value, if this cell is numeric
  32.  */
  33. double value;
  34.  
  35. /*
  36.  * Numeric value for this token
  37.  */
  38. double lexValue;
  39.  
  40. /*
  41.  * Index into input string (used for parsing)
  42.  */
  43. int lexIndex;
  44.  
  45. /*
  46.  * Token value returned from Lex()
  47.  */
  48. int token;
  49.  
  50. /*
  51.  * The text contents of this cell
  52.  */
  53. String text;
  54. int textLength;
  55. int textIndex; 
  56.  
  57. /*
  58.  * Reference to all cells in spreadsheet
  59.  */
  60. Cell cells[][];
  61.  
  62. /*
  63.  * Error flag, set if parse error detected
  64.  */
  65. boolean error;
  66.  
  67. /*
  68.  * Used to force rereading of tokens
  69.  */
  70. boolean lexFlag;
  71.  
  72. /*
  73.  * Number of rows and columns in the spreadsheet
  74.  * Used for bounds checking
  75.  */
  76. int cols;
  77. int rows;
  78.  
  79. public Cell (Cell cs[][], int r, int c) {
  80.  
  81.     cells = cs;
  82.     rows = r;
  83.     cols = c;
  84.     text = "";
  85.     lexFlag = true;
  86.     type = UNKN;
  87. }
  88.  
  89. /*
  90.  * Called to get the numeric value of this cell
  91.  */
  92. double evaluate () {
  93.  
  94.     resetLex ();
  95.     error = false;
  96.     switch (type) {
  97.         case FORMULA:
  98.         Lex ();
  99.         value = Level1 ();
  100.         if (error) return 0;
  101.         return value;
  102.  
  103.         case NUMBER:
  104.         value = lexValue;
  105.         return value;
  106.  
  107.         case UNKN:
  108.         return 0;
  109.     }
  110.     error = true;
  111.     return 0;
  112. }
  113.  
  114. /*
  115.  * Returns the string representation of the value
  116.  */
  117. String evalToString () {
  118.  
  119.     String s;
  120.  
  121.     if (type == TEXT || type == UNKN) return text;
  122.     s = String.valueOf (value);
  123.     if (error) return "Error";
  124.     else return s;
  125. }
  126.  
  127. /*
  128.  * Called to enter a string into this cell
  129.  */
  130. void enter (String s) {
  131.  
  132.     text = s;
  133.     textLength = text.length ();
  134.     resetLex ();
  135.     error = false;
  136.     switch (Lex ()) {
  137.         case EQUALS:
  138.         type = FORMULA;
  139.         break;
  140.  
  141.         case NUMBER:
  142.         type = NUMBER;
  143.         value = lexValue;
  144.         break;
  145.  
  146.         default:
  147.         type = TEXT;
  148.         break; 
  149.     }
  150. }
  151.  
  152. /*
  153.  * Top level of the recursive descent parser
  154.  * Handle plus and minus.
  155.  */
  156. double Level1 () {
  157.  
  158.     boolean ok;
  159.     double x1, x2;
  160.  
  161.     x1 = Level2 ();
  162.     if (error) return 0; 
  163.  
  164.     ok = true;
  165.     while (ok) switch (Lex ()) {
  166.         case PLUS:
  167.         x2 = Level2 ();
  168.         if (error) return 0;
  169.         x1 += x2;
  170.         break;
  171.  
  172.         case MINUS:
  173.         x2 = Level2 ();
  174.         if (error) return 0;
  175.         x1 -= x2;
  176.         break;
  177.  
  178.         default:
  179.         Unlex ();
  180.         ok = false;
  181.         break;
  182.     }
  183.     return x1;
  184. }
  185.  
  186. /*
  187.  * Handle multiply and divide. 
  188.  */
  189. double Level2 () {
  190.  
  191.     boolean ok;
  192.     double x1, x2;
  193.  
  194.     x1 = Level3 ();
  195.     if (error) return 0;
  196.  
  197.     ok = true;
  198.     while (ok) switch (Lex ()) {
  199.         case STAR:
  200.         x2 = Level3 ();
  201.         if (error) return 0;
  202.         x1 *= x2;
  203.         break;
  204.  
  205.         case SLASH:
  206.         x2 = Level3 ();
  207.         if (error) return 0;
  208.         x1 /= x2;
  209.         break;
  210.  
  211.         default:
  212.         Unlex ();
  213.         ok = false;
  214.         break;
  215.     }
  216.     return x1; 
  217. }
  218.  
  219. /*
  220. Handle unary minus, parentheses, constants, and cell references
  221.  */
  222. double Level3 () {
  223.  
  224.     double x1, x2;
  225.  
  226.     switch (Lex ()) {
  227.         case MINUS:
  228.         x2 = Level1 ();
  229.         if (error) return 0; 
  230.         return -x2;
  231.  
  232.         case LEFT:
  233.         x2 = Level1 ();
  234.         if (error) return 0;
  235.         if (Lex () != RIGHT) {
  236.             error = true;
  237.             return 0;
  238.         }
  239.         return x2;
  240.  
  241.         case NUMBER:
  242.         case REFERENCE:
  243.         return lexValue;
  244.     }
  245.     error = true;
  246.     return 0;
  247. }
  248.  
  249. /*
  250.  * Reset the lexical analyzer.
  251.  */
  252. void resetLex () {
  253.  
  254.     lexIndex = 0;
  255.     lexFlag = true;
  256. }
  257.  
  258. /*
  259.  * Push a token back for rereading. 
  260.  */
  261. void Unlex () {
  262.  
  263.     lexFlag = false;
  264. }
  265.  
  266. /*
  267.  * Returns the next token
  268.  */
  269. int Lex () {
  270.  
  271.     if (lexFlag) {
  272.         token = lowlevelLex ();
  273.     }
  274.     lexFlag = true;
  275.     return token;
  276. }
  277.  
  278. /*
  279.  * Returns the next token in the text string
  280.  */
  281. int lowlevelLex () {
  282.  
  283.     char c;
  284.     String s; 
  285.  
  286.     do {
  287.         if (lexIndex >= textLength) return EOT;
  288.         c = text.charAt (lexIndex++);
  289.     } while (c == ' ');
  290.     switch (c) {
  291.         case '=':
  292.         return EQUALS;
  293.  
  294.         case '+':
  295.         return PLUS;
  296.  
  297.         case '-':
  298.         return MINUS; 
  299.  
  300.         case '*':
  301.         return STAR;
  302.  
  303.         case '/':
  304.         return SLASH;
  305.  
  306.         case '(':
  307.         return LEFT;
  308.  
  309.         case ')':
  310.         return RIGHT;
  311.     }
  312.  
  313.     if (c >= '0' && c <= '9') {
  314.         s = "";
  315.         while ((c >= '0' && c <= '9') || c == '.' ||
  316.             c == '-' || c == 'e' || c == 'E') {
  317.             s += c;
  318.             if (lexIndex >= textLength) break;
  319.             c = text.charAt (lexIndex++);
  320.         }
  321.         lexIndex -= 1;
  322.         try {
  323.             lexValue = Double.valueOf (s).doubleValue();
  324.         } catch (NumberFormatException e) {
  325.             System.out.println (e);
  326.             error = true;
  327.             return UNKN;
  328.         }
  329.         return NUMBER; 
  330.     }
  331.     if (c >= 'a' && c <= 'z') {
  332.         int col = c - 'a';
  333.         int row;
  334.         s = "";
  335.         if (lexIndex >= textLength) {
  336.             error = true;
  337.             return UNKN;
  338.         }
  339.         c = text.charAt (lexIndex++);
  340.         while (c >= '0' && c <= '9') {
  341.             s += c;
  342.             if (lexIndex >= textLength) break;
  343.             c = text.charAt (lexIndex++);
  344.         }
  345.         lexIndex -= 1;
  346.         try {
  347.             row = Integer.valueOf (s).intValue() - 1;
  348.         } catch (NumberFormatException e) {
  349.             error = true;
  350.             return UNKN;
  351.         }
  352.         if (row >= rows || col >= cols) {
  353.             error = true;
  354.             return REFERENCE; 
  355.         }
  356.         lexValue = cells[row][col].evaluate();
  357.         if (cells[row][col].error) error = true;
  358.         return REFERENCE;
  359.     }
  360.     return TEXT;
  361. }
  362. }
  363.