accept(param, type = null, defValue, flat = true, allowSingleValue = false) {
        // TODO: remove this array check
        if (Array.isArray(type))
            type = type[0];
        if (param == null && defValue === undefined) {
            throw FormulaError.ARG_MISSING([type]);
        } else if (param == null)
            return defValue;

        if (typeof param !== "object" || Array.isArray(param))
            return param;

        const isArray = param.isArray;
        if (param.value != null) param = param.value;

        // return an un-parsed type.
        if (type == null)
            return param;

        if (param instanceof FormulaError)
            throw param;

        if (type === Types.ARRAY) {
            if (Array.isArray(param)) {
                return flat ? this.flattenDeep(param) : param;
            } else if (param instanceof Collection) {
                throw FormulaError.VALUE;
            } else if (allowSingleValue) {
                return flat ? [param] : [[param]];
            }
            throw FormulaError.VALUE;
        } else if (type === Types.COLLECTIONS) {
            return param;
        }

        // the only possible type for expectSingle=true are: string, boolean, number;
        // If array encountered, extract the first element.
        // extract first element from array
        if (isArray) {
            param = param[0][0];
        }
        const paramType = this.type(param);
        if (type === Types.STRING) {
            if (paramType === Types.BOOLEAN)
                param = param ? 'TRUE' : 'FALSE';
            else
                param = `${param}`
        } else if (type === Types.BOOLEAN) {
            if (paramType === Types.STRING)
                throw FormulaError.VALUE;
            if (paramType === Types.NUMBER)
                param = Boolean(param);
        } else if (type === Types.NUMBER) {
            param = this.acceptNumber(param, false);
        } else if (type === Types.NUMBER_NO_BOOLEAN) {
            param = this.acceptNumber(param, false, false);
        } else {
            throw FormulaError.VALUE;
        }
        return param;
    }
Check if the param valid, return the parsed param.
If type is not given, return the un-parsed param.
@param {*} param
@param {number|null} [type] - The expected type
          NUMBER: Expect a single number,
          ARRAY: Expect an flatten array,
          BOOLEAN: Expect a single boolean,
          STRING: Expect a single string,
          COLLECTIONS: Expect an Array of the above types
          null: Do not parse the value, return it directly.
          The collection is not a flatted array.
@param {*} [defValue] - Default value if the param is not given.
              if undefined, this param is required, a Error will throw if not given.
              if null, and param is undefined, null will be returned.
@param {boolean} [flat=true] - If the array should be flattened,
                     only applicable when type is ARRAY.
                     If false, collection is disallowed.
@param {boolean} allowSingleValue - If pack single value into 2d array,
                    only applicable when type is ARRAY.
@return {string|number|boolean|{}|Array}