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();
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);

View File

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

View File

@ -25,6 +25,7 @@ public class ConstantParser implements Parser<Constant> {
try {
l.add(Subscript.parser.parse(p, previousSumElement));
} catch (ParseException e) {
p.exceptionsPool.release(e);
break;
}
}
@ -33,6 +34,7 @@ public class ConstantParser implements Parser<Constant> {
try {
prime = Prime.parser.parse(p, previousSumElement);
} catch (ParseException e) {
p.exceptionsPool.release(e);
}
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class DoubleParser implements Parser<NumericWrapper> {
@ -80,6 +81,7 @@ class FloatingPointLiteral implements Parser<Double> {
result.append(digitsParser.parse(p, previousSumElement));
digits = true;
} catch (ParseException e) {
p.exceptionsPool.release(e);
}
try {
@ -90,6 +92,8 @@ class FloatingPointLiteral implements Parser<Double> {
if (!digits) {
p.position.setValue(pos0);
throw e;
} else {
p.exceptionsPool.release(e);
}
}
@ -103,6 +107,8 @@ class FloatingPointLiteral implements Parser<Double> {
if (!digits) {
p.position.setValue(pos0);
throw e;
} else {
p.exceptionsPool.release(e);
}
}
@ -113,6 +119,8 @@ class FloatingPointLiteral implements Parser<Double> {
if (!point) {
p.position.setValue(pos0);
throw e;
} else {
p.exceptionsPool.release(e);
}
}
@ -124,7 +132,7 @@ class FloatingPointLiteral implements Parser<Double> {
try {
return nb.toDouble(doubleString);
} 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 {
result = result.add(PlusOrMinusTerm.parser.parse(p, result));
} catch (ParseException e) {
p.exceptionsPool.release(e);
break;
}
}

View File

@ -10,6 +10,7 @@ import jscl.util.ArrayUtils;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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);
if (FunctionsRegistry.getInstance().getNames().contains(name) || OperatorsRegistry.getInstance().getNames().contains(name)) {
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>();
@ -33,6 +34,7 @@ public class ImplicitFunctionParser implements Parser<Function> {
try {
subscripts.add(Subscript.parser.parse(p, previousSumElement));
} catch (ParseException e) {
p.exceptionsPool.release(e);
break;
}
}
@ -41,6 +43,7 @@ public class ImplicitFunctionParser implements Parser<Function> {
try {
b = Derivation.parser.parse(p, previousSumElement);
} catch (ParseException e) {
p.exceptionsPool.release(e);
b = new int[0];
}
try {
@ -67,15 +70,12 @@ class Derivation implements Parser<int[]> {
}
public int[] parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
int result[];
try {
result = new int[]{PrimeCharacters.parser.parse(p, previousSumElement)};
return new int[]{PrimeCharacters.parser.parse(p, previousSumElement)};
} catch (ParseException e) {
result = SuperscriptList.parser.parse(p, previousSumElement);
p.exceptionsPool.release(e);
}
return result;
return SuperscriptList.parser.parse(p, previousSumElement);
}
}
@ -103,6 +103,7 @@ class SuperscriptList implements Parser<int[]> {
try {
result.add(CommaAndInteger.parser.parse(p, previousSumElement));
} catch (ParseException e) {
p.exceptionsPool.release(e);
break;
}
}

View File

@ -6,6 +6,7 @@ import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
public class IntegerParser implements Parser<Integer> {
@ -46,7 +47,7 @@ public class IntegerParser implements Parser<Integer> {
result.append(c);
} else {
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()))) {
@ -59,7 +60,7 @@ public class IntegerParser implements Parser<Integer> {
try {
return nb.toInteger(number);
} 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.Nullable;
import java.util.Collections;
public class JsclIntegerParser implements Parser<JsclInteger> {
@ -33,7 +34,7 @@ public class JsclIntegerParser implements Parser<JsclInteger> {
try {
return nb.toJsclInteger(number);
} 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 {
vectors.add(CommaAndVector.parser.parse(p, previousSumElement));
} catch (ParseException e) {
p.exceptionsPool.release(e);
break;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -39,6 +39,9 @@ public interface Parser<T> {
@Nonnull
public final MathContext context;
@Nonnull
public final ExceptionsPool exceptionsPool = new ExceptionsPool();
/**
* @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)

View File

@ -2,6 +2,7 @@ package jscl.text;
import jscl.math.Generic;
import jscl.text.msg.Messages;
import org.solovyev.common.collections.Collections;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -67,7 +68,7 @@ public class ParserUtils {
@Nonnull String messageId,
Object... parameters) throws ParseException {
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);
throw parseException;
}

View File

@ -9,6 +9,7 @@ import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@ -28,11 +29,11 @@ public class PostfixFunctionsParser implements Parser<Generic> {
private static Generic parsePostfix(@Nonnull List<PostfixFunctionParser> parsers,
Generic content,
@Nullable final Generic previousSumElement,
@Nonnull final Parameters parseParameters) throws ParseException {
@Nonnull final Parameters p) throws ParseException {
Generic result = content;
for (PostfixFunctionParser parser : parsers) {
final PostfixFunctionParser.Result postfixResult = parser.parse(parseParameters, previousSumElement);
final PostfixFunctionParser.Result postfixResult = parser.parse(p, previousSumElement);
if (postfixResult.isPostfixFunction()) {
final Operator postfixFunction;
@ -44,13 +45,13 @@ public class PostfixFunctionsParser implements Parser<Generic> {
if (postfixFunction == null) {
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 {
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);
s = b;
} catch (ParseException e) {
p.exceptionsPool.release(e);
try {
Generic b = DivideFactor.parser.parse(p, null);
if (s.compareTo(JsclInteger.valueOf(1)) == 0)
@ -38,6 +39,7 @@ class TermParser implements Parser<Generic> {
else
s = new Fraction(GenericVariable.content(s, true), GenericVariable.content(b, true)).expressionValue();
} catch (ParseException e2) {
p.exceptionsPool.release(e2);
break;
}
}

View File

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

View File

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

View File

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