expanded Value interface

This commit is contained in:
Denis Molony 2016-03-12 08:56:02 +11:00
parent ba5ba04ddc
commit 9db35ede39
6 changed files with 138 additions and 58 deletions

View File

@ -2,19 +2,17 @@ package com.bytezone.diskbrowser.visicalc;
class Cell implements Comparable<Cell>, Value class Cell implements Comparable<Cell>, Value
{ {
// private static final Pattern cellContents =
// Pattern.compile ("([-+/*]?)(([A-Z]{1,2}[0-9]{1,3})|([0-9.]+)|(@[^-+/*]+))");
final Address address; final Address address;
private final Sheet parent; private final Sheet parent;
private String label;
private char format = ' '; private char format = ' ';
private char repeatingChar; private char repeatingChar;
private String repeat = ""; private String repeat = "";
private String label;
private String expressionText; private String expressionText;
private Expression expression; private Value value;
// private boolean hasValue;
public Cell (Sheet parent, Address address) public Cell (Sheet parent, Address address)
{ {
@ -44,7 +42,7 @@ class Cell implements Comparable<Cell>, Value
System.out.printf ("Unexpected format [%s]%n", format); System.out.printf ("Unexpected format [%s]%n", format);
} }
void doCommand (String command) void setValue (String command)
{ {
switch (command.charAt (0)) switch (command.charAt (0))
{ {
@ -92,12 +90,6 @@ class Cell implements Comparable<Cell>, Value
expressionText = "11.9"; expressionText = "11.9";
else if (address.sortValue == 579) else if (address.sortValue == 579)
expressionText = "D9*G5/(1-((1+G5)^-D4))"; expressionText = "D9*G5/(1-((1+G5)^-D4))";
}
boolean hasValue ()
{
return expressionText != null;
} }
char getFormat () char getFormat ()
@ -105,6 +97,7 @@ class Cell implements Comparable<Cell>, Value
return format; return format;
} }
// this should be called by Sheet when drawing, so do all formatting here
String getText () String getText ()
{ {
if (label != null) if (label != null)
@ -114,20 +107,44 @@ class Cell implements Comparable<Cell>, Value
return "?"; 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 @Override
public double getValue () 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);
{ value = Function.getInstance (parent, "@ERROR()");
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);
} }
return expression.getValue (); else
// System.out.printf ("%s Instantiating [%s]%n", address, expressionText);
value = new Expression (parent, expressionText);
} }
@Override @Override

View File

