Fixed bugs and enhanched math parser.

This commit is contained in:
Andrea Cavalli 2017-06-09 22:47:30 +02:00
parent f31985764d
commit 8bc727e823
23 changed files with 463 additions and 302 deletions

View File

@ -0,0 +1,9 @@
package org.warp.picalculator;
public class IntegerObj {
public int i;
public IntegerObj(int i) {
this.i = i;
}
}

View File

@ -30,10 +30,10 @@ public class Main {
Main.args = args;
beforeStart();
new DisplayManager(screen);
Utils.debug.println("Shutdown...");
Utils.out.println(1, "Shutdown...");
beforeShutdown();
Utils.debug.println("");
Utils.debug.println("Closed.");
Utils.out.println(1, "");
Utils.out.println(1, "Closed.");
System.exit(0);
}

View File

@ -46,17 +46,49 @@ public class Utils {
public static final int scaleMode = BigDecimal.ROUND_HALF_UP;
public static final RoundingMode scaleMode2 = RoundingMode.HALF_UP;
public static DebugStream debug = new DebugStream();
public static AdvancedOutputStream out = new AdvancedOutputStream();
public static boolean debugOn;
public static int outputLevel = 5;
public static final int OUTPUTLEVEL_NODEBUG = 0;
public static final int OUTPUTLEVEL_DEBUG_MIN = 1;
public static final int OUTPUTLEVEL_DEBUG_MAX = 4;
public static boolean debugThirdScreen;
public static final boolean debugWindow2x = true;
public static final class DebugStream extends StringWriter {
public static final class AdvancedOutputStream extends StringWriter {
public void println(String str) {
if (debugOn) {
System.err.println(str);
println(0, str);
}
public void println(int level) {
if (outputLevel >= level) {
if (outputLevel == 0) {
System.out.println();
} else {
System.err.println();
}
}
}
public void println(int level, String str) {
if (outputLevel >= level) {
if (outputLevel == 0) {
System.out.println(str);
} else {
System.err.println(str);
}
}
}
public void print(int level, String str) {
if (outputLevel >= level) {
if (outputLevel == 0) {
System.out.print(str);
} else {
System.err.print(str);
}
}
}

View File

@ -832,7 +832,7 @@ public class Keyboard {
refreshRequest = true;
}
} else if (!done) {
Utils.debug.println("Key " + k.toString() + " ignored.");
Utils.out.println(1, "Key " + k.toString() + " ignored.");
}
}
@ -862,7 +862,7 @@ public class Keyboard {
refreshRequest = true;
}
} else if (!done) {
Utils.debug.println("Key " + k.toString() + " ignored.");
Utils.out.println(1, "Key " + k.toString() + " ignored.");
}
}

View File

@ -77,12 +77,12 @@ public final class DisplayManager implements RenderingLoop {
GraphicEngine d;
d = new GPUEngine();
if (d.isSupported()) {
Utils.debug.println("Using GPU Graphic Engine");
Utils.out.println(1, "Using GPU Graphic Engine");
return d;
}
d = new CPUEngine();
if (d.isSupported()) {
Utils.debug.println("Using CPU Graphic Engine");
Utils.out.println(1, "Using CPU Graphic Engine");
return d;
}
d = new Headless256Engine();
@ -273,7 +273,7 @@ public final class DisplayManager implements RenderingLoop {
if (brightness <= 10) {
renderer.glFillRect(Main.screenSize[0] - (padding + 16), 2, 16, 16, 16 * brightness, 16 * 1, 16, 16);
} else {
Utils.debug.println("Brightness error");
Utils.out.println(1, "Brightness error");
}
padding += 18 + 6;
@ -478,7 +478,7 @@ public final class DisplayManager implements RenderingLoop {
Gpio.pwmWrite(12, (int) Math.ceil(brightness * 1024f));
// SoftPwm.softPwmWrite(12, (int)(Math.ceil(brightness*10)));
} else {
Utils.debug.println("Brightness: " + newval);
Utils.out.println(1, "Brightness: " + newval);
}
}
}

View File

