public bool TryParse(PrioritizedString expr, ParameterInfo paramInfo, out Expression parsed)
        {
            expr = expr.Trim();

            foreach (var constName in ConstantsSorted.Where(constName => expr.Input == constName))
            {
                parsed = Expression.Constant(Constants[constName]);
                return(true);
            }
            parsed = null;
            return(false);
        }
        public bool TryParse(PrioritizedString expr, ParameterInfo paramInfo, out Expression parsed)
        {
            expr = expr.Trim();
            var exprStr = expr.Input;

            if (!Brackets.AreMatching(exprStr.First(), exprStr.Last()))
            {
                parsed = null;
                return(false);
            }

            var exprWithoutBrackets = expr.Substring(1, expr.Input.Length - 2);

            parsed = Combinator.ParseFunctionalExpression(exprWithoutBrackets, paramInfo);
            return(true);
        }
        public bool TryParse(PrioritizedString expr, ParameterInfo paramInfo, out Expression parsed)
        {
            expr = expr.Trim();
            if (double.TryParse(
                    expr.Input,
                    NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
                    CultureInfo.InvariantCulture,
                    out var num)
                )
            {
                parsed = Expression.Constant(num);
                return(true);
            }

            parsed = default;
            return(false);
        }
        public bool TryParse(PrioritizedString expr, ParameterInfo paramInfo, out Expression parsed)
        {
            expr = expr.Trim();
            var exprStr = expr.Input;

            if (paramInfo.Parameters.TryGetValue(exprStr, out var param))
            {
                parsed = param;
                return(true);
            }

            if (paramInfo.MainParameter is null && ParameterRe.IsMatch(exprStr))
            {
                paramInfo.MainParameter = exprStr;
                var mainParam = Expression.Parameter(typeof(double), exprStr);
                paramInfo.Parameters[exprStr] = mainParam;
                parsed = mainParam;
                return(true);
            }

            parsed = default;
            return(false);
        }
        public bool TryParse(PrioritizedString expr, ParameterInfo paramInfo, out Expression parsed)
        {
            expr = expr.Trim();

            bool isUnaryPlus;

            if (expr.Input.StartsWith("+"))
            {
                isUnaryPlus = true;
            }
            else if (expr.Input.StartsWith("-"))
            {
                isUnaryPlus = false;
            }
            else
            {
                parsed = default;
                return(false);
            }

            var arg = expr.Substring(1, expr.Length - 1).Trim();

            if (arg.Length == 0)
            {
                throw new ParseException("Found plus sign without argument");
            }
            if (arg.Input[0] == '-' || arg.Input[0] == '+')
            {
                throw new ParseException("Unary minus/plus cannot be followed by unary minus/plus");
            }
            parsed = isUnaryPlus
                ? Combinator.Parse(arg, paramInfo, Order)
                : Expression.Negate(Combinator.Parse(arg, paramInfo, Order));

            return(true);
        }