in src/Elastic.Apm/Model/Scanner.cs [115:235]
public Token Scan()
{
if (!HasNext())
return Token.Eof;
var c = Next();
while (char.IsWhiteSpace(c) || _scannerFilter.Skip(this, c))
{
if (HasNext())
c = Next();
else
return Token.Eof;
}
_start = _pos - 1;
if (c == '_' || char.IsLetter(c))
return ScanKeywordOrIdentifier(c != '_');
if (char.IsDigit(c))
return ScanNumericLiteral();
switch (c)
{
case '\'':
// Standard string literal
return ScanStringLiteral();
case '"':
// Standard double-quoted identifier.
//
// NOTE(axw) MySQL will treat " as a
// string literal delimiter by default,
// but we assume standard SQL and treat
// it as a identifier delimiter.
return ScanQuotedIdentifier('"');
case '[':
// T-SQL bracket-quoted identifier
return ScanQuotedIdentifier(']');
case '`':
// MySQL-style backtick-quoted identifier
return ScanQuotedIdentifier('`');
case '(':
return Token.Lparen;
case ')':
return Token.Rparen;
case '-':
if (IsNextChar('-'))
{
// -- comment
Next();
return ScanSimpleComment();
}
return Token.Other;
case '/':
if (IsNextChar('*'))
{
// /* comment */
Next();
return ScanBracketedComment();
}
else if (IsNextChar('/'))
{
// // line comment (ex. Cassandra QL)
Next();
return ScanSimpleComment();
}
return Token.Other;
case '.':
return Token.Period;
case '$':
if (!HasNext())
return Token.Other;
var nextC = Peek();
if (char.IsDigit(nextC))
{
while (HasNext())
{
if (!char.IsDigit(Peek()))
break;
Next();
}
return Token.Other;
}
else if (nextC == '$' || nextC == '_' || char.IsLetter(nextC))
{
// PostgreSQL supports dollar-quoted string literal syntax, like $foo$...$foo$.
// The tag (foo in this case) is optional, and if present follows identifier rules.
while (HasNext())
{
c = Next();
if (c == '$')
{
// This marks the end of the initial $foo$.
var textC = Text();
var i = _input.IndexOf(textC, _pos, StringComparison.InvariantCultureIgnoreCase);
if (i >= 0)
{
_end = i + textC.Length;
_pos = i + textC.Length;
return Token.String;
}
return Token.Other;
}
if (char.IsLetter(c) || char.IsDigit(c) || c == '_')
{
// Identifier char, consume
}
else if (char.IsWhiteSpace(c))
{
_end--;
return Token.Other;
}
}
// Unknown token starting with $ until EOF, just ignore it.
return Token.Other;
}
break;
default:
return Token.Other;
}
return Token.Other;
}