mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-11-23 19:31:00 +00:00
rebuilding expressions
This commit is contained in:
parent
bc27149106
commit
ed94972388
@ -98,7 +98,12 @@ class Cell implements Comparable<Cell>
|
||||
char operator = m.group (1).isEmpty () ? '+' : m.group (1).charAt (0);
|
||||
|
||||
if (m.group (3) != null) // address
|
||||
interim = parent.getValue (m.group (3));
|
||||
{
|
||||
Address address = new Address (m.group (3));
|
||||
Cell cell = parent.getCell (address);
|
||||
if (cell != null)
|
||||
interim = cell.getValue ();
|
||||
}
|
||||
else if (m.group (4) != null) // constant
|
||||
try
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
public class Count
|
||||
public class Count extends Function
|
||||
{
|
||||
Range range;
|
||||
Sheet parent;
|
||||
@ -11,6 +11,7 @@ public class Count
|
||||
range = parent.getRange (text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue ()
|
||||
{
|
||||
double result = 0;
|
||||
|
192
src/com/bytezone/diskbrowser/visicalc/Expression.java
Normal file
192
src/com/bytezone/diskbrowser/visicalc/Expression.java
Normal file
@ -0,0 +1,192 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Expression
|
||||
{
|
||||
// Expressions:
|
||||
// - number
|
||||
// - cell address
|
||||
// - function
|
||||
// - expression [+-*/^] expression
|
||||
// - [+-=] expression
|
||||
// - ( expression )
|
||||
|
||||
private static final Pattern pattern = Pattern.compile ("");
|
||||
|
||||
private boolean isUnavailable;
|
||||
private boolean isError;
|
||||
|
||||
private boolean hasValue;
|
||||
private double value;
|
||||
private Function function;
|
||||
private Address address;
|
||||
|
||||
private Expression expression1;
|
||||
private char operator;
|
||||
private Expression expression2;
|
||||
|
||||
private final Sheet parent;
|
||||
|
||||
public Expression (Sheet parent, String input)
|
||||
{
|
||||
this.parent = parent;
|
||||
String text = input.trim ();
|
||||
|
||||
char firstChar = text.charAt (0);
|
||||
if (firstChar == '-')
|
||||
{
|
||||
operator = '-';
|
||||
expression1 = new Expression (parent, text.substring (1));
|
||||
}
|
||||
else if (firstChar == '=' || firstChar == '+')
|
||||
{
|
||||
expression1 = new Expression (parent, text.substring (1));
|
||||
}
|
||||
else if (firstChar == '@')
|
||||
{
|
||||
String functionText = getFunctionText (text);
|
||||
char op = getOperator (functionText, text);
|
||||
if (op == ' ')
|
||||
function = Function.getInstance (parent, functionText);
|
||||
else if (op != '!')
|
||||
setExpressions (functionText, op, text);
|
||||
}
|
||||
else if (firstChar == '(')
|
||||
{
|
||||
String bracketText = getFunctionText (text);
|
||||
char op = getOperator (bracketText, text);
|
||||
if (op == ' ')
|
||||
expression1 =
|
||||
new Expression (parent, bracketText.substring (1, bracketText.length () - 2));
|
||||
else if (op != '!')
|
||||
setExpressions (bracketText, op, text);
|
||||
}
|
||||
else if ((firstChar >= '0' && firstChar <= '9') || firstChar == '.')
|
||||
{
|
||||
String numberText = getNumberText (text);
|
||||
char op = getOperator (numberText, text);
|
||||
if (op == ' ')
|
||||
{
|
||||
value = Double.parseDouble (numberText);
|
||||
hasValue = true;
|
||||
}
|
||||
else if (op != '!')
|
||||
setExpressions (numberText, op, text);
|
||||
}
|
||||
else if (firstChar >= 'A' && firstChar <= 'Z')
|
||||
{
|
||||
String addressText = getAddressText (text);
|
||||
char op = getOperator (addressText, text);
|
||||
if (op == ' ')
|
||||
address = new Address (addressText);
|
||||
else if (op != '!')
|
||||
setExpressions (addressText, op, text);
|
||||
}
|
||||
else
|
||||
System.out.printf ("Error processing [%s]%n", text);
|
||||
}
|
||||
|
||||
private void setExpressions (String text1, char op, String text2)
|
||||
{
|
||||
expression1 = new Expression (parent, text1);
|
||||
operator = op;
|
||||
expression2 = new Expression (parent, text2.substring (text1.length () + 2));
|
||||
}
|
||||
|
||||
double getValue ()
|
||||
{
|
||||
if (hasValue)
|
||||
return value;
|
||||
|
||||
if (function != null)
|
||||
return function.getValue ();
|
||||
|
||||
if (address != null)
|
||||
return parent.getCell (address).getValue ();
|
||||
|
||||
if (expression2 == null)
|
||||
{
|
||||
if (operator == '-')
|
||||
return expression1.getValue () * -1;
|
||||
return expression1.getValue ();
|
||||
}
|
||||
|
||||
switch (operator)
|
||||
{
|
||||
case ' ':
|
||||
return expression1.getValue ();
|
||||
case '+':
|
||||
return expression1.getValue () + expression2.getValue ();
|
||||
case '-':
|
||||
return expression1.getValue () - expression2.getValue ();
|
||||
case '*':
|
||||
return expression1.getValue () * expression2.getValue ();
|
||||
case '/':
|
||||
return expression1.getValue () / expression2.getValue ();
|
||||
case '^':
|
||||
return Math.pow (expression1.getValue (), expression2.getValue ());
|
||||
}
|
||||
|
||||
System.out.println ("Unresolved value");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String getFunctionText (String text)
|
||||
{
|
||||
int ptr = text.indexOf ('('); // find first left parenthesis
|
||||
int depth = 1;
|
||||
while (++ptr < text.length ()) // find matching right parenthesis
|
||||
{
|
||||
if (text.charAt (ptr) == ')')
|
||||
{
|
||||
--depth;
|
||||
if (depth == 0)
|
||||
break;
|
||||
}
|
||||
else if (text.charAt (ptr) == '(')
|
||||
++depth;
|
||||
}
|
||||
return text.substring (0, ptr);
|
||||
}
|
||||
|
||||
private String getNumberText (String text)
|
||||
{
|
||||
int ptr = 0;
|
||||
while (++ptr < text.length ())
|
||||
{
|
||||
char c = text.charAt (ptr);
|
||||
if (c != '.' && (c < '0' || c > '9'))
|
||||
break;
|
||||
}
|
||||
return text.substring (0, ptr);
|
||||
}
|
||||
|
||||
private String getAddressText (String text)
|
||||
{
|
||||
int ptr = 0;
|
||||
while (++ptr < text.length ())
|
||||
{
|
||||
char c = text.charAt (ptr);
|
||||
if ((c < '0' || c > '9') && (c < 'A' || c > 'Z'))
|
||||
break;
|
||||
}
|
||||
return text.substring (0, ptr);
|
||||
}
|
||||
|
||||
private char getOperator (String text1, String text2)
|
||||
{
|
||||
if (text1.length () == text2.length ())
|
||||
return ' ';
|
||||
|
||||
char c = text2.charAt (text1.length ());
|
||||
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^')
|
||||
{
|
||||
setExpressions (text1, c, text2);
|
||||
return c;
|
||||
}
|
||||
|
||||
// error
|
||||
return '!';
|
||||
}
|
||||
}
|
26
src/com/bytezone/diskbrowser/visicalc/Function.java
Normal file
26
src/com/bytezone/diskbrowser/visicalc/Function.java
Normal file
@ -0,0 +1,26 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
public abstract class Function
|
||||
{
|
||||
static Function getInstance (Sheet parent, String text)
|
||||
{
|
||||
if (text.startsWith ("@LOOKUP("))
|
||||
return new Lookup (parent, text);
|
||||
|
||||
if (text.startsWith ("@COUNT("))
|
||||
return new Count (parent, text);
|
||||
|
||||
if (text.startsWith ("@MIN("))
|
||||
return new Min (parent, text);
|
||||
|
||||
if (text.startsWith ("@MAX("))
|
||||
return new Max (parent, text);
|
||||
|
||||
if (text.startsWith ("@SUM("))
|
||||
return new Sum (parent, text);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract double getValue ();
|
||||
}
|
@ -1,22 +1,21 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
public class Lookup
|
||||
public class Lookup extends Function
|
||||
{
|
||||
Range range;
|
||||
Cell source;
|
||||
Sheet parent;
|
||||
boolean hasValue;
|
||||
String sourceText;
|
||||
String rangeText;
|
||||
|
||||
public Lookup (Sheet parent, String text)
|
||||
{
|
||||
this.parent = parent;
|
||||
|
||||
int pos = text.indexOf (',');
|
||||
String sourceText = text.substring (8, pos);
|
||||
String rangeText = text.substring (pos + 1, text.length () - 1);
|
||||
|
||||
source = parent.getCell (new Address (sourceText));
|
||||
range = parent.getRange (rangeText);
|
||||
sourceText = text.substring (8, pos);
|
||||
rangeText = text.substring (pos + 1, text.length () - 1);
|
||||
}
|
||||
|
||||
// need a mechanism to return NA and ERROR
|
||||
@ -25,18 +24,28 @@ public class Lookup
|
||||
return hasValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue ()
|
||||
{
|
||||
// source could be a formula - @LOOKUP(.2*K8+K7,H3...H16)
|
||||
source = parent.getCell (new Address (sourceText));
|
||||
range = parent.getRange (rangeText);
|
||||
|
||||
Address target = null;
|
||||
for (Address address : range)
|
||||
{
|
||||
if (parent.getCell (address).getValue () > source.getValue ())
|
||||
System.out.printf ("%s : %s%n", source, address);
|
||||
Cell cell = parent.getCell (address);
|
||||
if (cell != null && cell.getValue () > source.getValue ())
|
||||
break;
|
||||
target = address;
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
return parent.getCell (target.nextColumn ()).getValue ();
|
||||
if (range.isVertical ())
|
||||
return parent.getCell (target.nextColumn ()).getValue ();
|
||||
else
|
||||
return parent.getCell (target.nextRow ()).getValue ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
public class Max
|
||||
public class Max extends Function
|
||||
{
|
||||
Range range;
|
||||
Sheet parent;
|
||||
@ -11,6 +11,7 @@ public class Max
|
||||
range = parent.getRange (text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue ()
|
||||
{
|
||||
double max = Double.MIN_VALUE;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
public class Min
|
||||
public class Min extends Function
|
||||
{
|
||||
Range range;
|
||||
Sheet parent;
|
||||
@ -11,6 +11,7 @@ public class Min
|
||||
range = parent.getRange (text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue ()
|
||||
{
|
||||
double min = Double.MAX_VALUE;
|
||||
|
@ -39,6 +39,20 @@ class Range implements Iterable<Address>
|
||||
range.add (new Address (s));
|
||||
}
|
||||
|
||||
boolean isHorizontal ()
|
||||
{
|
||||
Address first = range.get (0);
|
||||
Address last = range.get (range.size () - 1);
|
||||
return first.row == last.row;
|
||||
}
|
||||
|
||||
boolean isVertical ()
|
||||
{
|
||||
Address first = range.get (0);
|
||||
Address last = range.get (range.size () - 1);
|
||||
return first.column == last.column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString ()
|
||||
{
|
||||
|
@ -251,7 +251,7 @@ public class Sheet implements Iterable<Cell>
|
||||
currentCell.doCommand (command);
|
||||
}
|
||||
}
|
||||
else if (command.startsWith ("@"))
|
||||
else if (command.startsWith ("@")) // function
|
||||
{
|
||||
currentCell.doCommand (command);
|
||||
}
|
||||
@ -414,19 +414,19 @@ public class Sheet implements Iterable<Cell>
|
||||
return range;
|
||||
}
|
||||
|
||||
public double getValue (Address address)
|
||||
private double getValue (Address address)
|
||||
{
|
||||
Cell cell = sheet.get (address.sortValue);
|
||||
return cell == null ? 0.0 : cell.getValue ();
|
||||
}
|
||||
|
||||
public double getValue (String cellName)
|
||||
private double getValue (String cellName)
|
||||
{
|
||||
Address address = new Address (cellName);
|
||||
return getValue (address);
|
||||
}
|
||||
|
||||
public Cell getCell (Address address)
|
||||
Cell getCell (Address address)
|
||||
{
|
||||
return sheet.get (address.sortValue);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.bytezone.diskbrowser.visicalc;
|
||||
|
||||
public class Sum
|
||||
public class Sum extends Function
|
||||
{
|
||||
Range range;
|
||||
Sheet parent;
|
||||
@ -11,6 +11,7 @@ public class Sum
|
||||
range = parent.getRange (text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue ()
|
||||
{
|
||||
double result = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user