Esempio n. 1
0
        private void ScanStackedOptions(
            ElementsCursor <SyntaxToken> cursor, List <SyntaxError> errors,
            SyntaxToken nameMarker, SyntaxToken name, IReadOnlyList <string> commandName, List <ArgumentSyntax> arguments)
        {
            var    builder      = new SyntaxTokenBuilder();
            var    optionsSpan  = name.Span;
            string optionNames  = name.StringValue;
            int    optionsCount = optionNames.Length;

            GetShortOptionName(errors, builder, optionsSpan, optionNames, 0);
            var shortName = builder.Build();
            var option    = new OptionSyntax(nameMarker, shortName, valueMarker: null, value: null);

            arguments.Add(option);
            nameMarker = null;

            for (int i = 1; i < optionsCount - 1; i++)
            {
                GetShortOptionName(errors, builder, optionsSpan, optionNames, i);
                shortName = builder.Build();
                option    = new OptionSyntax(nameMarker, shortName, valueMarker: null, value: null);
                arguments.Add(option);
            }

            GetShortOptionName(errors, builder, optionsSpan, optionNames, optionsCount - 1);
            if (name.HasTrailingTrivia)
            {
                builder.TrailingTrivia = name.TrailingTrivia;
            }
            name = builder.Build();

            option = ScanOption(cursor, errors, nameMarker, name, commandName);
            arguments.Add(option);
        }
Esempio n. 2
0
        private SyntaxToken ScanEndOfInput(
            ElementsCursor <SyntaxToken> cursor, List <SyntaxError> errors)
        {
            var token = cursor.Peek();

            if (token.Kind == SyntaxKind.EndOfInputToken)
            {
                return(token);
            }

            var builder = new SyntaxTokenBuilder();
            var span    = token.FullSpan;

            _syntaxFactory.EndOfInputToken(builder, span.Source, span.Start, missing: true);

            errors.Add(_syntaxFactory.MissingEndOfInputError(builder.Span));

            if (!span.IsEmpty)
            {
                int start  = span.Start;
                int length = cursor.TerminalElement.FullSpan.End - start;
                builder.TrailingTrivia = _syntaxFactory.UndefinedTrivia(span.Source, start, length);

                errors.Add(_syntaxFactory.UnrecognizedInputError(builder.TrailingTrivia.Span));
            }

            return(builder.Build());
        }
Esempio n. 3
0
        private ValueSyntax ScanValue(ElementsCursor <SyntaxToken> cursor, List <SyntaxError> errors)
        {
            var token = cursor.Peek();

            cursor.MoveNext();

            if (token.Kind == SyntaxKind.QuotedLiteralToken || !HasMoreTokens(cursor))
            {
                if (!HasSpaceAfterOrEnd(token, cursor.Peek(1)))
                {
                    // Quoted literals do not merge with any other literal
                    // even if they don't have spaces between them.
                    var builder = new SyntaxTokenBuilder(token);
                    builder.TrailingTrivia = _syntaxFactory.WhitespaceTriviaAfter(token, length: 0, missing: true);
                    token = builder.Build();
                    errors.Add(_syntaxFactory.MissingWhitespaceError(token.TrailingTrivia.Span));
                }

                if (token.Kind == SyntaxKind.QuotedLiteralToken &&
                    !HasClosingQuote(token))
                {
                    var span = token.Span;
                    errors.Add(_syntaxFactory.MissingClosingQuoteError(
                                   new TextSpan(span.Source, span.End, 0)));
                }

                return(new ValueSyntax(token));
            }

            return(ScanMultiTokenValue(cursor, errors, token));
        }
Esempio n. 4
0
        private SyntaxToken GetTerminalElement(SyntaxToken[] tokens, string commandLine)
        {
            var terminalElement = tokens.LastOrDefault();

            if (terminalElement == null || terminalElement.Kind != SyntaxKind.EndOfInputToken)
            {
                var builder = new SyntaxTokenBuilder();
                _syntaxFactory.EndOfInputToken(builder,
                                               commandLine, terminalElement?.FullSpan.End ?? 0, missing: true);
                terminalElement = builder.Build();
            }

            return(terminalElement);
        }
Esempio n. 5
0
        private CommandNameSyntax ScanCommandName(
            ElementsCursor <SyntaxToken> cursor, List <SyntaxError> errors, CancellationToken cancellation,
            out IReadOnlyList <string> commandName)
        {
            var nameParts = new List <SyntaxToken>();
            var command   = new List <string>();

            while (HasMoreTokens(cursor) && !cancellation.IsCancellationRequested)
            {
                var token = cursor.Peek();
                if (!IsIdentifier(token))
                {
                    break;
                }

                string subcommand = token.StringValue;
                if (!_semanticModel.HasSubCommand(command, subcommand))
                {
                    break;
                }

                if (!HasSpaceAfterOrEnd(token, cursor.Peek(1)))
                {
                    var builder = new SyntaxTokenBuilder(token);
                    builder.TrailingTrivia = _syntaxFactory.WhitespaceTriviaAfter(token, length: 0, missing: true);
                    token = builder.Build();

                    errors.Add(_syntaxFactory.MissingWhitespaceError(token.TrailingTrivia.Span));
                }

                command.Add(subcommand);
                nameParts.Add(token);
                cursor.MoveNext();
            }

            cancellation.ThrowIfCancellationRequested();
            commandName = command;
            if (nameParts.Count == 0)
            {
                return(null);
            }
            return(new CommandNameSyntax(nameParts));
        }
