public Token Scan()

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;
		}