コード例 #1
0
        static ReElement ParseSequence(ReParseContext context)
        {
            var choice   = new List <ReElement>();
            var sequence = new List <ReElement>();

            var abort = false;

            while (!context.End && !abort)
            {
                switch (context.Current)
                {
                case '[':
                    if (!context.MoveNext())
                    {
                        ThrowUnexpectedEnd();
                    }
                    sequence.Add(ParseCharSet(context));
                    if (context.End)
                    {
                        ThrowUnexpectedEnd();
                    }
                    if (context.Current != ']')
                    {
                        ThrowUnexpectedChar(context);
                    }
                    context.MoveNext();
                    break;

                case '(':
                    if (!context.MoveNext())
                    {
                        ThrowUnexpectedEnd();
                    }
                    sequence.Add(ParseSequence(context));
                    if (context.End)
                    {
                        ThrowUnexpectedEnd();
                    }
                    if (context.Current != ')')
                    {
                        ThrowUnexpectedChar(context);
                    }
                    context.MoveNext();
                    break;

                case ')':
                    abort = true;
                    break;

                case '|':
                    choice.Add(ReFactory.NewConcatenation(sequence));
                    sequence.Clear();
                    context.MoveNext();
                    break;

                case '.':
                    sequence.Add(ReFactory.NewSingleton(CharSet.LineBody));
                    context.MoveNext();
                    break;

                case '?':
                    if (sequence.Count == 0)
                    {
                        ThrowUnexpectedChar(context);
                    }
                    sequence[sequence.Count - 1] = ReFactory.NewRepetition(sequence[sequence.Count - 1], 0, 1);
                    context.MoveNext();
                    break;

                case '+':
                    if (sequence.Count == 0)
                    {
                        ThrowUnexpectedChar(context);
                    }
                    sequence[sequence.Count - 1] = ReFactory.NewRepetition(sequence[sequence.Count - 1], 1, null);
                    context.MoveNext();
                    break;

                case '*':
                    if (sequence.Count == 0)
                    {
                        ThrowUnexpectedChar(context);
                    }
                    sequence[sequence.Count - 1] = ReFactory.NewRepetition(sequence[sequence.Count - 1], 0, null);
                    context.MoveNext();
                    break;

                case '{':
                    if (sequence.Count == 0)
                    {
                        ThrowUnexpectedChar(context);
                    }
                    if (!context.MoveNext())
                    {
                        ThrowUnexpectedEnd();
                    }
                    sequence[sequence.Count - 1] = ParseRepitition(sequence[sequence.Count - 1], context);
                    if (context.Current != '}')
                    {
                        ThrowUnexpectedChar(context);
                    }
                    context.MoveNext();
                    break;

                case '\\':
                    if (!context.MoveNext())
                    {
                        ThrowUnexpectedEnd();
                    }
                    sequence.Add(ReFactory.NewSingleton(CharSet.New(ParseEscapeSequence(context))));
                    break;

                default:
                    sequence.Add(ReFactory.NewSingleton(CharSet.New(context.Current)));
                    context.MoveNext();
                    break;
                }
            }

            choice.Add(ReFactory.NewConcatenation(sequence));
            return(ReFactory.NewUnion(choice));
        }
コード例 #2
0
        static ReElement ParseCharSet(ReParseContext context)
        {
            var ranges = new List <CharRange>();
            var invert = false;

            if (context.Current == '^')
            {
                invert = true;
                if (!context.MoveNext())
                {
                    ThrowUnexpectedEnd();
                }
            }

            if (context.Current == ']')
            {
                ranges.Add(new CharRange(']', ']'));
                if (!context.MoveNext())
                {
                    ThrowUnexpectedEnd();
                }
            }

            var abort = false;

            while (!context.End && !abort)
            {
                switch (context.Current)
                {
                case ']':
                    abort = true;
                    break;

                case '-':
                    if (ranges.Count == 0)
                    {
                        ranges.Add(new CharRange('-', '-'));
                    }
                    else
                    {
                        var from = ranges[ranges.Count - 1].To;
                        if (!context.MoveNext())
                        {
                            ThrowUnexpectedEnd();
                        }
                        var to = context.Current;

                        if (to == ']')
                        {
                            ranges.Add(new CharRange('-', '-'));
                        }
                        else
                        {
                            if (!context.MoveNext())
                            {
                                ThrowUnexpectedEnd();
                            }

                            if (to == '\\')
                            {
                                to = ParseEscapeSequence(context);
                                if (context.End)
                                {
                                    ThrowUnexpectedEnd();
                                }
                            }

                            if (to < from)
                            {
                                ThrowBrokenCharRange(from, to);
                            }

                            ranges.Add(new CharRange(from, to));
                        }
                    }

                    break;

                case '\\':
                    if (!context.MoveNext())
                    {
                        ThrowUnexpectedEnd();
                    }
                    var c = ParseEscapeSequence(context);
                    ranges.Add(new CharRange(c, c));
                    break;

                default:
                    ranges.Add(new CharRange(context.Current, context.Current));
                    if (!context.MoveNext())
                    {
                        ThrowUnexpectedEnd();
                    }
                    break;
                }
            }

            var set = CharSet.New(ranges.ToArray());

            if (invert)
            {
                set = CharSet.Universal.Subtract(set);
            }

            return(ReFactory.NewSingleton(set));
        }