Esempio n. 6
0
        public IEnumerable <SyntaxToken> Lex(string commandLine, CancellationToken cancellation = default)
        {
            if (commandLine == null)
            {
                throw new ArgumentNullException(nameof(commandLine));
            }
            cancellation.ThrowIfCancellationRequested();

            var chars  = new CharsReadOnlyList(commandLine);
            var cursor = new ElementsCursor <char>(chars, EndOfInput);

            var builder = new SyntaxTokenBuilder();

            do
            {
                builder.LeadingTrivia = LexSyntaxTrivia(commandLine, cursor);
                LexSyntaxToken(builder, commandLine, cursor);
                builder.TrailingTrivia = LexSyntaxTrivia(commandLine, cursor);

                cancellation.ThrowIfCancellationRequested();
                yield return(builder.Build());
            } while (builder.Kind != SyntaxKind.EndOfInputToken);
        }
Esempio n. 7
0
        private ValueSyntax ScanMultiTokenValue(
            ElementsCursor <SyntaxToken> cursor, List <SyntaxError> errors,
            SyntaxToken first)
        {
            var tokens = new List <SyntaxToken>();
            var token  = first;

            tokens.Add(token);

            while (HasMoreTokens(cursor))
            {
                var next = cursor.Peek();
                if (HasSpaceAfterOrEnd(token, next))
                {
                    break;
                }

                if (next.Kind == SyntaxKind.QuotedLiteralToken)
                {
                    // Quoted literals do not merge with any other literal
                    // even if they don't have spaces between them.
                    var builder = new SyntaxTokenBuilder(token);
                    builder.TrailingTrivia   = _syntaxFactory.WhitespaceTriviaAfter(token, length: 0, missing: true);
                    tokens[tokens.Count - 1] = builder.Build();

                    errors.Add(_syntaxFactory.MissingWhitespaceError(builder.TrailingTrivia.Span));
                    break;
                }

                token = next;
                tokens.Add(token);
                cursor.MoveNext();
            }

            return(new ValueSyntax(tokens));
        }
Esempio n. 8
0
        private OptionSyntax ScanOption(ElementsCursor <SyntaxToken> cursor, List <SyntaxError> errors,
                                        SyntaxToken nameMarker, SyntaxToken name, IReadOnlyList <string> commandName)
        {
            SyntaxToken valueMarker = null;
            ValueSyntax value       = null;

            if (!HasMoreTokens(cursor))
            {
                return(new OptionSyntax(nameMarker, name, valueMarker, value));
            }

            var token = cursor.Peek();

            if (IsOptionValueMarker(token))
            {
                valueMarker = token;
                cursor.MoveNext();
                token = cursor.Peek();
            }
            else
            {
                if (!HasSpaceAfterOrEnd(name, token))
                {
                    var builder = new SyntaxTokenBuilder(name);
                    builder.TrailingTrivia = _syntaxFactory.WhitespaceTriviaAfter(name, length: 0, missing: true);
                    name = builder.Build();

                    errors.Add(_syntaxFactory.MissingWhitespaceError(name.TrailingTrivia.Span));
                }

                _semanticModel.TryGetOptionType(commandName, name.StringValue, out Type valueType);

                if (IsFlag(valueType))
                {
                    // Flag can have a value only if a value marker is specified
                    // because it have value 'true' by default.
                    return(new OptionSyntax(nameMarker, name, valueMarker, value));
                }
            }

            bool missingValue = valueMarker != null &&
                                (!HasMoreTokens(cursor) || (valueMarker.HasTrailingTrivia && IsOptionNameOrEndOfOptions(token, cursor.Peek(1))));

            if (missingValue)
            {
                SyntaxToken valueToken = null;
                var         builder    = new SyntaxTokenBuilder();
                var         span       = valueMarker.Span;
                _syntaxFactory.LiteralToken(builder, span.Source, span.End, 0, null, missing: true);

                if (valueMarker.HasTrailingTrivia)
                {
                    // Place trailing trivia after missing option value
                    builder.TrailingTrivia = valueMarker.TrailingTrivia;
                    valueToken             = builder.Build();

                    // and remove it from value marker.
                    builder.InitializeWith(valueMarker);
                    builder.TrailingTrivia = null;
                    valueMarker            = builder.Build();
                }
                else
                {
                    valueToken = builder.Build();
                }

                errors.Add(_syntaxFactory.MissingOptionValueError(valueToken.Span));
                value = new ValueSyntax(valueToken);
                return(new OptionSyntax(nameMarker, name, valueMarker, value));
            }

            bool isValue = (valueMarker != null && !valueMarker.HasTrailingTrivia) ||
                           !IsOptionNameOrEndOfOptions(token, cursor.Peek(1));

            if (isValue)
            {
                value = ScanValue(cursor, errors);
            }

            return(new OptionSyntax(nameMarker, name, valueMarker, value));
        }