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;
  }
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);
  }
}
 public Generic parse(@Nonnull Parameters p, Generic previousSumElement) throws ParseException {
   return parsePostfix(registry.getNames(), content, previousSumElement, p);
 }