Пример #1
0
        /// <summary>
        /// Parses the input string according to the rules in the
        /// format string. Similar to the standard C library's
        /// sscanf() function. Parsed fields are placed in the
        /// class' Results member.
        /// </summary>
        /// <param name="input">String to parse</param>
        /// <param name="format">Specifies rules for parsing input</param>
        public int Parse(string input, string format)
        {
            TextParser inp = new TextParser(input);
            TextParser fmt = new TextParser(format);
            List<object> results = new List<object>();
            FormatSpecifier spec = new FormatSpecifier();
            int count = 0;

            // Clear any previous results
            Results.Clear();

            // Process input string as indicated in format string
            while (!fmt.EndOfText && !inp.EndOfText)
            {
                if (ParseFormatSpecifier(fmt, spec))
                {
                    // Found a format specifier
                    TypeParser parser = _typeParsers.First(tp => tp.Type == spec.Type);
                    if (parser.Parser(inp, spec))
                        count++;
                    else
                        break;
                }
                else if (Char.IsWhiteSpace(fmt.Peek()))
                {
                    // Whitespace
                    inp.MovePastWhitespace();
                    fmt.MoveAhead();
                }
                else if (fmt.Peek() == inp.Peek())
                {
                    // Matching character
                    inp.MoveAhead();
                    fmt.MoveAhead();
                }
                else break;    // Break at mismatch
            }

            // Return number of fields successfully parsed
            return count;
        }
Пример #2
0
        /// <summary>
        /// Parse a string field
        /// </summary>
        private bool ParseString(TextParser input, FormatSpecifier spec)
        {
            // Skip any whitespace
            input.MovePastWhitespace();

            // Parse string characters
            int start = input.Position;
            while (!input.EndOfText && !Char.IsWhiteSpace(input.Peek()))
                input.MoveAhead();

            // Don't exceed field width
            if (spec.Width > 0)
            {
                int count = input.Position - start;
                if (spec.Width < count)
                    input.MoveAhead(spec.Width - count);
            }

            // Extract token
            if (input.Position > start)
            {
                if (!spec.NoResult)
                    Results.Add(input.Extract(start, input.Position));
                return true;
            }
            return false;
        }
Пример #3
0
        /// <summary>
        /// Parse an octal field
        /// </summary>
        private bool ParseOctal(TextParser input, FormatSpecifier spec)
        {
            // Skip any whitespace
            input.MovePastWhitespace();

            // Parse digits
            int start = input.Position;
            while (IsValidDigit(input.Peek(), 8))
                input.MoveAhead();

            // Don't exceed field width
            if (spec.Width > 0)
            {
                int count = input.Position - start;
                if (spec.Width < count)
                    input.MoveAhead(spec.Width - count);
            }

            // Extract token
            if (input.Position > start)
            {
                if (!spec.NoResult)
                    AddUnsigned(input.Extract(start, input.Position), spec.Modifier, 8);
                return true;
            }
            return false;
        }
Пример #4
0
        /// <summary>
        /// Parse hexadecimal field
        /// </summary>
        protected bool ParseHexadecimal(TextParser input, FormatSpecifier spec)
        {
            // Skip any whitespace
            input.MovePastWhitespace();

            // Parse 0x prefix
            int start = input.Position;
            if (input.Peek() == '0' && input.Peek(1) == 'x')
                input.MoveAhead(2);

            // Parse digits
            while (IsValidDigit(input.Peek(), 16))
                input.MoveAhead();

            // Don't exceed field width
            if (spec.Width > 0)
            {
                int count = input.Position - start;
                if (spec.Width < count)
                    input.MoveAhead(spec.Width - count);
            }

            // Extract token
            if (input.Position > start)
            {
                if (!spec.NoResult)
                    AddUnsigned(input.Extract(start, input.Position), spec.Modifier, 16);
                return true;
            }
            return false;
        }
Пример #5
0
        /// <summary>
        /// Parse a floating-point field
        /// </summary>
        private bool ParseFloat(TextParser input, FormatSpecifier spec)
        {
            // Skip any whitespace
            input.MovePastWhitespace();

            // Parse leading sign
            int start = input.Position;
            if (input.Peek() == '+' || input.Peek() == '-')
                input.MoveAhead();

            // Parse digits
            bool hasPoint = false;
            while (Char.IsDigit(input.Peek()) || input.Peek() == '.')
            {
                if (input.Peek() == '.')
                {
                    if (hasPoint)
                        break;
                    hasPoint = true;
                }
                input.MoveAhead();
            }

            // Parse exponential notation
            if (Char.ToLower(input.Peek()) == 'e')
            {
                input.MoveAhead();
                if (input.Peek() == '+' || input.Peek() == '-')
                    input.MoveAhead();
                while (Char.IsDigit(input.Peek()))
                    input.MoveAhead();
            }

            // Don't exceed field width
            if (spec.Width > 0)
            {
                int count = input.Position - start;
                if (spec.Width < count)
                    input.MoveAhead(spec.Width - count);
            }

            // Because we parse the exponential notation before we apply
            // any field-width constraint, it becomes awkward to verify
            // we have a valid floating point token. To prevent an
            // exception, we use TryParse() here instead of Parse().
            double result;

            // Extract token
            if (input.Position > start &&
                double.TryParse(input.Extract(start, input.Position), out result))
            {
                if (!spec.NoResult)
                {
                    if (spec.Modifier == Modifiers.Long ||
                        spec.Modifier == Modifiers.LongLong)
                        Results.Add(result);
                    else
                        Results.Add((float)result);
                }
                return true;
            }
            return false;
        }
Пример #6
0
        /// <summary>
        /// Parse integer field
        /// </summary>
        private bool ParseDecimal(TextParser input, FormatSpecifier spec)
        {
            int radix = 10;

            // Skip any whitespace
            input.MovePastWhitespace();

            // Parse leading sign
            int start = input.Position;
            if (input.Peek() == '+' || input.Peek() == '-')
            {
                input.MoveAhead();
            }
            else if (input.Peek() == '0')
            {
                if (Char.ToLower(input.Peek(1)) == 'x')
                {
                    radix = 16;
                    input.MoveAhead(2);
                }
                else
                {
                    radix = 8;
                    input.MoveAhead();
                }
            }

            // Parse digits
            while (IsValidDigit(input.Peek(), radix))
                input.MoveAhead();

            // Don't exceed field width
            if (spec.Width > 0)
            {
                int count = input.Position - start;
                if (spec.Width < count)
                    input.MoveAhead(spec.Width - count);
            }

            // Extract token
            if (input.Position > start)
            {
                if (!spec.NoResult)
                {
                    if (spec.Type == Types.Decimal)
                        AddSigned(input.Extract(start, input.Position), spec.Modifier, radix);
                    else
                        AddUnsigned(input.Extract(start, input.Position), spec.Modifier, radix);
                }
                return true;
            }
            return false;
        }