in src/backend/utils/adt/agtype_parser.c [1041:1146]
static inline void agtype_lex_number(agtype_lex_context *lex, char *s,
bool *num_err, int *total_len)
{
bool error = false;
int len = s - lex->input;
/* assume we have an integer until proven otherwise */
lex->token_type = AGTYPE_TOKEN_INTEGER;
/* Part (1): leading sign indicator. */
/* Caller already did this for us; so do nothing. */
/* Part (2): parse main digit string. */
if (len < lex->input_length && *s == '0')
{
s++;
len++;
}
else if (len < lex->input_length && *s >= '1' && *s <= '9')
{
do
{
s++;
len++;
} while (len < lex->input_length && *s >= '0' && *s <= '9');
}
else
{
error = true;
}
/* Part (3): parse optional decimal portion. */
if (len < lex->input_length && *s == '.')
{
/* since we have a decimal point, we have a float */
lex->token_type = AGTYPE_TOKEN_FLOAT;
s++;
len++;
if (len == lex->input_length || *s < '0' || *s > '9')
{
error = true;
}
else
{
do
{
s++;
len++;
} while (len < lex->input_length && *s >= '0' && *s <= '9');
}
}
/* Part (4): parse optional exponent. */
if (len < lex->input_length && (*s == 'e' || *s == 'E'))
{
/* since we have an exponent, we have a float */
lex->token_type = AGTYPE_TOKEN_FLOAT;
s++;
len++;
if (len < lex->input_length && (*s == '+' || *s == '-'))
{
s++;
len++;
}
if (len == lex->input_length || *s < '0' || *s > '9')
{
error = true;
}
else
{
do
{
s++;
len++;
} while (len < lex->input_length && *s >= '0' && *s <= '9');
}
}
/*
* Check for trailing garbage. As in agtype_lex(), any alphanumeric stuff
* here should be considered part of the token for error-reporting
* purposes.
*/
for (; len < lex->input_length && AGTYPE_ALPHANUMERIC_CHAR(*s); s++, len++)
error = true;
if (total_len != NULL)
*total_len = len;
if (num_err != NULL)
{
/* let the caller handle any error */
*num_err = error;
}
else
{
/* return token endpoint */
lex->prev_token_terminator = lex->token_terminator;
lex->token_terminator = s;
/* handle error if any */
if (error)
report_invalid_token(lex);
}
}