Пример #1
0
        internal void Run()
        {
            var next = charReader.Read();

            while (next != '\0')
            {
                var encoded = Encode(next);
                charWriter.Write(encoded);
                next = charReader.Read();
            }
        }
Пример #2
0
        private char?GetUnicodeSymbol(ICharReader charReader)
        {
            var sb = new StringBuilder(8);

            for (var i = 0; i < 4; i++)
            {
                var c = charReader.Read();
                if (!c.HasValue)
                {
                    throw new JsonException("Unterminated string");
                }
                if (char.IsDigit(c.Value) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
                {
                    sb.Append(c.Value);
                }
                else
                {
                    throw new JsonException($"Invalid character '{c.Value}' in hexidecimal unicode notation");
                }
            }

            var hexString = sb.ToString();
            var sChar     = (ushort)(Convert.ToUInt16(hexString.Substring(0, 2), 16) << 8);

            sChar += Convert.ToUInt16(hexString.Substring(2, 2), 16);
            return(Convert.ToChar(sChar));
        }
Пример #3
0
        private JsonValue ParseObject(ICharReader charReader)
        {
            var members = new List <JsonObjectMember>();

            if (!charReader.TrimRead('{'))
            {
                throw new JsonException("Expected '{' when parsing json object.");
            }

            var peek = charReader.TrimThenPeek();

            if (!peek.HasValue)
            {
                throw new JsonException("Unterminated object");
            }

            while (peek.Value != '}')
            {
                if (members.Any())
                {
                    if (!charReader.TrimRead(','))
                    {
                        throw new JsonException("Missing comma separater between array items.");
                    }
                }
                members.Add(ParseObjectMember(charReader));
                peek = charReader.TrimThenPeek();
                if (!peek.HasValue)
                {
                    throw new JsonException("Unterminated object");
                }
            }
            charReader.Read(); // }
            return(new JsonObject(members));
        }
Пример #4
0
        private static void AdvanceWhitespace(ICharReader charReader)
        {
            var peek = charReader.Peek();

            while (peek.HasValue && char.IsWhiteSpace(peek.Value))
            {
                charReader.Read();
                peek = charReader.Peek();
            }
        }
Пример #5
0
 private JsonValue ParseNull(ICharReader charReader)
 {
     foreach (var c in _null)
     {
         if (c != charReader.Read())
         {
             throw new JsonException($"Unexpected character '{c}' whilst parsing 'null'");
         }
     }
     return(new JsonNull());
 }
Пример #6
0
 private JsonValue ParseFalse(ICharReader charReader)
 {
     foreach (var c in _false)
     {
         if (c != charReader.Read())
         {
             throw new JsonException($"Unexpected character '{c}' whilst parsing 'false'");
         }
     }
     return(new JsonFalse());
 }
Пример #7
0
        private char?GetNextStringCharacter(ICharReader charReader, char?delimiter)
        {
            var c = charReader.Read();

            if (!c.HasValue)
            {
                throw new JsonException("Unterminated string");
            }
            if (c == delimiter)
            {
                return(null);
            }
            if (CharRequiresEscapeInString(c.Value))
            {
                throw new JsonException($"Unescaped '{c}' in string");
            }
            if (c != '\\')
            {
                return(c);
            }

            c = charReader.Read();
            if (!c.HasValue)
            {
                throw new JsonException("Unterminated string");
            }

            char fromShortCode;

            if (ShortEscapeDecodables.TryGetValue(c.Value, out fromShortCode))
            {
                return(fromShortCode);
            }

            if (c == 'u')
            {
                return(GetUnicodeSymbol(charReader));
            }

            throw new JsonException($"Unrecognised escape sequence '\\{c}'");
        }
Пример #8
0
        private JsonValue ParseNumber(ICharReader charReader)
        {
            var sb   = new StringBuilder();
            var peek = charReader.Peek();

            while (peek.HasValue && Numerics.Contains(peek.Value))
            {
                sb.Append(charReader.Read());
                peek = charReader.Peek();
            }

            return(new JsonNumber(sb.ToString()));
        }
Пример #9
0
        private JsonValue ParseArray(ICharReader charReader)
        {
            charReader.TrimRead(); // [

            var items = new List <JsonValue>();

            while (charReader.TrimThenPeek() != ']')
            {
                if (items.Any())
                {
                    if (!charReader.TrimRead(','))
                    {
                        throw new JsonException("Missing comma separater between array items.");
                    }
                }
                items.Add(ParseJsonValue(charReader));
            }
            charReader.Read(); // ]

            return(new JsonArray(items));
        }
Пример #10
0
        public TokenMatch Read(ICharReader Reader)
        {
            char          input;
            int?          index;
            IState        currentState;
            StringBuilder sb;
            IRule         reductionRule;
            string        lastGoodValue    = null;
            long          lastGoodPosition = 0;
            IRule         lastGoodRule     = null;
            TokenMatch    result;

            if (Reader == null)
            {
                throw new ArgumentNullException("Reader");
            }

            sb = new StringBuilder();

            currentState = states[0];
            while (true)
            {
                if (Reader.EOF)
                {
                    if (lastGoodPosition != 0)
                    {
                        break;
                    }
                    throw new Exceptions.EndOfStreamException(Reader.Position);
                }
                else
                {
                    input = Reader.Read();
                    index = currentState.GetNextStateIndex(input);
                }

                if (index == null)
                {
                    if (lastGoodPosition != 0)
                    {
                        break;
                    }
                    throw new InvalidInputException(Reader.Position, input);
                }

                sb.Append(input);
                currentState = states[index.Value];

                reductionRule = currentState.Reductions.FirstOrDefault();
                if (reductionRule != null)
                {
                    lastGoodPosition = Reader.Position;
                    lastGoodRule     = reductionRule;
                    lastGoodValue    = sb.ToString();
                }
            }

            Reader.Seek(lastGoodPosition);

            result         = new TokenMatch();
            result.Success = true;
            result.Token   = new Token(lastGoodRule.Name, lastGoodValue);
            result.Tags    = lastGoodRule.Tags.ToArray();
            return(result);
        }
Пример #11
0
 public static bool TrimRead(this ICharReader charReader, char c)
 {
     AdvanceWhitespace(charReader);
     return(charReader.Read(c));
 }
Пример #12
0
 public static char?TrimRead(this ICharReader charReader)
 {
     AdvanceWhitespace(charReader);
     return(charReader.Read());
 }
Пример #13
0
        private Token ReadNew()
        {
            CommentMode comment = CommentMode.None;
            int         readInt;
            Token       tmpToken;

            while ((readInt = _source.Read()) >= 0)
            {
                // Handle comment mode
                if (comment == CommentMode.Line)
                {
                    if (readInt == '\n' || readInt == '\r')
                    {
                        comment = CommentMode.None;
                    }
                    continue;
                }
                else if (comment == CommentMode.Block)
                {
                    if (readInt == '*')
                    {
                        if ((readInt = _source.Read()) == '/')
                        {
                            comment = CommentMode.None;
                        }
                        else if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                    }
                    continue;
                }

                // Skip whitespaces
                if (char.IsWhiteSpace((char)readInt))
                {
                    continue;
                }

                long position = _source.Position;
                switch (readInt)
                {
                case '+':
                    switch (readInt = _source.Read())
                    {
                    case '+': return(new Token(TokenType.OperatorIncrement, position));

                    case '=': return(new Token(TokenType.OperatorAssignPlus, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorPlus, position));
                    }

                case '-':
                    switch (readInt = _source.Read())
                    {
                    case '-': return(new Token(TokenType.OperatorDecrement, position));

                    case '=': return(new Token(TokenType.OperatorAssignMinus, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorMinus, position));
                    }

                case '*':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignTimes, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorTimes, position));
                    }

                case '/':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignDivide, position));

                    case '/':
                        comment = CommentMode.Line;
                        break;

                    case '*':
                        comment = CommentMode.Block;
                        break;

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorDivide, position));
                    }
                    break;

                case '%':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignModulo, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorModulo, position));
                    }

                case '(': return(new Token(TokenType.BracketLeft, position));

                case ')': return(new Token(TokenType.BracketRight, position));

                case '[': return(new Token(TokenType.SquareBracketLeft, position));

                case ']': return(new Token(TokenType.SquareBracketRight, position));

                case '{': return(new Token(TokenType.CurlyBracketLeft, position));

                case '}': return(new Token(TokenType.CurlyBracketRight, position));

                case ';': return(new Token(TokenType.EndOfInstruction, position));

                case ',': return(new Token(TokenType.Comma, position));

                case '.':
                    // It might be a floating point number (in fact, iff it is follows by a digit)
                    int nextInt = _source.Read();
                    if (nextInt >= 0)
                    {
                        _source.PushBack(nextInt);
                        if (char.IsDigit((char)nextInt))
                        {
                            // Since the next character is a digit, ProcessNumber_Float() cannot return null
                            return(ProcessNumber_Float(position, new StringBuilder(), readInt));
                        }
                    }
                    return(new Token(TokenType.Period, position));

                case ':':
                    switch (readInt = _source.Read())
                    {
                    case ':': return(new Token(TokenType.DoubleColon, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.Colon, position));
                    }

                case '<':
                    switch (readInt = _source.Read())
                    {
                    case '<':
                        if ((readInt = _source.Read()) == '=')
                        {
                            return(new Token(TokenType.OperatorAssignLeftShift, position));
                        }
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorLeftShift, position));

                    case '=': return(new Token(TokenType.OperatorLessThanEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorLessThan, position));
                    }

                case '>':
                    switch (readInt = _source.Read())
                    {
                    case '>':
                        if ((readInt = _source.Read()) == '=')
                        {
                            return(new Token(TokenType.OperatorAssignRightShift, position));
                        }
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorRightShift, position));

                    case '=': return(new Token(TokenType.OperatorMoreThanEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorMoreThan, position));
                    }

                case '!':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorNotEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorLogicalNot, position));
                    }

                case '~': return(new Token(TokenType.OperatorBitwiseNot, position));

                case '&':
                    switch (readInt = _source.Read())
                    {
                    case '&': return(new Token(TokenType.OperatorLogicalAnd, position));

                    case '=': return(new Token(TokenType.OperatorAssignBitwiseAnd, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorBitwiseAnd, position));
                    }

                case '|':
                    switch (readInt = _source.Read())
                    {
                    case '|': return(new Token(TokenType.OperatorLogicalOr, position));

                    case '=': return(new Token(TokenType.OperatorAssignBitwiseOr, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorBitwiseOr, position));
                    }

                case '^':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignBitwiseXor, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorBitwiseXor, position));
                    }

                case '=':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorAssign, position));
                    }

                case '\'':
                    switch (readInt = _source.Read())
                    {
                    case '\'':
                        throw new SyntaxException(_source.Position, "Empty character");

                    case '\\':
                        switch (readInt = _source.Read())
                        {
                        case '0': readInt = 0; break;

                        case '\'': break;

                        case '\\': break;

                        case 'n': readInt = '\n'; break;

                        case 'r': readInt = '\r'; break;

                        case 't': readInt = '\t'; break;

                        default:
                            throw new SyntaxException(_source.Position, "Unrecognized escape sequence");
                        }
                        break;
                    }
                    if (_source.Read() != '\'')
                    {
                        throw new SyntaxException(_source.Position, "Too many characters");
                    }
                    return(new ValuedToken <string>(TokenType.DecInt, position, readInt.ToString()));

                default:
                    if ((tmpToken = ProcessNumber(readInt)) != null)
                    {
                        return(tmpToken);
                    }
                    if ((tmpToken = ProcessName(readInt)) != null)
                    {
                        return(tmpToken);
                    }
                    if ((tmpToken = ProcessString(readInt)) != null)
                    {
                        return(tmpToken);
                    }
                    throw new SyntaxException(_source.Position, "Unrecognized character: " + (char)readInt);
                }
            }

            // We reached the end
            return(new Token(TokenType.EndOfDocument, _source.Position + 1));
        }