package jscl.text;
import jscl.math.Generic;
import jscl.math.function.PostfixFunctionsRegistry;
import jscl.math.operator.Operator;
import jscl.math.operator.TripleFactorial;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import static java.util.Collections.singletonList;
public class PostfixFunctionsParser implements Parser<Generic> {
private static final PostfixFunctionsRegistry registry = PostfixFunctionsRegistry.getInstance();
private static final PostfixFunctionParser tripleFactorialParser = new PostfixFunctionParser(TripleFactorial.NAME);
@Nonnull
private final Generic content;
public PostfixFunctionsParser(@Nonnull Generic content) {
this.content = content;
}
private static Generic parsePostfix(@Nonnull List<String> names,
final Generic content,
@Nullable final Generic previousSumElement,
@Nonnull final Parameters p) throws ParseException {
checkTripleFactorial(previousSumElement, p);
for (int i = 0; i < names.size(); i++) {
final PostfixFunctionParser parser = new PostfixFunctionParser(names.get(i));
final String functionName = parser.parse(p, previousSumElement);
if (functionName == null) {
continue;
}
final Generic[] parameters = previousSumElement == null ? new Generic[]{content} : new Generic[]{content, previousSumElement};
final Operator function = registry.get(functionName, parameters);
if (function != null) {
return parsePostfix(names, function.expressionValue(), previousSumElement, p);
}
throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_4, singletonList(functionName));
}
return content;
}
private static void checkTripleFactorial(@Nullable Generic previousSumElement, @Nonnull Parameters p) throws ParseException {
if (tripleFactorialParser.parse(p, previousSumElement) != null) {
throw p.exceptionsPool.obtain(p.position.intValue(), p.expression, Messages.msg_18);
}
}
public Generic parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
return parsePostfix(registry.getNames(), content, previousSumElement, p);
}
}