@ -10,9 +10,8 @@ public class Expression implements Value
// cell address // cell address
// function // function
// expression [+-*/^] expression // expression [+-*/^] expression
// [+-=] expression // [+-] expression
// ( expression ) // ( expression )
// -expression
// From the reference card: // From the reference card:
// Expressions are evaluated strictly from left to right except as modified by // Expressions are evaluated strictly from left to right except as modified by
@ -33,34 +32,18 @@ public class Expression implements Value
private final List<String> operators = new ArrayList<String> (); private final List<String> operators = new ArrayList<String> ();
private final List<String> signs = new ArrayList<String> (); private final List<String> signs = new ArrayList<String> ();
private boolean hasValue;
public Expression (Sheet parent, String input) 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); // System.out.printf ("Exp [%s]%n", line);
String line = checkBrackets (input);
int ptr = 0; int ptr = 0;
while (ptr < line.length ()) while (ptr < line.length ())
{ {
// check for optional leading + or -
char ch = line.charAt (ptr); char ch = line.charAt (ptr);
if (ch == '-') if (ch == '-')
{ {
signs.add ("(-)"); signs.add ("(-)");
@ -73,6 +56,7 @@ public class Expression implements Value
ch = line.charAt (++ptr); ch = line.charAt (++ptr);
} }
// check for mandatory function/sub-expression/number/cell reference
switch (ch) switch (ch)
{ {
case '@': // function case '@': // function
@ -84,12 +68,13 @@ public class Expression implements Value
case '(': // parentheses block case '(': // parentheses block
String bracketText = getFunctionText (line.substring (ptr)); String bracketText = getFunctionText (line.substring (ptr));
ptr += bracketText.length (); ptr += bracketText.length ();
bracketText = bracketText.substring (1, bracketText.length () - 1); values.add (new Expression (parent,
values.add (new Expression (parent, bracketText)); bracketText.substring (1, bracketText.length () - 1)));
break; break;
case '#': case '#':
System.out.printf ("Hash character [%s] in [%s]%n", ch, line); System.out.printf ("Hash character [%s] in [%s]%n", ch, line);
ptr++; // no idea
break; break;
default: default:
@ -97,21 +82,22 @@ public class Expression implements Value
{ {
String numberText = getNumberText (line.substring (ptr)); String numberText = getNumberText (line.substring (ptr));
ptr += numberText.length (); ptr += numberText.length ();
values.add (new Number (Double.parseDouble (numberText))); values.add (new Number (numberText));
} }
else if (ch >= 'A' && ch <= 'Z') // cell address else if (ch >= 'A' && ch <= 'Z') // cell address
{ {
String addressText = getAddressText (line.substring (ptr)); String addressText = getAddressText (line.substring (ptr));
ptr += addressText.length (); ptr += addressText.length ();
values.add (parent.getCell (new Address (addressText))); values.add (parent.getCell (addressText));
} }
else else
{ {
System.out.printf ("Unknown character [%s] in [%s]%n", ch, line); System.out.printf ("Unexpected character [%s] in [%s]%n", ch, line);
return; return;
} }
} }
// check for optional continuation operator
if (ptr < line.length ()) if (ptr < line.length ())
{ {
ch = line.charAt (ptr); ch = line.charAt (ptr);
@ -126,6 +112,7 @@ public class Expression implements Value
} }
assert values.size () > 0; assert values.size () > 0;
hasValue = true;
if (false) if (false)
{ {
@ -177,12 +164,47 @@ public class Expression implements Value
return 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) private String getFunctionText (String text)
{ {
int ptr = text.indexOf ('('); // find first left parenthesis int ptr = text.indexOf ('('); // find first left parenthesis
if (ptr < 0) if (ptr < 0)
return ""; return "";
int depth = 1; int depth = 1;
while (++ptr < text.length ()) // find matching right parenthesis while (++ptr < text.length ()) // find matching right parenthesis
{ {
if (text.charAt (ptr) == ')') if (text.charAt (ptr) == ')')

View File

@ -32,6 +32,7 @@ abstract class Function implements Value
Sheet parent; Sheet parent;
String functionText; String functionText;
boolean hasValue;
static Function getInstance (Sheet parent, String text) 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); 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) protected Range getRange (String text)
{ {
Range range = null; Range range = null;

View File

@ -1,12 +1,21 @@
package com.bytezone.diskbrowser.visicalc; 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 @Override
@ -20,4 +29,16 @@ public class Number implements Value
{ {
return String.format ("Number: %f", value); return String.format ("Number: %f", value);
} }
@Override
public boolean hasValue ()
{
return hasValue;
}
@Override
public String getError ()
{
return hasValue ? "" : "@NA";
}
} }

View File

@ -309,18 +309,21 @@ public class Sheet implements Iterable<Cell>
if (!command.isEmpty ()) if (!command.isEmpty ())
currentCell.format (command); // formatting command currentCell.format (command); // formatting command
if (!line.isEmpty ()) 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 getCell (Address address)
{ {
Cell cell = sheet.get (address.sortValue); Cell cell = sheet.get (address.sortValue);
if (cell == null) if (cell == null)
{
// cell = new Cell (this, address);
// sheet.put (address.sortValue, cell);
System.out.printf ("Nonexistent cell requested [%s]%n", address); System.out.printf ("Nonexistent cell requested [%s]%n", address);
}
return cell; return cell;
} }

View File

@ -2,5 +2,9 @@ package com.bytezone.diskbrowser.visicalc;
public interface Value public interface Value
{ {
public boolean hasValue ();
public double getValue (); public double getValue ();
public String getError ();
} }