Example #1
0
        public IParseResult TryConvertToTokenStream(IStringStream inputStream, out ITokenStream tokenStream)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException();
            }

            tokenStream = new TokenStream();

            while (!inputStream.IsEmpty())
            {
                var character = inputStream.LookAhead(0);

                if (!_parserFactory.TryGetTokenParser(character, out var tokenParser))
                {
                    return(new FailureParseResult(inputStream.CurrentPosition, RegSeedErrorType.InvalidInput));
                }

                var parseResult = tokenParser.TryGetToken(inputStream, out var token);

                if (!parseResult.IsSuccess)
                {
                    return(parseResult);
                }

                tokenStream.Append(token);
            }

            return(new SuccessParseResult(inputStream.CurrentPosition));
        }
Example #2
0
        private static void PopAndAppendWhileIsDigit(IStringStream stream, ref int initialPopCalls, ref string numberString)
        {
            var charCandidate = stream.LookAhead(initialPopCalls);

            while (charCandidate.Length == 1 && char.IsDigit(charCandidate[0]))
            {
                numberString = $"{numberString}{charCandidate}";
                initialPopCalls++;

                if (initialPopCalls >= stream.Count)
                {
                    return;
                }

                charCandidate = stream.LookAhead(initialPopCalls);
            }
        }
Example #3
0
        protected override IParseResult TryGetTokenWithoutNullCheck(IStringStream inputStream, out IToken token)
        {
            inputStream.Pop();

            if (inputStream.CurrentPosition > inputStream.Count || !inputStream.LookAhead(0).Equals(SpecialCharacters.NegateCharacterClass))
            {
                token = new OpenCharacterClassToken(_initialStreamPosition);
                return(new SuccessParseResult());
            }

            inputStream.Pop();
            token = new OpenNegatedCharacterClassToken(_initialStreamPosition);
            return(new SuccessParseResult());
        }
Example #4
0
        private static IParseResult <Tuple <string, int> > ParseCharacterSuccessResult(IStringStream stream,
                                                                                       bool executePop, int popCalls, long currentPosition)
        {
            var value = stream.LookAhead(popCalls);

            popCalls++;

            if (executePop)
            {
                CallPop(stream, popCalls);
            }

            return(new SuccessParseResult <Tuple <string, int> >(currentPosition, new Tuple <string, int>(value, popCalls)));
        }
Example #5
0
        private IParseResult <Tuple <string, int> > TryParseCharacterInternal(IStringStream stream, int initialPosition,
                                                                              bool executePop)
        {
            var popCalls        = initialPosition;
            var currentPosition = stream.CurrentPosition;

            if (popCalls < stream.Count &&
                !stream.LookAhead(popCalls).Equals(SpecialCharacters.Escape) &&
                _alphabet.IsValid(stream.LookAhead(popCalls)))
            {
                return(ParseCharacterSuccessResult(stream, executePop, popCalls, currentPosition));
            }

            var escapedCandidate = stream.LookAhead(popCalls++);

            if (popCalls >= stream.Count ||
                !escapedCandidate.Equals(SpecialCharacters.Escape) ||
                !_alphabet.IsValid(stream.LookAhead(popCalls)))
            {
                return(new FailureParseResult <Tuple <string, int> >(stream.CurrentPosition, RegSeedErrorType.SingleCharacterExpected));
            }

            return(ParseCharacterSuccessResult(stream, executePop, popCalls, currentPosition));
        }
Example #6
0
        private static IParseResult <Tuple <int?, int> > TryParseIntegerInternal(IStringStream stream, int initialPops, bool executePop)
        {
            var popCalls = initialPops;

            var initialPosition = stream.CurrentPosition;

            if (popCalls >= stream.Count)
            {
                return(new FailureParseResult <Tuple <int?, int> >(stream.CurrentPosition, RegSeedErrorType.UnexpectedEndOfStream));
            }

            var numberString  = string.Empty;
            var charCandidate = stream.LookAhead(popCalls);

            if (charCandidate.Equals(SpecialCharacters.Minus))
            {
                popCalls++;
                numberString = "-";
            }

            if (popCalls >= stream.Count && numberString.Equals("-"))
            {
                return(new FailureParseResult <Tuple <int?, int> >(stream.CurrentPosition, RegSeedErrorType.IntegerExpected));
            }

            if (popCalls >= stream.Count)
            {
                return(new FailureParseResult <Tuple <int?, int> >(stream.CurrentPosition, RegSeedErrorType.UnexpectedEndOfStream));
            }

            PopAndAppendWhileIsDigit(stream, ref popCalls, ref numberString);

            if (executePop)
            {
                CallPop(stream, popCalls);
            }

            if (string.IsNullOrEmpty(numberString))
            {
                return(new FailureParseResult <Tuple <int?, int> >(initialPosition, RegSeedErrorType.IntegerExpected));
            }

            var value = new Tuple <int?, int>(int.Parse(numberString), popCalls);

            return(new SuccessParseResult <Tuple <int?, int> >(initialPosition, value));
        }
