in src/Core/Parsers/EntitySourceNamesParser.cs [114:218]
private static (string?, string?) GetTokenAndNextToken(string input, int startIndex = 0)
{
bool startsWithBracket = input[startIndex] == '[';
int i = startIndex;
while (i < input.Length)
{
if (!startsWithBracket)
{
if (input[i] == '.')
{
// ^ is startIndex and i is current index
// Ex: abc.xyz
// ^ i
// Return "abc" as the token and the index of x as the next starting index
//
return (input[startIndex..i], input.Substring(i + 1));
}
if (input[i] == ']' || input[i] == '[')
{
// ^ is startIndex and i is current index
// Ex: abc]xyz
// ^ i
// Return exception because we encountered a ']' or '[', and the token was not surrounded by "[" and "]".
//
throw new DataApiBuilderException(message: "Token is not surrounded by '[' and ']'.",
statusCode: HttpStatusCode.ServiceUnavailable,
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization);
}
} // close of if of !startsWithBracket
else
{
if (input[i] == ']' && i + 1 < input.Length && input[i + 1] == '.')
{
// ^ is startIndex and i is current index
// Ex: [ab.c].xyz
// ^ i
// Return "ab.c" as the token and the index of x as the next starting index
//
return (input[(startIndex + 1)..i], input.Substring(i + 2));
}
else if (input[i] == ']' && i + 1 < input.Length && input[i + 1] == ']')
{
if (i + 2 >= input.Length)
{
// ^ is startIndex and i is current index
// Ex: [abc]]
// ^ i
// Return exception because we encountered ]] at the end of the string, and there is no closing "]"
throw new DataApiBuilderException(message: "Token does not have closing ']'.",
statusCode: HttpStatusCode.ServiceUnavailable,
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization);
}
// We increase by 2 so that we skip over the escaped "]"
i += 2;
continue;
}
else if (input[i] == ']' && i + 1 < input.Length && input[i + 1] != ']')
{
// ^ is startIndex and i is current index
// Ex: [abc]xyz
// ^ i
// Return exception because we encountered "]" and the character after "]" is not a "."
throw new DataApiBuilderException(message: "Token has invalid character next to ']'. Allowed characters are '.' and ']'.",
statusCode: HttpStatusCode.ServiceUnavailable,
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization);
}
} // close of else of !startsWithBracket
i += 1;
} // close of while loop
// Special cases for parsing tokens at the end of the string.
if (startsWithBracket)
{
if (!input.EndsWith(']'))
{
// ^ is startIndex and i is current index
// Ex: [abcdef
// ^ i
// Return exception because there is no corresponding closing "]".
//
throw new DataApiBuilderException(message: "Token does not have corresponding closing ']'.",
statusCode: HttpStatusCode.ServiceUnavailable,
subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization);
}
// ^ is startIndex and i is current index
// Ex: xyz.[abc.def]
// ^ i
// Return "abc.def" as the token and the input length as the index of the next token (it wont look for more tokens after this)
//
return (input[(startIndex + 1)..(input.Length - 1)], null);
}
else
{
// ^ is startIndex and i is current index
// Ex: abc.def
// ^ i
// Return "def" as the token and the input length as the index of the next token (it wont look for more tokens after this)
//
return (input[startIndex..(input.Length)], null);
}
}