예제 #1
0
        public static TokenName GetToken(string name)
        {
            if (!_lookup.TryGetValue(name, out TokenName tokenName))
            {
                tokenName = new TokenName(name);
                _lookup.AddOrUpdate(name, tokenName, _nullUpdate);
            }

            return(tokenName);
        }
예제 #2
0
        private TokenObject GetName()
        {
            long position = _position + _index;

            // Find the run of regular characters
            int end = _index + 1;

            while ((end < _length) && !_lookupDelimiterWhitespace[_line[end]])
            {
                end++;
            }

            string name = Encoding.ASCII.GetString(_line, _index + 1, end - _index - 1);

            _index = end;

            // Convert any escape sequences
            while (true)
            {
                int escape = name.IndexOf('#');
                if (escape < 0)
                {
                    break;
                }

                // Check there are two digits after it
                if ((escape > (name.Length - 3)) || !_lookupHexadecimal[(byte)name[escape + 1]] || !_lookupHexadecimal[(byte)name[escape + 2]])
                {
                    return(new TokenError(position + escape, $"Escaped character inside name is not followed by two hex digits."));
                }

                char val = (char)(_lookupHexToDecimal[(byte)name[escape + 1]] * 16 + _lookupHexToDecimal[(byte)name[escape + 2]]);
                name = name.Replace(name.Substring(escape, 3), $"{val}");
            }

            return(TokenName.GetToken(name));
        }
예제 #3
0
        public ParseObjectBase ParseObject(bool allowEmpty = false)
        {
            Tokenizer.IgnoreComments = true;
            TokenObject t = Tokenizer.GetToken();

            if (allowEmpty && (t is TokenEmpty))
            {
                return(null);
            }
            else
            {
                ThrowOnEmptyOrError(t);
            }

            if (t is TokenName)
            {
                // Store one instance of each unique name to minimize memory footprint
                TokenName tokenName = (TokenName)t;
                return(ParseName.GetParse(tokenName.Value));
            }
            else if (t is TokenInteger)
            {
                TokenObject t2 = Tokenizer.GetToken();
                ThrowOnError(t2);

                // An object reference has a second integer, the generation number
                if (t2 is TokenInteger)
                {
                    TokenObject t3 = Tokenizer.GetToken();
                    ThrowOnError(t3);

                    // An object reference has a third value which is the 'R' keyword
                    if ((t3 is TokenKeyword) && (((TokenKeyword)t3).Value == ParseKeyword.R))
                    {
                        return(new ParseObjectReference(t as TokenInteger, t2 as TokenInteger));
                    }

                    Tokenizer.PushToken(t3);
                }

                Tokenizer.PushToken(t2);
                return(new ParseInteger(t as TokenInteger));
            }
            else if (t is TokenReal)
            {
                return(new ParseReal(t as TokenReal));
            }
            else if (t is TokenStringHex)
            {
                return(new ParseString(t as TokenStringHex));
            }
            else if (t is TokenStringLiteral)
            {
                return(new ParseString(t as TokenStringLiteral));
            }
            else if (t is TokenArrayOpen)
            {
                List <ParseObjectBase> objects = new List <ParseObjectBase>();

                ParseObjectBase entry = null;
                while (true)
                {
                    entry = ParseObject();
                    if (entry == null)
                    {
                        break;
                    }
                    else
                    {
                        ThrowOnEmptyOrError(t);
                    }

                    objects.Add(entry);
                }

                ThrowIfNot <TokenArrayClose>(Tokenizer.GetToken());
                return(new ParseArray(objects));
            }
            else if (t is TokenDictionaryOpen)
            {
                List <string>          names   = new List <string>();
                List <ParseObjectBase> entries = new List <ParseObjectBase>();

                ParseObjectBase value1 = null;
                ParseObjectBase value2 = null;
                while (true)
                {
                    value1 = ParseObject();
                    if (value1 == null)
                    {
                        break;
                    }
                    else
                    {
                        ThrowOnEmptyOrError(t);
                    }

                    // Key value must be a Name
                    ParseName name = value1 as ParseName;
                    if (name == null)
                    {
                        throw new ApplicationException($"Dictionary key must be a name instead of {name.GetType().Name}.");
                    }

                    value2 = ParseObject();
                    if (value2 == null)
                    {
                        throw new ApplicationException($"Dictionary value missing for key {name.Value}.");
                    }
                    else
                    {
                        ThrowOnEmptyOrError(t);
                    }

                    names.Add(name.Value);
                    entries.Add(value2);
                }

                ThrowIfNot <TokenDictionaryClose>(Tokenizer.GetToken());
                return(new ParseDictionary(names, entries));
            }
            else if (t is TokenKeyword)
            {
                switch ((t as TokenKeyword).Value)
                {
                case ParseKeyword.True:
                    return(ParseObjectBase.True);

                case ParseKeyword.False:
                    return(ParseObjectBase.False);

                case ParseKeyword.Null:
                    return(ParseObjectBase.Null);
                }
            }
            else if (t is TokenIdentifier)
            {
                // Store one instance of each unique identifier to minimize memory footprint
                TokenIdentifier tokenIdentifier = (TokenIdentifier)t;
                return(ParseIdentifier.GetParse(tokenIdentifier.Value));
            }

            // Token is not one that starts an object, so put the token back
            Tokenizer.PushToken(t);
            return(null);
        }