首页 > 数据库 >MySQL 源码|67 - 语法解析(V2):数值字面值|V20240905

MySQL 源码|67 - 语法解析(V2):数值字面值|V20240905

时间:2024-09-05 22:54:01浏览次数:12  
标签:num int MySQL 语义 数值字 NUM str error 源码

目录文档: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_numreal_ulong_numulonglong_numrealk_ulonglong_num 语义组的语义组较多,在图中已忽略):

在这里插入图片描述

语义组:signed_num

signed_num 语义组用于解析没有前置负号或有前置负号的整型。

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 类型。

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 类型;如果输入十进制小数或超出范围的十进制整数,则抛出异常。

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 类型。

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 类型;如果输入十进制小数或超出范围的十进制整数,则抛出异常。

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] 的字符串两种格式。

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 语法:
备选规则返回值类型备选规则含义
NUMItem_int 对象整型(-2147483648 到 2147483647)
LONG_NUMItem_int 对象长整型(-9223372036854775808 到 9223372036854775807,且不在 NUM 的范围中)
ULONGLONG_NUMItem_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 语法:
备选规则返回值类型备选规则含义
NUMint64_literal 语义组)Item_int 对象整型(-2147483648 到 2147483647)
LONG_NUMint64_literal 语义组)Item_int 对象长整型(-9223372036854775808 到 9223372036854775807,且不在 NUM 的范围中)
ULONGLONG_NUMint64_literal 语义组)Item_uint 对象无符号整型(9223372036854775807 到 18446744073709551615)
DECIMAL_NUMItem_decimal 对象十进制整数(小于 -9223372036854775808 或大于 18446744073709551615),或包含 . 而不包含 e 或 E 的十进制小数
FLOAT_NUMItem_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 作为一个非终结符,实际上并不是一个常量,但是在执行的过程中是一个常量。

/*
  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

相关文章