예제 #1
0
 /// <summary>
 /// Parses the version expression.
 /// </summary>
 public static bool TryParse(string value, out ComposerVersionExpression expression) => TryParse(value.AsSpan(), out expression);
        /// <summary>
        /// Parses the version expression.
        /// </summary>
        public static bool TryParse(ReadOnlySpan <char> value, out ComposerVersionExpression expression)
        {
            expression = default;
            value      = value.Trim();

            // ranges
            var range = value.IndexOf(Tokens.Range); // regexp

            if (range > 0)
            {
                // A - B
                if (ComposerVersion.TryParse(value.Slice(0, range), out var fromversion) &&
                    ComposerVersion.TryParse(value.Slice(range + Tokens.Range.Length), out var toversion))
                {
                    expression = new RangeExpression {
                        From = fromversion, To = toversion,
                    };
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else if (range == 0)
            {
                // - B
                return(false);
            }

            // AND, highest precedence
            var and = Tokens.AndRegex.Match(value.ToString());

            if (and.Success)
            {
                var cap = and.Groups[1];

                if (TryParse(value.Slice(0, cap.Index), out var leftexpr) &&
                    TryParse(value.Slice(cap.Index + cap.Length), out var rightexpr))
                {
                    expression = new AndExpression {
                        Left = leftexpr, Right = rightexpr,
                    };
                    return(true);
                }
            }

            // OR
            var or = value.IndexOf(Tokens.Or);

            if (or > 0)
            {
                // A || B
                if (TryParse(value.Slice(0, or), out var left) &&
                    TryParse(value.Slice(or + Tokens.Or.Length), out var right))
                {
                    expression = new OrExpression {
                        Left = left, Right = right,
                    };
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else if (or == 0)
            {
                // invalid
                return(false);
            }

            //
            if (value.IsEmpty)
            {
                return(false);
            }

            // unary version ranges
            Operation op;

            if (value[0] == Tokens.CaretVersion)
            {
                op    = Operation.CaretVersionRange;
                value = value.Slice(1);
            }
            else if (value[0] == Tokens.TildeVersion)
            {
                op    = Operation.TildeVersionRange;
                value = value.Slice(1);
            }
            else if (value.StartsWith(Tokens.Lte))
            {
                op    = Operation.LessThanOrEqual;
                value = value.Slice(Tokens.Lte.Length);
            }
            else if (value.StartsWith(Tokens.Gte))
            {
                op    = Operation.GreaterThanOrEqual;
                value = value.Slice(Tokens.Gte.Length);
            }
            else if (value.StartsWith(Tokens.Ne))
            {
                op    = Operation.NotEqual;
                value = value.Slice(Tokens.Ne.Length);
            }
            else if (value[0] == Tokens.Lt)
            {
                op    = Operation.LessThan;
                value = value.Slice(1);
            }
            else if (value[0] == Tokens.Gt)
            {
                op    = Operation.GreaterThan;
                value = value.Slice(1);
            }
            else
            {
                op = Operation.Exact;
            }

            if (ComposerVersion.TryParse(value, out var version))
            {
                if (op == Operation.Exact)
                {
                    expression = new ExactVersionExpression {
                        Version = version
                    };
                }
                else
                {
                    expression = new UnaryExpression(op)
                    {
                        Version = version,
                    };
                }

                return(true);
            }

            //
            return(false);
        }