public static TokenName GetToken(string name) { if (!_lookup.TryGetValue(name, out TokenName tokenName)) { tokenName = new TokenName(name); _lookup.AddOrUpdate(name, tokenName, _nullUpdate); } return(tokenName); }
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)); }
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); }