@ -132,7 +132,7 @@ public class MathInputScreen extends Screen {
@Override
public boolean keyPressed(Key k) {
Utils.debug.println(k.toString());
Utils.out.println(1, k.toString());
switch (k) {
case OK:
userInput.toggleExtra();
@ -184,7 +184,7 @@ public class MathInputScreen extends Screen {
case SIMPLIFY:
if (DisplayManager.error != null) {
//TODO: make the error management a global API rather than being relegated to this screen.
Utils.debug.println("Resetting after error...");
Utils.out.println(1, "Resetting after error...");
DisplayManager.error = null;
calc.f = null;
calc.f2 = null;
@ -205,38 +205,40 @@ public class MathInputScreen extends Screen {
calc.f.add(expr);
int stop = 0;
boolean done = false;
ObjectArrayList<ObjectArrayList<Function>> resultExpressions = new ObjectArrayList<>();
resultExpressions.add(new ObjectArrayList<Function>(expr.getParameters()));
ObjectArrayList<Function> resultExpressions = new ObjectArrayList<>();
resultExpressions.add(expr.getParameter());
while (!done && stop < 3000) {
ObjectArrayList<ObjectArrayList<Function>> newResultExpressions = new ObjectArrayList<>();
ObjectArrayList<Function> newResultExpressions = new ObjectArrayList<>();
done = true;
for (ObjectArrayList<Function> resultExpr : resultExpressions) {
ObjectArrayList<Function> newResults = new ObjectArrayList<>();
for (Function f : resultExpr) {
if (f.isSimplified() == false) {
done = false;
if (f instanceof Expression) {
ObjectArrayList<Function> fncResult = ((Expression)f).solve();
for (Function resultItem : fncResult) {
newResultExpressions.add(new ObjectArrayList<Function>(new Function[] {resultItem}));
}
} else {
List<Function> fncResult = f.simplify();
for (Function resultItem : fncResult) {
newResultExpressions.add(new ObjectArrayList<Function>(new Function[] {resultItem}));
}
for (Function f : resultExpressions) {
Function newResult = null;
if (f.isSimplified() == false) {
done = false;
if (f instanceof Expression) {
ObjectArrayList<Function> fncResult = ((Expression)f).solve();
for (Function resultItem : fncResult) {
newResultExpressions.add(resultItem);
}
} else {
newResults.add(f);
List<Function> fncResult = f.simplify();
for (Function resultItem : fncResult) {
newResultExpressions.add(resultItem);
}
}
} else {
newResult = f;
}
if (newResults.isEmpty() == false) {
newResultExpressions.add(newResults);
if (newResult != null) {
newResultExpressions.add(newResult);
}
}
resultExpressions = newResultExpressions;
stop++;
}
Utils.out.println(2, "INPUT: "+expr);
for (Function rr : resultExpressions) {
Utils.out.println(1, "RESULT: " + rr.toString());
}
ObjectArrayList<ObjectArrayList<Block>> resultBlocks = MathParser.parseOutput(calc, resultExpressions);
result.setContentAsMultipleGroups(resultBlocks);
// showVariablesDialog(() -> {
@ -372,18 +374,14 @@ public class MathInputScreen extends Screen {
userInput.clear();
result.clear();
if (DisplayManager.error != null) {
Utils.debug.println("Resetting after error...");
Utils.out.println(1, "Resetting after error...");
DisplayManager.error = null;
}
return true;
case SURD_MODE:
calc.exactMode = !calc.exactMode;
if (calc.exactMode == false) {
calc.f2 = solveExpression(calc.f2);
} else {
result.clear();
Keyboard.keyPressed(Key.SIMPLIFY);
}
result.clear();
Keyboard.keyPressed(Key.SIMPLIFY);
return true;
case debug1:
DisplayManager.INSTANCE.setScreen(new EmptyScreen());
@ -442,7 +440,11 @@ public class MathInputScreen extends Screen {
}
}
@SuppressWarnings("unused")
@Deprecated
private ObjectArrayList<Function> solveExpression(ObjectArrayList<Function> f22) {
return null;
/*
try {
try {
return calc.solveExpression(f22);
@ -461,9 +463,12 @@ public class MathInputScreen extends Screen {
System.err.println(e.id);
}
return null;
*/
}
@Deprecated
protected void step() {
/*
try {
try {
showVariablesDialog();
@ -499,7 +504,7 @@ public class MathInputScreen extends Screen {
results.addAll(hs);
calc.f2 = results;
}
Utils.debug.println(calc.f2.toString());
Utils.out.println(1, calc.f2.toString());
} catch (final Exception ex) {
if (Utils.debugOn) {
ex.printStackTrace();
@ -514,9 +519,12 @@ public class MathInputScreen extends Screen {
DisplayManager.error = e.id.toString();
System.err.println(e.id);
}
*/
}
@Deprecated
protected void simplify() {
/*
try {
try {
for (final Function f : calc.f) {
@ -553,6 +561,7 @@ public class MathInputScreen extends Screen {
DisplayManager.error = e.id.toString();
System.err.println(e.id);
}
*/
}
@SuppressWarnings("unused")
@ -610,7 +619,7 @@ public class MathInputScreen extends Screen {
DisplayManager.INSTANCE.setScreen(cvs);
try {
while (DisplayManager.screen == cvs) {
Utils.debug.println(Thread.currentThread().getName());
Utils.out.println(1, Thread.currentThread().getName());
Thread.sleep(200);
}
} catch (final InterruptedException e) {}

View File

@ -177,4 +177,9 @@ public abstract class FunctionOperator implements Function {
@Override
public abstract boolean equals(Object o);
@Override
public String toString() {
return this.getClass().getSimpleName()+"("+this.getParameter1()+","+this.getParameter2()+")";
}
}

View File

@ -20,6 +20,17 @@ public abstract class FunctionSingle implements Function {
parameter = value;
}
/**
* Create a new instance of FunctionSingle.
*
* @param mathContext
* Math Context
*/
public FunctionSingle(MathContext mathContext) {
this.mathContext = mathContext;
parameter = null;
}
/**
* Create a new instance of FunctionSingle.
*

View File

@ -30,7 +30,10 @@ public class MathContext {
resultsCount = 0;
}
@Deprecated
public Function parseString(String string) throws Error {
return null;
/*
if (string.contains("{")) {
if (!string.startsWith("{")) {
throw new Error(Errors.SYNTAX_ERROR);
@ -46,9 +49,13 @@ public class MathContext {
} else {
return new Expression(this, string);
}
*/
}
@Deprecated
public Function parseEquationString(String string) throws Error {
return null;
/*
final String[] parts = string.split("=");
if (parts.length == 1) {
return new Equation(this, new Expression(this, parts[0]), new Number(this, BigInteger.ZERO));
@ -56,10 +63,13 @@ public class MathContext {
return new Equation(this, new Expression(this, parts[0]), new Expression(this, parts[1]));
} else {
throw new Error(Errors.SYNTAX_ERROR);
}
}*/
}
@Deprecated
public ObjectArrayList<Function> solveExpression(ObjectArrayList<Function> input) throws Error {
return null;
/*
ObjectArrayList<Function> results = new ObjectArrayList<>();
final ObjectArrayList<Function> partialResults = new ObjectArrayList<>();
for (final Function f : input) {
@ -87,6 +97,7 @@ public class MathContext {
}
}
return results;
*/
}
public Function getChild() {

View File

@ -29,28 +29,29 @@ import org.warp.picalculator.math.functions.trigonometry.Tangent;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class Expression extends FunctionDynamic {
public class Expression extends FunctionSingle {
public Expression(MathContext root) {
super(root);
}
public Expression(MathContext root, Function[] values) {
super(root, values);
}
public Expression(MathContext root, Function value) {
super(root, new Function[] { value });
super(root, value);
}
private boolean initialParenthesis = false;
@Deprecated
public Expression(MathContext root, String string) throws Error {
this(root, string, "", true);
}
@Deprecated
public Expression(MathContext root, String string, String debugSpaces, boolean initialParenthesis) throws Error {
super(root);
/*
super(root);
this.initialParenthesis = initialParenthesis;
boolean isNumber = false;
@ -72,7 +73,7 @@ public class Expression extends FunctionDynamic {
// If the expression is already a number:
// Se l'espressione è già un numero:
final Number t = new Number(root, string);
functions = new Function[] { t };
parameter = t;
Utils.debug.println(debugSpaces + "•Result:" + t.toString());
} else {
// Else prepare the expression:
@ -223,7 +224,7 @@ public class Expression extends FunctionDynamic {
// Convert the expression to a list of objects
Expression imputRawParenthesis = new Expression(root);
imputRawParenthesis = (Expression) imputRawParenthesis.setParameters(new Function[] {});
imputRawParenthesis = (Expression) imputRawParenthesis.setParameter(null);
String tmp = "";
final char[] functions = concat(concat(concat(concat(MathematicalSymbols.functions, MathematicalSymbols.parentheses), MathematicalSymbols.signums(true)), MathematicalSymbols.variables), MathematicalSymbols.genericSyntax);
for (int i = 0; i < processExpression.length(); i++) {
@ -555,48 +556,32 @@ public class Expression extends FunctionDynamic {
final String result = toString();
Utils.debug.println(debugSpaces + "•Result:" + result);
}
*/
}
@Override
protected boolean isSolvable() {
if (getParametersLength() > 1) {
final Function f = getParameter();
if (f.isSimplified() == false) {
return true;
} else if (getParametersLength() == 1) {
final Function f = getParameter(0);
if (f.isSimplified() == false) {
return true;
} else {
return !parenthesisNeeded();
}
} else {
return !parenthesisNeeded();
}
return false;
}
@Override
public ObjectArrayList<Function> solve() throws Error {
final ObjectArrayList<Function> ret = new ObjectArrayList<>();
if (getParametersLength() == 1) {
if (getParameter(0).isSimplified() || !parenthesisNeeded()) {
ret.add(getParameter(0));
return ret;
} else {
final List<Function> l = getParameter(0).simplify();
for (final Function f : l) {
if (f instanceof Number || f instanceof Variable) {
ret.add(f);
} else {
ret.add(new Expression(root, new Function[] { f }));
}
}
return ret;
}
if (getParameter().isSimplified() || !parenthesisNeeded()) {
ret.add(getParameter());
return ret;
} else {
for (final Function f : getParameters()) {
if (f.isSimplified() == false) {
final List<Function> partial = f.simplify();
for (final Function fnc : partial) {
ret.add(new Expression(root, new Function[] { fnc }));
}
final List<Function> l = getParameter().simplify();
for (final Function f : l) {
if (f instanceof Number || f instanceof Variable) {
ret.add(f);
} else {
ret.add(new Expression(mathContext, f));
}
}
return ret;
@ -608,20 +593,18 @@ public class Expression extends FunctionDynamic {
if (initialParenthesis) {
parenthesisneeded = false;
} else {
if (getParametersLength() == 1) {
final Function f = getParameter(0);
if (f instanceof Number || f instanceof Variable || f instanceof Expression || f instanceof Division || f instanceof Joke || f instanceof Undefined || f instanceof Power || f instanceof Sine || f instanceof Cosine || f instanceof Tangent || f instanceof ArcSine || f instanceof ArcCosine || f instanceof ArcTangent || f instanceof RootSquare) {
final Function f = getParameter(0);
if (f instanceof Number || f instanceof Variable || f instanceof Expression || f instanceof Division || f instanceof Joke || f instanceof Undefined || f instanceof Power || f instanceof Sine || f instanceof Cosine || f instanceof Tangent || f instanceof ArcSine || f instanceof ArcCosine || f instanceof ArcTangent || f instanceof RootSquare) {
parenthesisneeded = false;
}
if (f instanceof Multiplication) {
if (((Multiplication) f).getParameter1() instanceof Number) {
parenthesisneeded = !(((Multiplication) f).getParameter2() instanceof Variable);
} else if (((Multiplication) f).getParameter2() instanceof Number) {
parenthesisneeded = !(((Multiplication) f).getParameter1() instanceof Variable);
} else if (((Multiplication) f).getParameter1() instanceof Variable || ((Multiplication) f).getParameter2() instanceof Variable) {
parenthesisneeded = false;
}
if (f instanceof Multiplication) {
if (((Multiplication) f).getParameter1() instanceof Number) {
parenthesisneeded = !(((Multiplication) f).getParameter2() instanceof Variable);
} else if (((Multiplication) f).getParameter2() instanceof Number) {
parenthesisneeded = !(((Multiplication) f).getParameter1() instanceof Variable);
} else if (((Multiplication) f).getParameter1() instanceof Variable || ((Multiplication) f).getParameter2() instanceof Variable) {
parenthesisneeded = false;
}
}
}
}
return parenthesisneeded;
@ -645,46 +628,29 @@ public class Expression extends FunctionDynamic {
@Override
public String toString() {
String s = "(";
if (functions.length > 0) {
for (final Function f : functions) {
if (f == null) {
s += "[null],";
} else {
s += f.toString() + ",";
}
}
s = s.substring(0, s.length() - 1);
if (parameter == null) {
s += "null";
} else {
s += parameter.toString();
}
s = s.substring(0, s.length() - 1);
s += ")";
return s;
}
@Override
public boolean equals(Object o) {
if (o instanceof Expression) {
final Expression f = (Expression) o;
final Function[] exprFuncs1 = getParameters();
final Function[] exprFuncs2 = f.getParameters();
if (exprFuncs1.length == exprFuncs2.length) {
for (int i = 0; i < exprFuncs1.length; i++) {
if (exprFuncs1[i].equals(exprFuncs2[i]) == false) {
return false;
}
}
return true;
}
} else if (o != null & getParametersLength() == 1) {
if (parameter == null | o == null) {
return parameter == o;
} else {
final Function f = (Function) o;
return (getParameter(0).equals(f));
} else if (o == null & getParametersLength() == 0) {
return true;
}
return false;
}
@Override
public Expression clone() {
return new Expression(root, functions);
return new Expression(mathContext, parameter);
}
}

View File

@ -105,11 +105,6 @@ public class Multiplication extends FunctionOperator {
return new Multiplication(mathContext, parameter1, parameter2);
}
@Override
public String toString() {
return "(" + parameter1.toString() + ")*(" + parameter2.toString() + ")";
}
@Override
public ObjectArrayList<Block> toBlock(MathContext context) throws Error {
ObjectArrayList<Block> result = new ObjectArrayList<>();

View File

@ -48,7 +48,7 @@ public class EquationsSystem extends FunctionDynamic {
if (f instanceof Number) {
ret.add(f);
} else {
ret.add(new Expression(root, new Function[] { f }));
ret.add(new Expression(root, f));
}
}
return ret;
@ -58,7 +58,7 @@ public class EquationsSystem extends FunctionDynamic {
if (f.isSimplified() == false) {
final List<Function> partial = f.simplify();
for (final Function fnc : partial) {
ret.add(new Expression(root, new Function[] { fnc }));
ret.add(new Expression(root, fnc));
}
}
}

View File

@ -2,48 +2,27 @@ package org.warp.picalculator.math.parser;
import org.warp.picalculator.Error;
import org.warp.picalculator.Errors;
import org.warp.picalculator.IntegerObj;
import org.warp.picalculator.Utils;
import org.warp.picalculator.gui.expression.blocks.Block;
import org.warp.picalculator.gui.expression.blocks.BlockChar;
import org.warp.picalculator.gui.expression.blocks.BlockContainer;
import org.warp.picalculator.gui.expression.blocks.BlockDivision;
import org.warp.picalculator.gui.expression.blocks.BlockExponentialNotation;
import org.warp.picalculator.gui.expression.blocks.BlockParenthesis;
import org.warp.picalculator.gui.expression.blocks.BlockPower;
import org.warp.picalculator.gui.expression.blocks.BlockSquareRoot;
import org.warp.picalculator.gui.expression.containers.InputContainer;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.MathematicalSymbols;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Expression;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Power;
import org.warp.picalculator.math.functions.RootSquare;
import org.warp.picalculator.math.functions.Subtraction;
import org.warp.picalculator.math.functions.Sum;
import org.warp.picalculator.math.functions.SumSubtraction;
import org.warp.picalculator.math.functions.Variable;
import org.warp.picalculator.math.functions.Variable.V_TYPE;
import org.warp.picalculator.math.parser.features.FeatureChar;
import org.warp.picalculator.math.parser.features.FeatureDivision;
import org.warp.picalculator.math.parser.features.FeatureMultiplication;
import org.warp.picalculator.math.parser.features.FeatureNumber;
import org.warp.picalculator.math.parser.features.FeatureParenthesis;
import org.warp.picalculator.math.parser.features.FeaturePowerChar;
import org.warp.picalculator.math.parser.features.FeatureSquareRoot;
import org.warp.picalculator.math.parser.features.FeatureSum;
import org.warp.picalculator.math.parser.features.FeatureVariable;
import org.warp.picalculator.math.parser.features.interfaces.Feature;
import org.warp.picalculator.math.parser.features.interfaces.FeatureDouble;
import org.warp.picalculator.math.parser.features.interfaces.FeatureSingle;
import com.sun.org.apache.xpath.internal.functions.Function2Args;
import org.warp.picalculator.math.parser.steps.JoinNumberAndVariables;
import org.warp.picalculator.math.parser.steps.FixMultiplicationsAndDivisions;
import org.warp.picalculator.math.parser.steps.FixSingleFunctionArgs;
import org.warp.picalculator.math.parser.steps.FixSumsAndSubtractions;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
public class MathParser {
public static Expression parseInput(MathContext context, InputContainer c) throws Error {
@ -55,15 +34,11 @@ public class MathParser {
return result;
}
public static ObjectArrayList<ObjectArrayList<Block>> parseOutput(MathContext context, ObjectArrayList<ObjectArrayList<Function>> resultExpressions) throws Error {
public static ObjectArrayList<ObjectArrayList<Block>> parseOutput(MathContext context, ObjectArrayList<Function> resultExpressions) throws Error {
final ObjectArrayList<ObjectArrayList<Block>> result = new ObjectArrayList<>();
for (ObjectArrayList<Function> resultExpression : resultExpressions) {
final ObjectArrayList<Block> resultBlocks = new ObjectArrayList<>();
for (Function f : resultExpression) {
ObjectArrayList<Block> resultPart = f.toBlock(context);
if (resultPart == null) throw new Error(Errors.NOT_IMPLEMENTED, "Unknown function " + f.getClass().getSimpleName());
resultBlocks.addAll(resultPart);
}
for (Function resultExpression : resultExpressions) {
ObjectArrayList<Block> resultBlocks = resultExpression.toBlock(context);
if (resultBlocks == null) throw new Error(Errors.NOT_IMPLEMENTED, "Unknown function " + resultExpression.getClass().getSimpleName());
result.add(resultBlocks);
}
return result;
@ -73,7 +48,7 @@ public class MathParser {
features = fixFeatures(context, features);
final ObjectArrayList<Function> process = new ObjectArrayList<>();
ObjectArrayList<Function> process = new ObjectArrayList<>();
for (final Feature f : features) {
Function fnc = f.toFunction(context);
@ -81,7 +56,7 @@ public class MathParser {
process.add(fnc);
}
fixStack(context, process);
process = fixStack(context, process);
if (process.size() > 1) {
throw new Error(Errors.UNBALANCED_STACK, "The stack is unbalanced. Not all the functions are nested correctly");
@ -90,119 +65,55 @@ public class MathParser {
return process.get(0);
}
private static void fixStack(MathContext context, ObjectArrayList<Function> process) throws Error {
private static ObjectArrayList<Function> fixStack(MathContext context, ObjectArrayList<Function> functionsList) throws Error {
final MathParserStep[] steps = new MathParserStep[] {
new JoinNumberAndVariables(context),
new FixSingleFunctionArgs(),
new FixMultiplicationsAndDivisions(),
new FixSumsAndSubtractions(),
};
boolean lastLoopDidSomething;
Function lastElement;
ObjectListIterator<Function> stackIterator;
for (MathParserStep step : steps) {
Utils.out.println(2, "Stack fixing step \""+step.getStepName()+"\"");
int stepQty = step.requiresReversedIteration()?-1:1, initialIndex = step.requiresReversedIteration()?functionsList.size()-1:0;
do {
lastLoopDidSomething = false;
lastElement = null;
IntegerObj curIndex = new IntegerObj(initialIndex);
while(curIndex.i >= 0 && curIndex.i < functionsList.size()) {
final Function f = functionsList.get(curIndex.i);
//Phase 0: join number and variables ([2][x] => [[2]*[x]])
do {
lastLoopDidSomething = false;
stackIterator = process.listIterator(process.size());
Function lastElement = null;
while (stackIterator.hasPrevious()) {
final Function f = stackIterator.previous();
final int curIndex = stackIterator.nextIndex();
if (f instanceof Number | f instanceof Variable) {
if (lastElement instanceof Variable) {
if (step.eval(curIndex, lastElement, f, functionsList)) {
lastLoopDidSomething = true;
final Function var = process.get(curIndex + 1);
final Function numb = process.get(curIndex);
stackIterator.set(new Multiplication(context, numb, var));
process.remove(curIndex + 1);
}
lastElement=f;
curIndex.i+=stepQty;
}
lastElement = f;
} while (lastLoopDidSomething);
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, "\tStatus: ");
for (Function f : functionsList) {
Utils.out.print(Utils.OUTPUTLEVEL_DEBUG_MAX, f.toString());
}
} while (lastLoopDidSomething);
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_MAX);
}
//Phase 1
do {
lastLoopDidSomething = false;
stackIterator = process.listIterator(process.size());
Function lastElement = null;
while (stackIterator.hasPrevious()) {
final Function f = stackIterator.previous();
// //Phase 4
// do {
// lastLoopDidSomething = false;
// functionListIterator = functionsList.iterator();
// while (functionListIterator.hasNext()) {
// final Function f = functionListIterator.next();
//
// if (f instanceof Function2Args) {
//
// }
// }
// } while (lastLoopDidSomething);
if (f instanceof FunctionSingle) {
if (((FunctionSingle) f).getParameter() == null) {
lastLoopDidSomething = true;
if (lastElement == null) {
throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified.");
} else {
((FunctionSingle) f).setParameter(lastElement);
process.remove(stackIterator.nextIndex());
}
}
}
lastElement = f;
}
} while (lastLoopDidSomething);
//Phase 2
do {
lastLoopDidSomething = false;
stackIterator = process.listIterator();
while (stackIterator.hasNext()) {
final Function f = stackIterator.next();
final int curIndex = stackIterator.previousIndex();
if (f instanceof Multiplication || f instanceof Division) {
if (curIndex - 1 >= 0 && stackIterator.hasNext()) {
lastLoopDidSomething = true;
final Function next = process.get(curIndex + 1);
final Function prev = process.get(curIndex - 1);
stackIterator.set(f.setParameter(0, prev).setParameter(1, next));
process.remove(curIndex + 1);
process.remove(curIndex - 1);
} else {
if (f.getParameter(0) == null || f.getParameter(1) == null) {
throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified.");
}
}
}
}
} while (lastLoopDidSomething);
//Phase 3
do {
lastLoopDidSomething = false;
stackIterator = process.listIterator();
while (stackIterator.hasNext()) {
final Function f = stackIterator.next();
final int curIndex = stackIterator.previousIndex();
if (f instanceof Sum || f instanceof Subtraction || f instanceof SumSubtraction) {
if (curIndex - 1 >= 0 && stackIterator.hasNext()) {
lastLoopDidSomething = true;
final Function next = process.get(curIndex + 1);
final Function prev = process.get(curIndex - 1);
stackIterator.set(f.setParameter(0, prev).setParameter(1, next));
process.remove(curIndex + 1);
process.remove(curIndex - 1);
} else {
if (f.getParameter(0) == null || f.getParameter(1) == null) {
throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified.");
}
}
}
}
} while (lastLoopDidSomething);
//Phase 4
do {
lastLoopDidSomething = false;
stackIterator = process.iterator();
while (stackIterator.hasNext()) {
final Function f = stackIterator.next();
if (f instanceof Function2Args) {
}
}
} while (lastLoopDidSomething);
return functionsList;
}
private static ObjectArrayList<Feature> fixFeatures(final MathContext context, ObjectArrayList<Feature> features)

View File

@ -0,0 +1,27 @@
package org.warp.picalculator.math.parser;
import org.warp.picalculator.Error;
import org.warp.picalculator.IntegerObj;
import org.warp.picalculator.math.Function;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Join number and variables together ([2][4][x] => [[24]*[x]])
* @author Andrea Cavalli
*
*/
public interface MathParserStep {
/**
*
* @param f
* @param curIndex
* @param process
* @return true if something changed
*/
public boolean eval(IntegerObj curIndex, Function lastFunction, Function currentFunction, ObjectArrayList<Function> functionsfunctionsList) throws Error;
public boolean requiresReversedIteration();
public String getStepName();
}

View File

@ -0,0 +1,48 @@
package org.warp.picalculator.math.parser.steps;
import org.warp.picalculator.Error;
import org.warp.picalculator.Errors;
import org.warp.picalculator.IntegerObj;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.parser.MathParserStep;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class FixMultiplicationsAndDivisions implements MathParserStep {
@Override
public boolean eval(IntegerObj curIndex, Function lastFunction, Function currentFunction,
ObjectArrayList<Function> functionsList) throws Error {
if (currentFunction instanceof Multiplication || currentFunction instanceof Division) {
if (currentFunction.getParameter(0) == null && currentFunction.getParameter(1) == null) {
if (curIndex.i - 1 >= 0 && curIndex.i + 1 < functionsList.size()) {
final Function next = functionsList.get(curIndex.i + 1);
final Function prev = functionsList.get(curIndex.i - 1);
functionsList.set(curIndex.i, currentFunction.setParameter(0, prev).setParameter(1, next));
functionsList.remove(curIndex.i + 1);
functionsList.remove(curIndex.i - 1);
curIndex.i--;
return true;
} else {
if (currentFunction.getParameter(0) == null || currentFunction.getParameter(1) == null) {
throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified.");
}
}
}
}
return false;
}
@Override
public boolean requiresReversedIteration() {
return false;
}
@Override
public String getStepName() {
return "Fix Multiplications and Divisions";
}
}

View File

@ -0,0 +1,46 @@
package org.warp.picalculator.math.parser.steps;
import org.warp.picalculator.Error;
import org.warp.picalculator.Errors;
import org.warp.picalculator.IntegerObj;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.parser.MathParserStep;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Puts the argument of Single Functions inside them
* @author Andrea Cavalli
*
*/
public class FixSingleFunctionArgs implements MathParserStep {
@Override
public boolean eval(IntegerObj curIndex, Function lastFunction, Function currentFunction,
ObjectArrayList<Function> functionsList) throws Error {
if (currentFunction instanceof FunctionSingle) {
if (((FunctionSingle) currentFunction).getParameter() == null) {
if (lastFunction == null) {
throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified.");
} else {
((FunctionSingle) currentFunction).setParameter(lastFunction);
functionsList.remove(curIndex.i+1);
}
return true;
}
}
return false;
}
@Override
public boolean requiresReversedIteration() {
return true;
}
@Override
public String getStepName() {
return "Fix Single Function Arguments";
}
}

View File

@ -0,0 +1,50 @@
package org.warp.picalculator.math.parser.steps;
import org.warp.picalculator.Error;
import org.warp.picalculator.Errors;
import org.warp.picalculator.IntegerObj;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Subtraction;
import org.warp.picalculator.math.functions.Sum;
import org.warp.picalculator.math.functions.SumSubtraction;
import org.warp.picalculator.math.parser.MathParserStep;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class FixSumsAndSubtractions implements MathParserStep {
@Override
public boolean eval(IntegerObj curIndex, Function lastFunction, Function currentFunction,
ObjectArrayList<Function> functionsList) throws Error {
if (currentFunction instanceof Sum || currentFunction instanceof Subtraction || currentFunction instanceof SumSubtraction) {
if (currentFunction.getParameter(0) == null && currentFunction.getParameter(1) == null) {
if (curIndex.i - 1 >= 0 && curIndex.i + 1 < functionsList.size()) {
final Function next = functionsList.get(curIndex.i + 1);
final Function prev = functionsList.get(curIndex.i - 1);
functionsList.set(curIndex.i, currentFunction.setParameter(0, prev).setParameter(1, next));
functionsList.remove(curIndex.i + 1);
functionsList.remove(curIndex.i - 1);
curIndex.i--;
return true;
} else {
if (currentFunction.getParameter(0) == null || currentFunction.getParameter(1) == null) {
throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified.");
}
}
}
}
return false;
}
@Override
public boolean requiresReversedIteration() {
return false;
}
@Override
public String getStepName() {
return "Fix Sums and Subtractions";
}
}

View File

@ -0,0 +1,45 @@
package org.warp.picalculator.math.parser.steps;
import org.warp.picalculator.IntegerObj;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Variable;
import org.warp.picalculator.math.parser.MathParserStep;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class JoinNumberAndVariables implements MathParserStep {
private MathContext context;
public JoinNumberAndVariables(MathContext context) {
this.context = context;
}
@Override
public boolean eval(IntegerObj curIndex, Function lastFunction, Function currentFunction, ObjectArrayList<Function> functionsList) {
if (currentFunction instanceof Number | currentFunction instanceof Variable) {
if (lastFunction instanceof Variable) {
final Function var = lastFunction;
final Function numb = currentFunction;
functionsList.set(curIndex.i, new Multiplication(context, numb, var));
functionsList.remove(curIndex.i + 1);
return true;
}
}
return false;
}
@Override
public boolean requiresReversedIteration() {
return true;
}
@Override
public String getStepName() {
return "Join number and variables together";
}
}

View File

@ -27,28 +27,24 @@ public class ExpandRule1 {
final Negative fnc = (Negative) f;
if (fnc.getParameter() instanceof Expression) {
final Expression expr = (Expression) fnc.getParameter();
if (expr.getParametersLength() == 1) {
if (expr.getParameter(0) instanceof Sum) {
return true;
} else if (expr.getParameter(0) instanceof Subtraction) {
return true;
} else if (expr.getParameter(0) instanceof SumSubtraction) {
return true;
}
if (expr.getParameter() instanceof Sum) {
return true;
} else if (expr.getParameter() instanceof Subtraction) {
return true;
} else if (expr.getParameter() instanceof SumSubtraction) {
return true;
}
}
} else if (f instanceof Subtraction || f instanceof SumSubtraction) {
final FunctionOperator fnc = (FunctionOperator) f;
if (fnc.getParameter2() instanceof Expression) {
final Expression expr = (Expression) fnc.getParameter2();
if (expr.getParametersLength() == 1) {
if (expr.getParameter(0) instanceof Sum) {
return true;
} else if (expr.getParameter(0) instanceof Subtraction) {
return true;
} else if (expr.getParameter(0) instanceof SumSubtraction) {
return true;
}
if (expr.getParameter() instanceof Sum) {
return true;
} else if (expr.getParameter() instanceof Subtraction) {
return true;
} else if (expr.getParameter() instanceof SumSubtraction) {
return true;
}
}
}
@ -77,7 +73,7 @@ public class ExpandRule1 {
}
final Function fnc = expr.getParameter(0);
final Function fnc = expr.getParameter();
if (fnc instanceof Sum) {
final Function a = ((Sum) fnc).getParameter1();
final Function b = ((Sum) fnc).getParameter2();

View File

@ -22,13 +22,13 @@ public class ExpandRule5 {
final Negative fnc = (Negative) f;
if (fnc.getParameter() instanceof Expression) {
final Expression e = (Expression) fnc.getParameter();
return e.getParametersLength() == 1 && e.getParameter(0) instanceof Negative;
return e.getParameter() instanceof Negative;
}
} else if (f instanceof Subtraction) {
final Subtraction fnc = (Subtraction) f;
if (fnc.getParameter2() instanceof Expression) {
final Expression e = (Expression) fnc.getParameter2();
return e.getParametersLength() == 1 && e.getParameter(0) instanceof Negative;
return e.getParameter() instanceof Negative;
}
}
return false;
@ -39,10 +39,10 @@ public class ExpandRule5 {
if (f instanceof Negative) {
final Negative fnc = (Negative) f;
result.add(((Negative) ((Expression) fnc.getParameter()).getParameter(0)).getParameter());
result.add(((Negative) ((Expression) fnc.getParameter()).getParameter()).getParameter());
} else if (f instanceof Subtraction) {
final Subtraction fnc = (Subtraction) f;
result.add(((Negative) ((Expression) fnc.getParameter2()).getParameter(0)).getParameter());
result.add(((Negative) ((Expression) fnc.getParameter2()).getParameter()).getParameter());
}
return result;
}

View File

@ -21,7 +21,7 @@ public class ExponentRule4 {
public static boolean compare(Function f) {
final Power fnc = (Power) f;
if (fnc.getParameter1() instanceof Expression && ((Expression) fnc.getParameter1()).getParametersLength() == 1 && ((Expression) fnc.getParameter1()).getParameter(0) instanceof Multiplication && fnc.getParameter2() instanceof Number) {
if (fnc.getParameter1() instanceof Expression && ((Expression) fnc.getParameter1()).getParameter() instanceof Multiplication && fnc.getParameter2() instanceof Number) {
return true;
}
return false;
@ -32,7 +32,7 @@ public class ExponentRule4 {
final ObjectArrayList<Function> result = new ObjectArrayList<>();
final Power fnc = (Power) f;
final Expression expr = (Expression) fnc.getParameter1();
final Multiplication mult = (Multiplication) expr.getParameter(0);
final Multiplication mult = (Multiplication) expr.getParameter();
final Function a = mult.getParameter1();
final Function b = mult.getParameter2();
final Number n = (Number) fnc.getParameter2();

View File

@ -23,7 +23,7 @@ public class SyntaxRule2 {
}
if (f.getParameter2() instanceof Expression) {
final Expression e = (Expression) f.getParameter2();
if (e.getParametersLength() == 1 && e.getParameter(0) instanceof Sum) {
if (e.getParameter() instanceof Sum) {
return true;
}
}
@ -39,8 +39,8 @@ public class SyntaxRule2 {
b = ((Sum) f.getParameter2()).getParameter1();
c = ((Sum) f.getParameter2()).getParameter2();
} else {
b = ((Sum) ((Expression) f.getParameter2()).getParameter(0)).getParameter1();
c = ((Sum) ((Expression) f.getParameter2()).getParameter(0)).getParameter2();
b = ((Sum) ((Expression) f.getParameter2()).getParameter()).getParameter1();
c = ((Sum) ((Expression) f.getParameter2()).getParameter()).getParameter2();
}
final Sum mIn = new Sum(root, a, b);
f.setParameter1(mIn);