目录文档:MySQL 源码|源码剖析文档目录
源码位置(版本 = MySQL 8.0.37):/sql/sql_yacc.yy
前置文档:
根据 MySQL 源码|21 - 词法解析:状态转移逻辑梳理 中梳理的 MySQL 词法解析逻辑,有如下终结符与数值相关:
终结符名称 | 终结符表示内容 |
---|---|
NUM | 整型(-2147483648 到 2147483647) |
LONG_NUM | 长整型(-9223372036854775808 到 9223372036854775807,且不在 NUM 的范围中) |
ULONGLONG_NUM | 无符号整型(9223372036854775807 到 18446744073709551615) |
DECIMAL_NUM | 十进制整数(小于 -9223372036854775808 或大于 18446744073709551615),或包含 . 而不包含 e 或 E 的十进制小数 |
HEX_NUM | 十六进制数字符串(例如 x'0F' 或 0x0F ) |
FLOAT_NUM | 包含 . 和 e 或 E 的十进制小数 |
下面我们通过使用了这 6 个终结符的语义组出发,梳理数值字面值,其涉及的 symbol 及 symbol 之间的关系如下(图中绿色节点为字符串字面值涉及节点、蓝色节点为其他语义组、灰色节点为其他终结符;其中使用 ulong_num
、real_ulong_num
、ulonglong_num
和 realk_ulonglong_num
语义组的语义组较多,在图中已忽略):
语义组:signed_num
signed_num
语义组用于解析没有前置负号或有前置负号的整型。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
int
类型(num
) - Bison 语法:
signed_num:
NUM { $$= static_cast<int>(my_strtoll($1.str, nullptr, 10)); }
| '-' NUM { $$= -static_cast<int>(my_strtoll($2.str, nullptr, 10)); }
;
语义组:dec_num
dec_num
语义组用于解析十进制小数或超出范围的十进制整数。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:没有返回值(仅用于抛出异常,所以不需要返回值)
- 使用场景:
dec_num_error
语义组(用于抛出异常) - Bison 语法:
dec_num:
DECIMAL_NUM
| FLOAT_NUM
;
语义组:dec_num_error
dec_num_error
语义组用于解析十进制小数或超出范围的十进制整数,并抛出异常。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:没有返回值(仅用于抛出异常,所以不需要返回值)
- 使用场景:
real_ulong_num
语义组和real_ulonglong_num
语义组(用于解析十进制整数,如果是小数则抛出异常) - Bison 语法:
dec_num_error:
dec_num
{ YYTHD->syntax_error(ER_ONLY_INTEGERS_ALLOWED); }
;
语义组:ulong_num
ulong_num
语义组用于解析十进制整数或小数和十六进制数(转换为十进制数),返回 unsigned long
类型。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
unsigned long
(ulong_num
) - Bison 语法:
ulong_num:
NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| HEX_NUM { $$= (ulong) my_strtoll($1.str, nullptr, 16); }
| LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| FLOAT_NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
;
语义组:real_ulong_num
real_ulong_num
语义组用于解析十进制整数和十六进制数(转换为十进制数),返回 unsigned long
类型;如果输入十进制小数或超出范围的十进制整数,则抛出异常。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
unsigned long
(ulong_num
) - Bison 语法:
real_ulong_num:
NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| HEX_NUM { $$= (ulong) my_strtoll($1.str, nullptr, 16); }
| LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, nullptr, &error); }
| dec_num_error { MYSQL_YYABORT; }
;
语义组:ulonglong_num
ulonglong_num
语义组用于解析十进制整数或小数,返回 unsigned long long int
类型。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
unsigned long long int
(ulonglong_number
) - Bison 语法:
ulonglong_num:
NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
;
语义组:real_ulonglong_num
real_ulonglong_num
语义组用于解析十进制整数和十六进制数(转换为十进制数),返回 unsigned long long int
类型;如果输入十进制小数或超出范围的十进制整数,则抛出异常。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
unsigned long long int
(ulonglong_number
) - Bison 语法:
real_ulonglong_num:
NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| HEX_NUM { $$= (ulonglong) my_strtoll($1.str, nullptr, 16); }
| ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, nullptr, &error); }
| dec_num_error { MYSQL_YYABORT; }
;
语义组:size_number
size_number
语义组用于解析文件大小的值,支持长整型和结尾为 [gGmMkK]
的字符串两种格式。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
unsigned long long int
(ulonglong_number
) - Bison 语法:
size_number:
real_ulonglong_num { $$= $1;}
| IDENT_sys
{
ulonglong number;
uint text_shift_number= 0;
longlong prefix_number;
const char *start_ptr= $1.str;
size_t str_len= $1.length;
const char *end_ptr= start_ptr + str_len;
int error;
prefix_number= my_strtoll10(start_ptr, &end_ptr, &error);
if ((start_ptr + str_len - 1) == end_ptr)
{
switch (end_ptr[0])
{
case 'g':
case 'G':
text_shift_number+=10;
[[fallthrough]];
case 'm':
case 'M':
text_shift_number+=10;
[[fallthrough]];
case 'k':
case 'K':
text_shift_number+=10;
break;
default:
{
my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
MYSQL_YYABORT;
}
}
if (prefix_number >> 31)
{
my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0));
MYSQL_YYABORT;
}
number= prefix_number << text_shift_number;
}
else
{
my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
MYSQL_YYABORT;
}
$$= number;
}
;
语义组:int64_literal
int64_literal
语义组用于解析 -9223372036854775808 到 18446744073709551615 之间的整数,将 -9223372036854775808 到 9223372036854775807 之间的整数解析为 Item_int
对象(/sql/item.h),将 9223372036854775807 到 18446744073709551615 之间的整型数值解析为 Item_uint
对象(/sql/item.h)。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 使用场景:
stable_integer
语义组(静态整型)、NUM_literal
语义组(数值字面值) - 返回值类型:
Item_num
类(item_num
) - 备选规则和 Bison 语法:
备选规则 | 返回值类型 | 备选规则含义 |
---|---|---|
NUM | Item_int 对象 | 整型(-2147483648 到 2147483647) |
LONG_NUM | Item_int 对象 | 长整型(-9223372036854775808 到 9223372036854775807,且不在 NUM 的范围中) |
ULONGLONG_NUM | Item_uint 对象 | 无符号整型(9223372036854775807 到 18446744073709551615) |
int64_literal:
NUM { $$ = NEW_PTN Item_int(@$, $1); }
| LONG_NUM { $$ = NEW_PTN Item_int(@$, $1); }
| ULONGLONG_NUM { $$ = NEW_PTN Item_uint(@$, $1.str, $1.length); }
;
语义组:NUM_literal
NUM_literal
语义组用于解析包含各类整数和小数在内的所有十进制数值字面值。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 使用场景:
literal
语义组(通用字面值)、signed_literal
语义组(有符号通用字面值)等 - 返回值类型:
Item_num
类(item_num
) - 备选规则和 Bison 语法:
备选规则 | 返回值类型 | 备选规则含义 |
---|---|---|
NUM (int64_literal 语义组) | Item_int 对象 | 整型(-2147483648 到 2147483647) |
LONG_NUM (int64_literal 语义组) | Item_int 对象 | 长整型(-9223372036854775808 到 9223372036854775807,且不在 NUM 的范围中) |
ULONGLONG_NUM (int64_literal 语义组) | Item_uint 对象 | 无符号整型(9223372036854775807 到 18446744073709551615) |
DECIMAL_NUM | Item_decimal 对象 | 十进制整数(小于 -9223372036854775808 或大于 18446744073709551615),或包含 . 而不包含 e 或 E 的十进制小数 |
FLOAT_NUM | Item_float 对象 | 包含 . 和 e 或 E 的十进制小数 |
NUM_literal:
int64_literal
| DECIMAL_NUM
{
$$= NEW_PTN Item_decimal(@$, $1.str, $1.length, YYCSCL);
}
| FLOAT_NUM
{
$$= NEW_PTN Item_float(@$, $1.str, $1.length);
}
;
语义组:stable_integer
stable_integer
语义组用于解析 -9223372036854775808 到 18446744073709551615 之间的整数或预编译表达式的占位符。stable_integer
作为一个非终结符,实际上并不是一个常量,但是在执行的过程中是一个常量。
- 官方文档:MySQL 参考手册 - 11.1.2 Numeric Literals
- 返回值类型:
Item
类(item
),用于表示查询任何类型表达式的基类。 - Bison 语法如下:
/*
The stable_integer nonterminal symbol is not really constant, but constant
for the duration of an execution.
*/
stable_integer:
int64_literal { $$ = $1; }
| param_or_var
;
标签:num,int,MySQL,语义,数值字,NUM,str,error,源码
From: https://blog.csdn.net/Changxing_J/article/details/141943114