Пример #1
0
        /// <summary>
        /// Parses the given pattern and returns the expression tree
        /// </summary>
        /// <param name="pattern">String regular expression pattern</param>
        /// <returns>Expression tree relating to the supplied patterns</returns>
        private static Node ParsePattern(string pattern)
        {
            var processedPattern = Preprocess(pattern);
            var iterator         = new PatternIterator(processedPattern);

            return(Expression(ref iterator));
        }
Пример #2
0
        /// <summary>
        /// Returns a character <see cref="Node"/>
        /// </summary>
        /// <remarks>
        /// char => .
        /// </remarks>
        /// <param name="iterator">Pattern iterator giving access to the character stream</param>
        /// <returns></returns>
        private static Node Char(ref PatternIterator iterator)
        {
            var data = iterator.Peek();

            if (!(char.IsLetterOrDigit(data) || data == '\0'))
            {
                throw new InvalidOperationException($"Parse error: expected alphanumeric, got {iterator.Peek()} at {iterator.Position}");
            }

            return(new CharacterNode(iterator.Pop()));
        }
Пример #3
0
        /// <summary>
        /// Returns an expression <see cref="Node"/>
        /// </summary>
        /// <remarks>
        /// expr = concat '|' expr | concat
        /// </remarks>
        /// <param name="iterator">Pattern iterator giving access to the character stream</param>
        /// <returns></returns>
        private static Node Expression(ref PatternIterator iterator)
        {
            var left = Concat(ref iterator);

            switch (iterator.Peek())
            {
            case '|':
                iterator.Pop();
                return(new AlternativeNode(left, Expression(ref iterator)));

            default:
                return(left);
            }
        }
Пример #4
0
        /// <summary>
        /// Returns a sequential <see cref="Node"/>
        /// </summary>
        /// <remarks>
        /// concat => rep concat | rep
        /// </remarks>
        /// <param name="iterator">Pattern iterator giving access to the character stream</param>
        /// <returns></returns>
        private static Node Concat(ref PatternIterator iterator)
        {
            var left = Rep(ref iterator);

            switch (iterator.Peek())
            {
            case '.':
                iterator.Pop();
                return(new ConcatenationNode(left, Concat(ref iterator)));

            default:
                return(left);
            }
        }
Пример #5
0
        /// <summary>
        /// Returns an atomic <see cref="Node"/>
        /// </summary>
        /// <remarks>
        /// atom => char | '(' expr ')'
        /// </remarks>
        /// <param name="iterator">Pattern iterator giving access to the character stream</param>
        /// <returns></returns>
        private static Node Atom(ref PatternIterator iterator)
        {
            switch (iterator.Peek())
            {
            case '(':
                iterator.Pop();
                var expression = Expression(ref iterator);
                var next       = iterator.Pop();
                if (next != ')')
                {
                    throw new ParseException(iterator.Data, iterator.Position, $"Expected ')' but received '{next}'");
                }
                return(expression);

            default:
                return(Char(ref iterator));
            }
        }
Пример #6
0
        /// <summary>
        /// Returns a repeating <see cref="Note"/>
        /// </summary>
        /// <remarks>
        /// rep => atom '*' | atom '?' | atom '+' | atom
        /// </remarks>
        /// <param name="iterator">Pattern iterator giving access to the character stream</param>
        /// <returns></returns>
        private static Node Rep(ref PatternIterator iterator)
        {
            var node = Atom(ref iterator);

            switch (iterator.Peek())
            {
            case '*':
                iterator.Pop();
                return(new OptionalRepeatingNode(node));

            case '?':
                iterator.Pop();
                return(new OptionalNode(node));

            case '+':
                iterator.Pop();
                return(new RequiredRepeatingNode(node));

            default:
                return(node);
            }
        }