private static List <State> ParseRepetitionRange(IPrattParseContext <char> ctx, List <State> states, IParser <char, int> digits)
    {
        if (states.Last().Type == StateType.EndOfInput)
        {
            throw new RegexException("Cannot quantify the end anchor $");
        }

        int min   = 0;
        var first = ctx.TryParse(digits);

        if (first.Success)
        {
            min = first.Value;
        }

        var comma = ctx.TryParse(MatchChar(','));

        if (!comma.Success)
        {
            ctx.Expect(MatchChar('}'));
            // No comma, so we must have {X} form
            if (!first.Success)
            {
                throw new RegexException("Invalid range specifier. Must be one of {X} {X,} {,Y} or {X,Y}");
            }
            return(State.SetPreviousStateRange(states, min, min));
        }

        // At this point we might have X, X,Y or ,Y
        // In any case, min is filled in now with either a value or 0
        var second = ctx.TryParse(digits);

        ctx.Expect(MatchChar('}'));
        return(State.SetPreviousStateRange(states, min, second.Success ? second.Value : int.MaxValue));
    }
    private static List <State> ParseAlternation(IPrattParseContext <char, List <State> > ctx, List <State> states)
    {
        var options = new List <List <State> >()
        {
            states
        };

        while (true)
        {
            var option = ctx.TryParse(0);
            if (!option.Success || option.Value.Count == 0)
            {
                break;
            }

            options.Add(option.Value);
        }

        if (options.Count == 1)
        {
            return(states);
        }

        return(new List <State>
        {
            new State("alternation")
            {
                Type = StateType.Alternation,
                Alternations = options
            }
        });
    }
    private static (char low, char high) ParseCharacterRange(IPrattParseContext <char> ctx, char c)
    {
        var low  = c;
        var next = ctx.Input.Peek();

        if (next != '-')
        {
            return(low, low);
        }

        // We're keeping the peek'd char (dash) so advance input and keep going
        ctx.Input.GetNext();
        c = ctx.Input.GetNext();
        if (c == ']')
        {
            throw new RegexException("Unexpected ] after -. Expected end of range. Did you mean '\\]'?");
        }

        c = GetUnescapedCharacter(ctx, c);

        var high = c;

        if (high < low)
        {
            throw new RegexException($"Invalid range {high}-{low} should be {low}-{high}");
        }

        return(low, high);
    }
    private static List <State> ParseCharacterClass(IPrattParseContext <char> ctx, List <State>?states)
    {
        var invertResult = ctx.TryParse(MatchChar('^'));
        var ranges       = new List <(char low, char high)>();

        while (true)
        {
            if (ctx.Input.IsAtEnd)
            {
                throw new RegexException("Incomplete character class");
            }

            var c = ctx.Input.GetNext();
            if (c == ']')
            {
                break;
            }

            c = GetUnescapedCharacter(ctx, c);

            var range = ParseCharacterRange(ctx, c);
            ranges.Add(range);
        }

        if (ranges.Count == 0)
        {
            throw new RegexException("Empty character class");
        }

        var matcher = new CharacterMatcher(invertResult.Success, ranges);

        return(State.AddMatch(states, c => matcher.IsMatch(c), "class"));
    }
    private static char GetUnescapedCharacter(IPrattParseContext <char> ctx, char c)
    {
        if (c != '\\')
        {
            return(c);
        }

        if (ctx.Input.IsAtEnd)
        {
            throw new RegexException("Expected character, found end");
        }

        return(ctx.Input.GetNext());
    }
Ejemplo n.º 6
0
 public IOption <IPrattToken <TOutput> > LeftDenominator(IPrattParseContext <TInput, TOutput> context, IPrattToken left) => FailureOption <IPrattToken <TOutput> > .Instance;
Ejemplo n.º 7
0
 public IOption <IPrattToken <TOutput> > LeftDenominator(IPrattParseContext <TInput, TOutput> context, IPrattToken left)
 => _parselet.Led(context, left, this);
Ejemplo n.º 8
0
 public IOption <IPrattToken <TOutput> > NullDenominator(IPrattParseContext <TInput, TOutput> context)
 => _parselet.Nud(context, this);