ParseExceptions pool

This commit is contained in:
serso 2016-01-24 22:13:44 +01:00
parent b482b83007
commit 88c1253609
21 changed files with 106 additions and 57 deletions

View File

@ -123,7 +123,7 @@ public class Expression extends Generic {
int index = position.intValue(); int index = position.intValue();
if (index < expression.length()) { if (index < expression.length()) {
throw new ParseException(Messages.msg_1, index, expression, index + 1); throw new ParseException(index, expression, Messages.msg_1, index + 1);
} }
return new Expression().init(generic); return new Expression().init(generic);

View File

@ -33,6 +33,7 @@ public class CompoundIdentifier implements Parser<String> {
// NOTE: '.' must be appended after parsing // NOTE: '.' must be appended after parsing
result.append(".").append(dotAndId); result.append(".").append(dotAndId);
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -25,6 +25,7 @@ public class ConstantParser implements Parser<Constant> {
try { try {
l.add(Subscript.parser.parse(p, previousSumElement)); l.add(Subscript.parser.parse(p, previousSumElement));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }
@ -33,6 +34,7 @@ public class ConstantParser implements Parser<Constant> {
try { try {
prime = Prime.parser.parse(p, previousSumElement); prime = Prime.parser.parse(p, previousSumElement);
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
} }
return new Constant(name, prime, ArrayUtils.toArray(l, new Generic[l.size()])); return new Constant(name, prime, ArrayUtils.toArray(l, new Generic[l.size()]));

View File

@ -10,6 +10,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
public class DoubleParser implements Parser<NumericWrapper> { public class DoubleParser implements Parser<NumericWrapper> {
@ -80,6 +81,7 @@ class FloatingPointLiteral implements Parser<Double> {
result.append(digitsParser.parse(p, previousSumElement)); result.append(digitsParser.parse(p, previousSumElement));
digits = true; digits = true;
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
} }
try { try {
@ -90,6 +92,8 @@ class FloatingPointLiteral implements Parser<Double> {
if (!digits) { if (!digits) {
p.position.setValue(pos0); p.position.setValue(pos0);
throw e; throw e;
} else {
p.exceptionsPool.release(e);
} }
} }
@ -103,6 +107,8 @@ class FloatingPointLiteral implements Parser<Double> {
if (!digits) { if (!digits) {
p.position.setValue(pos0); p.position.setValue(pos0);
throw e; throw e;
} else {
p.exceptionsPool.release(e);
} }
} }
@ -113,6 +119,8 @@ class FloatingPointLiteral implements Parser<Double> {
if (!point) { if (!point) {
p.position.setValue(pos0); p.position.setValue(pos0);
throw e; throw e;
} else {
p.exceptionsPool.release(e);
} }
} }
@ -124,7 +132,7 @@ class FloatingPointLiteral implements Parser<Double> {
try { try {
return nb.toDouble(doubleString); return nb.toDouble(doubleString);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ParseException(Messages.msg_8, p.position.intValue(), p.expression, doubleString); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_8, Collections.singletonList(doubleString));
} }
} }
} }

View File

@ -0,0 +1,28 @@
package jscl.text;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ExceptionsPool {
@Nonnull
private final List<ParseException> list = new ArrayList<>();
@Nonnull
public ParseException obtain(int position, @Nonnull String expression, @Nonnull String messageCode) {
return obtain(position, expression, messageCode, Collections.emptyList());
}
@Nonnull
public ParseException obtain(int position, @Nonnull String expression, @Nonnull String messageCode, @Nonnull List<?> messagesArgs) {
final ParseException exception = !list.isEmpty() ? list.remove(list.size() - 1) : new ParseException();
exception.set(position, expression, messageCode, messagesArgs);
return exception;
}
public void release(@Nonnull ParseException e) {
list.add(e);
}
}

View File

@ -25,6 +25,7 @@ public class ExpressionParser implements Parser<Generic> {
try { try {
result = result.add(PlusOrMinusTerm.parser.parse(p, result)); result = result.add(PlusOrMinusTerm.parser.parse(p, result));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -10,6 +10,7 @@ import jscl.util.ArrayUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public class ImplicitFunctionParser implements Parser<Function> { public class ImplicitFunctionParser implements Parser<Function> {
@ -25,7 +26,7 @@ public class ImplicitFunctionParser implements Parser<Function> {
final String name = ParserUtils.parseWithRollback(CompoundIdentifier.parser, pos0, previousSumElement, p); final String name = ParserUtils.parseWithRollback(CompoundIdentifier.parser, pos0, previousSumElement, p);
if (FunctionsRegistry.getInstance().getNames().contains(name) || OperatorsRegistry.getInstance().getNames().contains(name)) { if (FunctionsRegistry.getInstance().getNames().contains(name) || OperatorsRegistry.getInstance().getNames().contains(name)) {
p.position.setValue(pos0); p.position.setValue(pos0);
throw new ParseException(Messages.msg_6, p.position.intValue(), p.expression, name); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_6, Collections.singletonList(name));
} }
final List<Generic> subscripts = new ArrayList<Generic>(); final List<Generic> subscripts = new ArrayList<Generic>();
@ -33,6 +34,7 @@ public class ImplicitFunctionParser implements Parser<Function> {
try { try {
subscripts.add(Subscript.parser.parse(p, previousSumElement)); subscripts.add(Subscript.parser.parse(p, previousSumElement));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }
@ -41,6 +43,7 @@ public class ImplicitFunctionParser implements Parser<Function> {
try { try {
b = Derivation.parser.parse(p, previousSumElement); b = Derivation.parser.parse(p, previousSumElement);
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
b = new int[0]; b = new int[0];
} }
try { try {
@ -67,15 +70,12 @@ class Derivation implements Parser<int[]> {
} }
public int[] parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException { public int[] parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
int result[];
try { try {
result = new int[]{PrimeCharacters.parser.parse(p, previousSumElement)}; return new int[]{PrimeCharacters.parser.parse(p, previousSumElement)};
} catch (ParseException e) { } catch (ParseException e) {
result = SuperscriptList.parser.parse(p, previousSumElement); p.exceptionsPool.release(e);
} }
return SuperscriptList.parser.parse(p, previousSumElement);
return result;
} }
} }
@ -103,6 +103,7 @@ class SuperscriptList implements Parser<int[]> {
try { try {
result.add(CommaAndInteger.parser.parse(p, previousSumElement)); result.add(CommaAndInteger.parser.parse(p, previousSumElement));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -6,6 +6,7 @@ import jscl.text.msg.Messages;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collections;
public class IntegerParser implements Parser<Integer> { public class IntegerParser implements Parser<Integer> {
@ -46,7 +47,7 @@ public class IntegerParser implements Parser<Integer> {
result.append(c); result.append(c);
} else { } else {
p.position.setValue(pos0); p.position.setValue(pos0);
throw new ParseException(Messages.msg_7, p.position.intValue(), p.expression); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_7);
} }
while (p.position.intValue() < p.expression.length() && nb.getAcceptableCharacters().contains(p.expression.charAt(p.position.intValue()))) { while (p.position.intValue() < p.expression.length() && nb.getAcceptableCharacters().contains(p.expression.charAt(p.position.intValue()))) {
@ -59,7 +60,7 @@ public class IntegerParser implements Parser<Integer> {
try { try {
return nb.toInteger(number); return nb.toInteger(number);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ParseException(Messages.msg_8, p.position.intValue(), p.expression, number); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_8, Collections.singletonList(number));
} }
} }
} }

View File

@ -7,6 +7,7 @@ import jscl.text.msg.Messages;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collections;
public class JsclIntegerParser implements Parser<JsclInteger> { public class JsclIntegerParser implements Parser<JsclInteger> {
@ -33,7 +34,7 @@ public class JsclIntegerParser implements Parser<JsclInteger> {
try { try {
return nb.toJsclInteger(number); return nb.toJsclInteger(number);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ParseException(Messages.msg_8, p.position.intValue(), p.expression, number); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_8, Collections.singletonList(number));
} }
} }
} }

View File

@ -34,6 +34,7 @@ public class MatrixParser implements Parser<Matrix> {
try { try {
vectors.add(CommaAndVector.parser.parse(p, previousSumElement)); vectors.add(CommaAndVector.parser.parse(p, previousSumElement));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -1,7 +1,6 @@
package jscl.text; package jscl.text;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.Matrix;
import jscl.math.MatrixVariable; import jscl.math.MatrixVariable;
import jscl.math.Variable; import jscl.math.Variable;
@ -14,12 +13,6 @@ class MatrixVariableParser implements Parser<Variable> {
} }
public Variable parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException { public Variable parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
Matrix m; return new MatrixVariable(MatrixParser.parser.parse(p, previousSumElement));
try {
m = (Matrix) MatrixParser.parser.parse(p, previousSumElement);
} catch (ParseException e) {
throw e;
}
return new MatrixVariable(m);
} }
} }

View File

@ -27,6 +27,7 @@ public class NumeralBaseParser implements Parser<NumeralBase> {
result = numeralBase; result = numeralBase;
break; break;
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
} }
} }

View File

@ -34,6 +34,8 @@ public class ParameterListParser implements Parser<Generic[]> {
if (minNumberOfParameters > 0) { if (minNumberOfParameters > 0) {
p.position.setValue(pos0); p.position.setValue(pos0);
throw e; throw e;
} else {
p.exceptionsPool.release(e);
} }
} }
@ -41,6 +43,7 @@ public class ParameterListParser implements Parser<Generic[]> {
try { try {
result.add(CommaAndExpression.parser.parse(p, previousSumElement)); result.add(CommaAndExpression.parser.parse(p, previousSumElement));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -1,56 +1,61 @@
package jscl.text; package jscl.text;
import jscl.text.msg.JsclMessage; import org.solovyev.common.collections.Collections;
import org.solovyev.common.msg.Message; import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageLevel; import org.solovyev.common.msg.MessageLevel;
import org.solovyev.common.msg.MessageType; import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle;
public class ParseException extends Exception implements Message { public class ParseException extends Exception implements Message {
private int position;
@Nonnull @Nonnull
private final Message message; private String expression;
private final int position;
@Nonnull @Nonnull
private final String expression; private String messageCode;
@Nonnull
private List<?> parameters;
public ParseException(@Nonnull String messageCode, int position, @Nonnull String expression, Object... parameters) { ParseException() {
this.message = new JsclMessage(messageCode, MessageType.error, parameters);
this.position = position;
this.expression = expression;
} }
public ParseException(@Nonnull Message message, int position, @Nonnull String expression) { public ParseException(int position, @Nonnull String expression, @Nonnull String messageCode, @Nullable Object... parameters) {
this.message = message; set(position, expression, messageCode, Collections.asList(parameters));
}
void set(int position, @Nonnull String expression, @Nonnull String messageCode, @Nonnull List<?> parameters) {
this.position = position; this.position = position;
this.expression = expression; this.expression = expression;
this.messageCode = messageCode;
this.parameters = parameters;
} }
@Nonnull @Nonnull
public String getMessageCode() { public String getMessageCode() {
return this.message.getMessageCode(); return messageCode;
} }
@Nonnull @Nonnull
public List<Object> getParameters() { public List<Object> getParameters() {
return this.message.getParameters(); return (List<Object>) parameters;
} }
@Nonnull @Nonnull
@Override @Override
public MessageLevel getMessageLevel() { public MessageLevel getMessageLevel() {
return this.message.getMessageLevel(); return MessageType.error;
} }
@Nonnull @Nonnull
@Override @Override
public String getLocalizedMessage(@Nonnull Locale locale) { public String getLocalizedMessage(@Nonnull Locale locale) {
return this.message.getLocalizedMessage(locale); final ResourceBundle rb = ResourceBundle.getBundle("jscl/text/msg/messages", locale);
return rb.getString(getMessageCode());
} }
public int getPosition() { public int getPosition() {
@ -67,20 +72,21 @@ public class ParseException extends Exception implements Message {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
ParseException that = (ParseException) o; ParseException exception = (ParseException) o;
if (position != that.position) return false; if (position != exception.position) return false;
if (!expression.equals(that.expression)) return false; if (!expression.equals(exception.expression)) return false;
if (!message.equals(that.message)) return false; if (!messageCode.equals(exception.messageCode)) return false;
return parameters.equals(exception.parameters);
return true;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = message.hashCode(); int result = position;
result = 31 * result + position;
result = 31 * result + expression.hashCode(); result = 31 * result + expression.hashCode();
result = 31 * result + messageCode.hashCode();
result = 31 * result + parameters.hashCode();
return result; return result;
} }
} }

View File

@ -39,6 +39,9 @@ public interface Parser<T> {
@Nonnull @Nonnull
public final MathContext context; public final MathContext context;
@Nonnull
public final ExceptionsPool exceptionsPool = new ExceptionsPool();
/** /**
* @param expression expression to be parsed * @param expression expression to be parsed
* @param position current position of expression. Side effect: if parsing is successful this parameter should be increased on the number of parsed letters (incl whitespaces etc) * @param position current position of expression. Side effect: if parsing is successful this parameter should be increased on the number of parsed letters (incl whitespaces etc)

View File

@ -2,6 +2,7 @@ package jscl.text;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.text.msg.Messages; import jscl.text.msg.Messages;
import org.solovyev.common.collections.Collections;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -67,7 +68,7 @@ public class ParserUtils {
@Nonnull String messageId, @Nonnull String messageId,
Object... parameters) throws ParseException { Object... parameters) throws ParseException {
final MutableInt position = p.position; final MutableInt position = p.position;
final ParseException parseException = new ParseException(messageId, position.intValue(), p.expression, parameters); final ParseException parseException = p.exceptionsPool.obtain(position.intValue(), p.expression, messageId, Collections.asList(parameters));
position.setValue(pos0); position.setValue(pos0);
throw parseException; throw parseException;
} }

View File

@ -9,6 +9,7 @@ import jscl.text.msg.Messages;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -28,11 +29,11 @@ public class PostfixFunctionsParser implements Parser<Generic> {
private static Generic parsePostfix(@Nonnull List<PostfixFunctionParser> parsers, private static Generic parsePostfix(@Nonnull List<PostfixFunctionParser> parsers,
Generic content, Generic content,
@Nullable final Generic previousSumElement, @Nullable final Generic previousSumElement,
@Nonnull final Parameters parseParameters) throws ParseException { @Nonnull final Parameters p) throws ParseException {
Generic result = content; Generic result = content;
for (PostfixFunctionParser parser : parsers) { for (PostfixFunctionParser parser : parsers) {
final PostfixFunctionParser.Result postfixResult = parser.parse(parseParameters, previousSumElement); final PostfixFunctionParser.Result postfixResult = parser.parse(p, previousSumElement);
if (postfixResult.isPostfixFunction()) { if (postfixResult.isPostfixFunction()) {
final Operator postfixFunction; final Operator postfixFunction;
@ -44,13 +45,13 @@ public class PostfixFunctionsParser implements Parser<Generic> {
if (postfixFunction == null) { if (postfixFunction == null) {
if (TripleFactorial.NAME.equals(postfixResult.getPostfixFunctionName())) { if (TripleFactorial.NAME.equals(postfixResult.getPostfixFunctionName())) {
throw new ParseException(Messages.msg_18, parseParameters.position.intValue(), parseParameters.expression); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_18);
} else { } else {
throw new ParseException(Messages.msg_4, parseParameters.position.intValue(), parseParameters.expression, postfixResult.getPostfixFunctionName()); throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_4, Collections.singletonList(postfixResult.getPostfixFunctionName()));
} }
} }
result = parsePostfix(parsers, postfixFunction.expressionValue(), previousSumElement, parseParameters); result = parsePostfix(parsers, postfixFunction.expressionValue(), previousSumElement, p);
} }
} }

View File

@ -31,6 +31,7 @@ class TermParser implements Parser<Generic> {
result = result.multiply(s); result = result.multiply(s);
s = b; s = b;
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
try { try {
Generic b = DivideFactor.parser.parse(p, null); Generic b = DivideFactor.parser.parse(p, null);
if (s.compareTo(JsclInteger.valueOf(1)) == 0) if (s.compareTo(JsclInteger.valueOf(1)) == 0)
@ -38,6 +39,7 @@ class TermParser implements Parser<Generic> {
else else
s = new Fraction(GenericVariable.content(s, true), GenericVariable.content(b, true)).expressionValue(); s = new Fraction(GenericVariable.content(s, true), GenericVariable.content(b, true)).expressionValue();
} catch (ParseException e2) { } catch (ParseException e2) {
p.exceptionsPool.release(e2);
break; break;
} }
} }

View File

@ -33,6 +33,7 @@ class UnsignedFactor implements Parser {
try { try {
list.add(PowerExponentParser.parser.parse(p, null)); list.add(PowerExponentParser.parser.parse(p, null));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -34,6 +34,7 @@ public class VectorParser implements Parser<JsclVector> {
try { try {
result.add(CommaAndExpression.parser.parse(p, previousSumElement)); result.add(CommaAndExpression.parser.parse(p, previousSumElement));
} catch (ParseException e) { } catch (ParseException e) {
p.exceptionsPool.release(e);
break; break;
} }
} }

View File

@ -1,7 +1,6 @@
package jscl.text; package jscl.text;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.JsclVector;
import jscl.math.Variable; import jscl.math.Variable;
import jscl.math.VectorVariable; import jscl.math.VectorVariable;
@ -14,12 +13,6 @@ public class VectorVariableParser implements Parser<Variable> {
} }
public Variable parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException { public Variable parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
JsclVector result; return new VectorVariable(VectorParser.parser.parse(p, previousSumElement));
try {
result = VectorParser.parser.parse(p, previousSumElement);
} catch (ParseException e) {
throw e;
}
return new VectorVariable(result);
} }
} }