diff --git a/src/com/bytezone/diskbrowser/visicalc/Cell.java b/src/com/bytezone/diskbrowser/visicalc/Cell.java index a84bc4b..f68b6c9 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Cell.java +++ b/src/com/bytezone/diskbrowser/visicalc/Cell.java @@ -2,19 +2,17 @@ package com.bytezone.diskbrowser.visicalc; class Cell implements Comparable, Value { - // private static final Pattern cellContents = - // Pattern.compile ("([-+/*]?)(([A-Z]{1,2}[0-9]{1,3})|([0-9.]+)|(@[^-+/*]+))"); - final Address address; private final Sheet parent; - private String label; private char format = ' '; private char repeatingChar; private String repeat = ""; + private String label; private String expressionText; - private Expression expression; + private Value value; + // private boolean hasValue; public Cell (Sheet parent, Address address) { @@ -44,7 +42,7 @@ class Cell implements Comparable, Value System.out.printf ("Unexpected format [%s]%n", format); } - void doCommand (String command) + void setValue (String command) { switch (command.charAt (0)) { @@ -92,12 +90,6 @@ class Cell implements Comparable, Value expressionText = "11.9"; else if (address.sortValue == 579) expressionText = "D9*G5/(1-((1+G5)^-D4))"; - - } - - boolean hasValue () - { - return expressionText != null; } char getFormat () @@ -105,6 +97,7 @@ class Cell implements Comparable, Value return format; } + // this should be called by Sheet when drawing, so do all formatting here String getText () { if (label != null) @@ -114,20 +107,44 @@ class Cell implements Comparable, Value return "?"; } + @Override + public boolean hasValue () + { + if (label != null || repeatingChar > 0) + return false; + + if (value == null) + createValue (); + return value.hasValue (); + } + + // this should be called when doing calculations @Override public double getValue () { - if (expression == null) + if (value == null) + createValue (); + return value.getValue (); + } + + @Override + public String getError () + { + if (value == null) + createValue (); + return hasValue () ? "" : "@NA"; + } + + private void createValue () + { + if (expressionText == null) { - if (expressionText == null) - { - System.out.printf ("%s null expression text %n", address); - return 0; - } - // System.out.printf ("%s Instantiating [%s]%n", address, expressionText); - expression = new Expression (parent, expressionText); + System.out.printf ("%s null expression text %n", address); + value = Function.getInstance (parent, "@ERROR()"); } - return expression.getValue (); + else + // System.out.printf ("%s Instantiating [%s]%n", address, expressionText); + value = new Expression (parent, expressionText); } @Override diff --git a/src/com/bytezone/diskbrowser/visicalc/Expression.java b/src/com/bytezone/diskbrowser/visicalc/Expression.java index 9303a34..7939650 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Expression.java +++ b/src/com/bytezone/diskbrowser/visicalc/Expression.java @@ -10,9 +10,8 @@ public class Expression implements Value // cell address // function // expression [+-*/^] expression - // [+-=] expression + // [+-] expression // ( expression ) - // -expression // From the reference card: // Expressions are evaluated strictly from left to right except as modified by @@ -33,34 +32,18 @@ public class Expression implements Value private final List operators = new ArrayList (); private final List signs = new ArrayList (); + private boolean hasValue; + public Expression (Sheet parent, String input) { - String line = input.trim (); - - // System.out.printf ("New expression [%s]%n", input); - - int leftBracket = 0; - int rightBracket = 0; - - for (char c : input.toCharArray ()) - if (c == '(') - leftBracket++; - else if (c == ')') - rightBracket++; - - if (leftBracket != rightBracket) - { - System.out.printf ("**** Unbalanced brackets: left:%d, right:%d ****%n", - leftBracket, rightBracket); - line = "@ERROR()"; - } - // System.out.printf ("Exp [%s]%n", line); + String line = checkBrackets (input); + int ptr = 0; while (ptr < line.length ()) { + // check for optional leading + or - char ch = line.charAt (ptr); - if (ch == '-') { signs.add ("(-)"); @@ -73,6 +56,7 @@ public class Expression implements Value ch = line.charAt (++ptr); } + // check for mandatory function/sub-expression/number/cell reference switch (ch) { case '@': // function @@ -84,12 +68,13 @@ public class Expression implements Value case '(': // parentheses block String bracketText = getFunctionText (line.substring (ptr)); ptr += bracketText.length (); - bracketText = bracketText.substring (1, bracketText.length () - 1); - values.add (new Expression (parent, bracketText)); + values.add (new Expression (parent, + bracketText.substring (1, bracketText.length () - 1))); break; case '#': System.out.printf ("Hash character [%s] in [%s]%n", ch, line); + ptr++; // no idea break; default: @@ -97,21 +82,22 @@ public class Expression implements Value { String numberText = getNumberText (line.substring (ptr)); ptr += numberText.length (); - values.add (new Number (Double.parseDouble (numberText))); + values.add (new Number (numberText)); } else if (ch >= 'A' && ch <= 'Z') // cell address { String addressText = getAddressText (line.substring (ptr)); ptr += addressText.length (); - values.add (parent.getCell (new Address (addressText))); + values.add (parent.getCell (addressText)); } else { - System.out.printf ("Unknown character [%s] in [%s]%n", ch, line); + System.out.printf ("Unexpected character [%s] in [%s]%n", ch, line); return; } } + // check for optional continuation operator if (ptr < line.length ()) { ch = line.charAt (ptr); @@ -126,6 +112,7 @@ public class Expression implements Value } assert values.size () > 0; + hasValue = true; if (false) { @@ -177,12 +164,47 @@ public class Expression implements Value return value; } + @Override + public boolean hasValue () + { + return hasValue; + } + + @Override + public String getError () + { + return hasValue ? "" : "Error"; + } + + private String checkBrackets (String input) + { + String line = input.trim (); + + int leftBracket = 0; + int rightBracket = 0; + + for (char c : line.toCharArray ()) + if (c == '(') + leftBracket++; + else if (c == ')') + rightBracket++; + + if (leftBracket != rightBracket) + { + System.out.printf ("**** Unbalanced brackets: left:%d, right:%d ****%n", + leftBracket, rightBracket); + return "@ERROR()"; + } + return line; + } + private String getFunctionText (String text) { int ptr = text.indexOf ('('); // find first left parenthesis if (ptr < 0) return ""; int depth = 1; + while (++ptr < text.length ()) // find matching right parenthesis { if (text.charAt (ptr) == ')') diff --git a/src/com/bytezone/diskbrowser/visicalc/Function.java b/src/com/bytezone/diskbrowser/visicalc/Function.java index 56e64eb..a2f2d8e 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Function.java +++ b/src/com/bytezone/diskbrowser/visicalc/Function.java @@ -32,6 +32,7 @@ abstract class Function implements Value Sheet parent; String functionText; + boolean hasValue; static Function getInstance (Sheet parent, String text) { @@ -78,6 +79,18 @@ abstract class Function implements Value this.functionText = text.substring (pos + 1, text.length () - 1); } + @Override + public boolean hasValue () + { + return hasValue; + } + + @Override + public String getError () + { + return hasValue ? "" : "Error"; + } + protected Range getRange (String text) { Range range = null; diff --git a/src/com/bytezone/diskbrowser/visicalc/Number.java b/src/com/bytezone/diskbrowser/visicalc/Number.java index 35a6daf..839689a 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Number.java +++ b/src/com/bytezone/diskbrowser/visicalc/Number.java @@ -1,12 +1,21 @@ package com.bytezone.diskbrowser.visicalc; -public class Number implements Value +class Number implements Value { - private final double value; + private double value; + private boolean hasValue; - public Number (double value) + public Number (String text) { - this.value = value; + try + { + this.value = Double.parseDouble (text); + hasValue = true; + } + catch (NumberFormatException e) + { + hasValue = false; + } } @Override @@ -20,4 +29,16 @@ public class Number implements Value { return String.format ("Number: %f", value); } + + @Override + public boolean hasValue () + { + return hasValue; + } + + @Override + public String getError () + { + return hasValue ? "" : "@NA"; + } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/visicalc/Sheet.java b/src/com/bytezone/diskbrowser/visicalc/Sheet.java index 96e0dbe..2e6b38a 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Sheet.java +++ b/src/com/bytezone/diskbrowser/visicalc/Sheet.java @@ -309,18 +309,21 @@ public class Sheet implements Iterable if (!command.isEmpty ()) currentCell.format (command); // formatting command if (!line.isEmpty ()) - currentCell.doCommand (line); // expression + currentCell.setValue (line); // expression + } + + Cell getCell (String addressText) + { + Address address = new Address (addressText); + return getCell (address); } Cell getCell (Address address) { Cell cell = sheet.get (address.sortValue); if (cell == null) - { - // cell = new Cell (this, address); - // sheet.put (address.sortValue, cell); System.out.printf ("Nonexistent cell requested [%s]%n", address); - } + return cell; } diff --git a/src/com/bytezone/diskbrowser/visicalc/Value.java b/src/com/bytezone/diskbrowser/visicalc/Value.java index 950a200..8d652d2 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Value.java +++ b/src/com/bytezone/diskbrowser/visicalc/Value.java @@ -2,5 +2,9 @@ package com.bytezone.diskbrowser.visicalc; public interface Value { + public boolean hasValue (); + public double getValue (); + + public String getError (); } \ No newline at end of file