/// <summary> /// Convert from DottedIdentifier /// </summary> public static PartialSymbol FromDottedIdentifier(SymbolTable symbolTable, DottedIdentifier identifier) { using (var pooledStringIds = Pools.GetStringIdList()) { var stringIds = pooledStringIds.Instance; while (identifier != null) { stringIds.Add(identifier.Head.StringId); identifier = identifier.GetTail(symbolTable); } var components = stringIds.AsArray(); return(new PartialSymbol(components)); } }
/// <summary> /// Internal api to try to create a RelativePath from a string. /// </summary> /// <remarks>This function serves as an internal overload for tryCreate when called from AbsolutePath so we do not get the DotDotOutOfScope error when traversing beyond the root.</remarks> /// <param name="table">StringTable instance.</param> /// <param name="relativePath">Relative path to pass in.</param> /// <param name="result">Output relative path after parsing.</param> /// <param name="characterWithError">Output the character that had the error.</param> /// <param name="allowDotDotOutOfScope">Whether to allow the function to parse .. beyond the root.</param> /// <returns>Return the parser result indicating success, or what was wrong with the parsing.</returns> internal static ParseResult TryCreateInternal <T>(StringTable table, T relativePath, out RelativePath result, out int characterWithError, bool allowDotDotOutOfScope = false) where T : struct, ICharSpan <T> { Contract.RequiresNotNull(table); Contract.Ensures((Contract.Result <ParseResult>() == ParseResult.Success) == Contract.ValueAtReturn(out result).IsValid); using (var wrap = Pools.GetStringIdList()) { List <StringId> components = wrap.Instance; int index = 0; int start = 0; while (index < relativePath.Length) { var ch = relativePath[index]; // trivial reject of invalid characters if (!IsValidRelativePathChar(ch)) { characterWithError = index; result = Invalid; return(ParseResult.FailureDueToInvalidCharacter); } if (ch == '\\' || ch == '/') { // found a component separator if (index > start) { // make a path atom out of [start..index] PathAtom.ParseResult papr = PathAtom.TryCreate( table, relativePath.Subsegment(start, index - start), out PathAtom atom, out int charError); if (papr != PathAtom.ParseResult.Success) { characterWithError = index + charError; result = Invalid; return(ParseResult.FailureDueToInvalidCharacter); } components.Add(atom.StringId); } // skip over the slash index++; start = index; continue; } if (ch == '.' && index == start) { // component starts with a . if ((index == relativePath.Length - 1) || (relativePath[index + 1] == '\\') || (relativePath[index + 1] == '/')) { // component is a sole . so skip it index += 2; start = index; continue; } if (relativePath[index + 1] == '.') { // component starts with .. if ((index == relativePath.Length - 2) || (relativePath[index + 2] == '\\') || (relativePath[index + 2] == '/')) { // component is a sole .. so try to go up if (components.Count == 0 && !allowDotDotOutOfScope) { characterWithError = index; result = Invalid; return(ParseResult.FailureDueToDotDotOutOfScope); } if (components.Count != 0) { components.RemoveAt(components.Count - 1); } index += 3; start = index; continue; } } } index++; } if (index > start) { // make a path atom out of [start..index] PathAtom.ParseResult papr = PathAtom.TryCreate( table, relativePath.Subsegment(start, index - start), out PathAtom atom, out int charError); if (papr != PathAtom.ParseResult.Success) { characterWithError = index + charError; result = Invalid; return(ParseResult.FailureDueToInvalidCharacter); } components.Add(atom.StringId); } result = new RelativePath(components.ToArray()); characterWithError = -1; return(ParseResult.Success); } }
/// <summary> /// Try to create a PartialSymbol from a string. /// </summary> /// <returns>Return the parser result indicating success, or what was wrong with the parsing.</returns> public static ParseResult TryCreate <T>(StringTable table, T partialSymbol, out PartialSymbol result, out int characterWithError) where T : struct, ICharSpan <T> { Contract.RequiresNotNull(table); using (var wrap = Pools.GetStringIdList()) { List <StringId> components = wrap.Instance; int index = 0; int start = 0; int last = partialSymbol.Length - 1; while (index < partialSymbol.Length) { var ch = partialSymbol[index]; // trivial reject of invalid characters if (!SymbolCharacters.IsValidDottedIdentifierChar(ch)) { characterWithError = index; result = Invalid; return(ParseResult.FailureDueToInvalidCharacter); } if (ch == SymbolCharacters.DottedIdentifierSeparatorChar) { // found a component separator if (index == start || index == last) { characterWithError = index; result = Invalid; return(ParseResult.LeadingOrTrailingDot); } else if (index > start) { // make a identifier atom out of [start..index] SymbolAtom atom; int charError; SymbolAtom.ParseResult papr = SymbolAtom.TryCreate( table, partialSymbol.Subsegment(start, index - start), out atom, out charError); if (papr != SymbolAtom.ParseResult.Success) { characterWithError = index + charError; result = Invalid; return(ParseResult.FailureDueToInvalidCharacter); } components.Add(atom.StringId); } // skip over the dot index++; start = index; continue; } index++; } if (index > start) { // make a identifier atom out of [start..index] SymbolAtom atom; int charError; SymbolAtom.ParseResult papr = SymbolAtom.TryCreate( table, partialSymbol.Subsegment(start, index - start), out atom, out charError); if (papr != SymbolAtom.ParseResult.Success) { characterWithError = index + charError; result = Invalid; return(ParseResult.FailureDueToInvalidCharacter); } components.Add(atom.StringId); } result = new PartialSymbol(components.ToArray()); characterWithError = -1; return(ParseResult.Success); } }