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
{
// 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<Cell>, 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<Cell>, 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<Cell>, 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<Cell>, 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

View File

@ -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<String> operators = new ArrayList<String> ();
private final List<String> signs = new ArrayList<String> ();
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) == ')')

View File

@ -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;

View File

@ -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";
}
}

View File

@ -309,18 +309,21 @@ public class Sheet implements Iterable<Cell>
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;
}

View File

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