postfix functions calculations fixes
This commit is contained in:
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CharacterAtPositionFinder;
|
||||
import org.solovyev.android.calculator.StartsWithFinder;
|
||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||
import org.solovyev.android.calculator.model.ParseException;
|
||||
import org.solovyev.common.utils.CollectionsUtils;
|
||||
import org.solovyev.common.utils.Finder;
|
||||
|
||||
@@ -36,17 +37,7 @@ public enum MathType {
|
||||
}
|
||||
},
|
||||
|
||||
grouping_separator(250, false, false, "'", " ") {
|
||||
@Override
|
||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||
return i;
|
||||
}
|
||||
},
|
||||
grouping_separator(250, false, false, "'", " "),
|
||||
|
||||
power_10(300, true, false, "E") {
|
||||
@Override
|
||||
@@ -68,6 +59,33 @@ public enum MathType {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* @Override
|
||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws ParseException {
|
||||
if (result.length() > 0) {
|
||||
int startOfPrefixFunction = getPostfixFunctionStart(result, result.length() - 1);
|
||||
if (result.length() > startOfPrefixFunction) {
|
||||
startOfPrefixFunction = Math.max(0, startOfPrefixFunction);
|
||||
final String substring = result.substring(startOfPrefixFunction);
|
||||
result.setCharAt(startOfPrefixFunction, '(');
|
||||
for ( int j = 0; j < substring.length(); j++ ){
|
||||
if (result.length() > startOfPrefixFunction + 1 + j) {
|
||||
result.setCharAt(startOfPrefixFunction + 1 + j, substring.charAt(j));
|
||||
} else {
|
||||
result.append(substring.charAt(j));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append('(');
|
||||
}
|
||||
super.processToJscl(result, i, match);
|
||||
result.append(")");
|
||||
} else {
|
||||
throw new ParseException("Could not find start of prefix function!");
|
||||
}
|
||||
|
||||
return returnI(i, match);
|
||||
}*/
|
||||
},
|
||||
unary_operation(500, false, false, "-", "=", "!"),
|
||||
binary_operation(600, false, false, "-", "+", "*", "×", "∙", "/", "^") {
|
||||
@@ -190,6 +208,56 @@ public enum MathType {
|
||||
this.tokens = Collections.unmodifiableList(tokens);
|
||||
}
|
||||
|
||||
/* public static int getPostfixFunctionStart(@NotNull CharSequence s, int position) throws ParseException {
|
||||
assert s.length() > position;
|
||||
|
||||
int numberOfOpenGroups = 0;
|
||||
int result = position;
|
||||
for (; result >= 0; result--) {
|
||||
|
||||
final MathType mathType = getType(s.toString(), result).getMathType();
|
||||
|
||||
if (CollectionsUtils.contains(mathType, digit, dot, grouping_separator, power_10)) {
|
||||
// continue
|
||||
} else if (mathType == close_group_symbol) {
|
||||
numberOfOpenGroups++;
|
||||
} else if (mathType == open_group_symbol) {
|
||||
if (numberOfOpenGroups > 0) {
|
||||
numberOfOpenGroups--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (stop(s, numberOfOpenGroups, result)) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfOpenGroups != 0){
|
||||
throw new ParseException("Could not find start of prefix function!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean stop(CharSequence s, int numberOfOpenGroups, int i) {
|
||||
if (numberOfOpenGroups == 0) {
|
||||
if (i > 0) {
|
||||
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
|
||||
endsWithFinder.setI(i + 1);
|
||||
if (!CollectionsUtils.contains(function.getTokens(), FilterType.included, endsWithFinder)) {
|
||||
MathType type = getType(s.toString(), i).getMathType();
|
||||
if (type != constant) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}*/
|
||||
|
||||
@NotNull
|
||||
public List<String> getTokens() {
|
||||
return tokens;
|
||||
@@ -207,9 +275,13 @@ public enum MathType {
|
||||
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
|
||||
}
|
||||
|
||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws ParseException {
|
||||
final String substitute = getSubstituteToJscl(match);
|
||||
result.append(substitute == null ? match : substitute);
|
||||
return returnI(i, match);
|
||||
}
|
||||
|
||||
protected int returnI(int i, @NotNull String match) {
|
||||
if (match.length() > 1) {
|
||||
return i + match.length() - 1;
|
||||
} else {
|
||||
@@ -220,11 +292,7 @@ public enum MathType {
|
||||
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
|
||||
final String substitute = getSubstituteFromJscl(match);
|
||||
result.append(substitute == null ? match : substitute);
|
||||
if (match.length() > 1) {
|
||||
return i + match.length() - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
return returnI(i, match);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -318,7 +386,7 @@ public enum MathType {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
public int processToJscl(@NotNull StringBuilder result, int i) {
|
||||
public int processToJscl(@NotNull StringBuilder result, int i) throws ParseException {
|
||||
return mathType.processToJscl(result, i, match);
|
||||
}
|
||||
|
||||
@@ -344,4 +412,25 @@ public enum MathType {
|
||||
private static boolean contains(@NotNull List<Character> list, @NotNull final CharacterAtPositionFinder atPositionFinder) {
|
||||
return get(list, atPositionFinder) != null;
|
||||
}
|
||||
|
||||
private static class EndsWithFinder implements Finder<String> {
|
||||
|
||||
private int i;
|
||||
|
||||
@NotNull
|
||||
private final CharSequence targetString;
|
||||
|
||||
private EndsWithFinder(@NotNull CharSequence targetString) {
|
||||
this.targetString = targetString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(@Nullable String s) {
|
||||
return targetString.subSequence(0, i).toString().endsWith(s);
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,13 +7,10 @@
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.StartsWithFinder;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.common.utils.CollectionsUtils;
|
||||
import org.solovyev.common.utils.FilterType;
|
||||
import org.solovyev.common.utils.Finder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -48,6 +45,10 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
|
||||
|
||||
if (mathTypeBefore == MathType.function && CollectionsUtils.get(MathType.openGroupSymbols, startsWithFinder) != null) {
|
||||
throw new ParseException("Empty function: " + mathTypeResult.getMatch());
|
||||
} else if (mathTypeBefore == MathType.postfix_function && mathTypeResult.getMathType() == MathType.binary_operation) {
|
||||
if ( mathTypeResult.getMatch().equals("^") ) {
|
||||
throw new ParseException("Power operation after postfix function is currently unsupported!");
|
||||
}
|
||||
}
|
||||
|
||||
i = mathTypeResult.processToJscl(result, i);
|
||||
@@ -99,80 +100,6 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
|
||||
return new PreparedExpression(result.toString(), undefinedVars);
|
||||
}
|
||||
|
||||
private void replaceVariables(StringBuilder sb, String s, int i, @NotNull StartsWithFinder startsWithFinder) {
|
||||
for (Var var : CalculatorEngine.instance.getVarsRegister().getVars()) {
|
||||
if (!var.isSystem()) {
|
||||
if (s.startsWith(var.getName(), i)) {
|
||||
if (CollectionsUtils.get(MathType.function.getTokens(), startsWithFinder) == null) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getPostfixFunctionStart(@NotNull String s, int position) {
|
||||
assert s.length() > position;
|
||||
|
||||
int numberOfOpenGroups = 0;
|
||||
int result = position;
|
||||
for (; result >= 0; result--) {
|
||||
|
||||
final MathType mathType = MathType.getType(s, result).getMathType();
|
||||
|
||||
if (CollectionsUtils.contains(mathType, MathType.digit, MathType.dot, MathType.grouping_separator)) {
|
||||
// continue
|
||||
} else if (mathType == MathType.close_group_symbol) {
|
||||
numberOfOpenGroups++;
|
||||
} else if (mathType == MathType.open_group_symbol) {
|
||||
numberOfOpenGroups--;
|
||||
} else {
|
||||
if (stop(s, numberOfOpenGroups, result)) break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean stop(String s, int numberOfOpenGroups, int i) {
|
||||
if (numberOfOpenGroups == 0) {
|
||||
if (i > 0) {
|
||||
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
|
||||
endsWithFinder.setI(i + 1);
|
||||
if (!CollectionsUtils.contains(MathType.function.getTokens(), FilterType.included, endsWithFinder)) {
|
||||
MathType type = MathType.getType(s, i).getMathType();
|
||||
if (type != MathType.constant) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class EndsWithFinder implements Finder<String> {
|
||||
|
||||
private int i;
|
||||
|
||||
@NotNull
|
||||
private final String targetString;
|
||||
|
||||
private EndsWithFinder(@NotNull String targetString) {
|
||||
this.targetString = targetString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(@Nullable String s) {
|
||||
return targetString.substring(0, i).endsWith(s);
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
public static String wrap(@NotNull JsclOperation operation, @NotNull String s) {
|
||||
return operation.name() + "(\"" + s + "\");";
|
||||
}
|
||||
|
Reference in New Issue
Block a user