Example #7
0
        public void TryConvertToTokenStream_ThrowsArgumentException_WhenTokenParserFailsToParseToken()
        {
            _input.IsEmpty().Returns(false);
            _input.LookAhead(Arg.Any <long>()).Returns(string.Empty);
            _parserFactory.TryGetTokenParser(Arg.Any <string>(), out _).Returns(x =>
            {
                x[1] = _tokenParser;
                return(true);
            });
            _tokenParser.TryGetToken(Arg.Any <IStringStream>(), out _).Returns(new FailureParseResult(0));

            var lexer = new Lexer(_parserFactory);

            var result = lexer.TryConvertToTokenStream(_input, out _);

            Assert.IsFalse(result.IsSuccess);
            _tokenParser.Received(1).TryGetToken(Arg.Any <IStringStream>(), out _);
        }
Example #8
0
        public IParseResult <CharacterRange> TryParseCharacterRange(IStringStream stream, string rangeSeparator = null)
        {
            rangeSeparator = rangeSeparator ?? SpecialCharacters.CharacterRangeSeparator;

            if (stream == null)
            {
                throw new ArgumentNullException();
            }

            var initialPosition = stream.CurrentPosition;

            var startCharacterResult = TryParseCharacterInternal(stream, 0, false);

            if (!startCharacterResult.IsSuccess)
            {
                return(new FailureParseResult <CharacterRange>(initialPosition));
            }

            var popCalls = startCharacterResult.Value.Item2;

            if (popCalls >= stream.Count || !stream.LookAhead(popCalls).Equals(rangeSeparator))
            {
                return(new FailureParseResult <CharacterRange>(initialPosition + popCalls));
            }

            popCalls++;

            var endCharacterResult = TryParseCharacterInternal(stream, popCalls, false);

            if (!endCharacterResult.IsSuccess)
            {
                return(new FailureParseResult <CharacterRange>(initialPosition, RegSeedErrorType.CharacterRangeExpected));
            }

            CallPop(stream, endCharacterResult.Value.Item2);

            var value = new CharacterRange();

            return(value.TrySetRange(startCharacterResult.Value.Item1, endCharacterResult.Value.Item1, _alphabet).IsSuccess
                ? (IParseResult <CharacterRange>) new SuccessParseResult <CharacterRange>(initialPosition, value)
                : new FailureParseResult <CharacterRange>(initialPosition, RegSeedErrorType.InvalidRange));
        }
Example #9
0
 private static bool IsCharacterRangeSeparator(IStringStream inputStream) =>
 inputStream.LookAhead(0).Equals(SpecialCharacters.CharacterRangeSeparator);
Example #10
0
        public IParseResult <IntegerInterval> TryParseIntegerInterval(IStringStream stream, ParseIntervalSettings settings = null)
        {
            if (stream == null)
            {
                throw new ArgumentNullException();
            }

            settings = settings ?? ParseIntervalSettings.Default;

            var initialPosition = stream.CurrentPosition;
            var popCalls        = 0;

            if (popCalls >= stream.Count || !stream.LookAhead(popCalls).Equals(settings.OpenSymbol))
            {
                return(new FailureParseResult <IntegerInterval>(initialPosition, RegSeedErrorType.IntegerIntervalExpected));
            }

            popCalls++;

            var lowerBound = IsNextCharacterSymbol(settings.Separator, stream, popCalls)
                ? new SuccessParseResult <Tuple <int?, int> >(0, new Tuple <int?, int>(null, popCalls))
                : TryParseIntegerInternal(stream, popCalls, false);

            if (!lowerBound.IsSuccess)
            {
                return(new FailureParseResult <IntegerInterval>(initialPosition + popCalls, RegSeedErrorType.IntegerIntervalExpected));
            }

            popCalls = lowerBound.Value.Item2;

            if (lowerBound.Value.Item1 != null && IsNextCharacterSymbol(settings.CloseSymbol, stream, popCalls))
            {
                return(SingleIntegerInterval(lowerBound.Value.Item1.Value, stream, popCalls));
            }

            if (!IsNextCharacterSymbol(settings.Separator, stream, popCalls))
            {
                return(new FailureParseResult <IntegerInterval>(initialPosition + popCalls, RegSeedErrorType.IntegerIntervalSeparatorExpected));
            }

            popCalls++;

            var upperBound = IsNextCharacterSymbol(settings.CloseSymbol, stream, popCalls)
                ? new SuccessParseResult <Tuple <int?, int> >(0, new Tuple <int?, int>(null, popCalls))
                : TryParseIntegerInternal(stream, popCalls, false);

            if (!upperBound.IsSuccess)
            {
                return(new FailureParseResult <IntegerInterval>(initialPosition, RegSeedErrorType.CharacterRangeExpected));
            }

            popCalls = upperBound.Value.Item2;

            if (popCalls >= stream.Count || !stream.LookAhead(popCalls).Equals(settings.CloseSymbol))
            {
                return(new FailureParseResult <IntegerInterval>(initialPosition, RegSeedErrorType.IntegerIntervalExpected));
            }

            popCalls++;
            CallPop(stream, popCalls);

            var value = new IntegerInterval();

            return(value.TrySetValue(lowerBound.Value.Item1, upperBound.Value.Item1).IsSuccess
                ? new SuccessParseResult <IntegerInterval>(initialPosition, value)
                : (IParseResult <IntegerInterval>) new FailureParseResult <IntegerInterval>(initialPosition, RegSeedErrorType.InvalidInterval));
        }
Example #11
0
 private static bool IsNextCharacterSymbol(string symbol, IStringStream stream, int position) =>
 position < stream.Count && symbol.Equals(stream.LookAhead(position));