示例#1
0
        private IniToken LexDefineKeyword(char c, IniTokenPosition pos)
        {
            var sb = new StringBuilder(c.ToString());

            while (!char.IsWhiteSpace(CurrentChar))
            {
                sb.Append(CurrentChar);
                NextChar();
            }
            return(new IniToken(IniTokenType.DefineKeyword, pos)
            {
                StringValue = sb.ToString()
            });
        }
示例#2
0
        private IniToken LexQuotedString(IniTokenPosition pos)
        {
            var sb = new StringBuilder();

            while (CurrentChar != '"')
            {
                sb.Append(CurrentChar);
                NextChar();
            }
            NextChar();
            return(new IniToken(IniTokenType.StringLiteral, pos)
            {
                StringValue = sb.ToString()
            });
        }
示例#3
0
        private (IniToken?, int nextCharIndex) ReadToken(char[] separators)
        {
            if (_currentLineCharIndex >= _currentLineText.Length)
            {
                return(null, _currentLineCharIndex);
            }

            var nextCharIndex = _currentLineCharIndex;

            // Skip leading trivia.
            while (nextCharIndex < _currentLineText.Length &&
                   separators.Contains(_currentLineText[nextCharIndex]))
            {
                nextCharIndex++;
            }

            var startIndex = nextCharIndex;
            var length     = 0;

            var position = new IniTokenPosition(_fileName, _currentLine + 1, nextCharIndex + 1);

            while (nextCharIndex < _currentLineText.Length &&
                   !separators.Contains(_currentLineText[nextCharIndex]))
            {
                length++;
                nextCharIndex++;
            }

            // Skip trailing separator.
            if (nextCharIndex < _currentLineText.Length &&
                separators.Contains(_currentLineText[nextCharIndex]))
            {
                nextCharIndex++;
            }

            var result = _currentLineText.AsSpan(startIndex, length).ToString();

            if (result.Length == 0)
            {
                return(null, nextCharIndex);
            }

            return(new IniToken(result, position), nextCharIndex);
        }
示例#4
0
 public IniParseException(string message, IniTokenPosition position)
     : base($"({position}): {message}")
 {
 }
示例#5
0
        private IniToken LexNumber(char c, IniTokenPosition pos)
        {
            var hasDot = c == '.';

            var numberValue = c.ToString();

            while (char.IsDigit(CurrentChar) || CurrentChar == '.' || CurrentChar == 'v')
            {
                if (CurrentChar == '.')
                {
                    if (hasDot)
                    {
                        // ODDITY: In CivilianProp.ini:6893, there are two dots in the number: 18.5.0
                        NextChar();
                        continue;
                    }
                    hasDot = true;
                }
                else if (CurrentChar == 'v')
                {
                    // ODDITY: In CivilianBuilding.ini:20199, there's a "v" in the middle of a number.
                    if (PeekChar() == '.')
                    {
                        NextChar();
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
                numberValue += CurrentChar;
                NextChar();
            }

            var tokenType = hasDot
                ? IniTokenType.FloatLiteral
                : IniTokenType.IntegerLiteral;

            if (CurrentChar == '%')
            {
                tokenType = IniTokenType.PercentLiteral;
                NextChar();
            }
            else if (IsIdentifierChar(CurrentChar))
            {
                var numIdentifierChars = 0;
                while (IsIdentifierChar(CurrentChar))
                {
                    numberValue += CurrentChar;
                    NextChar();
                    numIdentifierChars++;
                }
                if (numIdentifierChars == 1 && numberValue.EndsWith("f"))
                {
                    return(new IniToken(tokenType, CurrentPosition)
                    {
                        FloatValue = float.Parse(numberValue.TrimEnd('f'))
                    });
                }
                if (hasDot)
                {
                    throw new IniParseException($"Invalid number: {numberValue}", CurrentPosition);
                }
                return(new IniToken(IniTokenType.Identifier, CurrentPosition)
                {
                    StringValue = numberValue
                });
            }

            switch (tokenType)
            {
            case IniTokenType.FloatLiteral:
            case IniTokenType.PercentLiteral:
                return(new IniToken(tokenType, pos)
                {
                    FloatValue = float.Parse(numberValue)
                });

            case IniTokenType.IntegerLiteral:
                var longNumber = long.Parse(numberValue);
                if (Math.Abs(longNumber) <= int.MaxValue)
                {
                    return(new IniToken(tokenType, pos)
                    {
                        IntegerValue = (int)longNumber
                    });
                }
                return(new IniToken(tokenType, pos)
                {
                    LongValue = longNumber
                });

            default:
                throw new ArgumentOutOfRangeException();
            }
        }