MySQL 源码|107 - 词法解析:状态转移逻辑(字面值)

2.2.2 字面值解析逻辑

如果在实现中,通过没有跳出 CASE 语句逻辑,继续执行另一个状态的处理逻辑,则在描述中将这种情况也描述为重置了自动机状态以方便理解。

2.2.2.1 二进制字面值

对于格式为 [bB]'[01]*' 的二进制字面值,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 bB 时,通过 state_map 映射,将自动机状态置为 MY_LEX_IDENT_OR_BIN
  • MY_LEX_IDENT_OR_BIN:如果下一个字符是 ' 则将自动机状态置为 MY_LEX_BIN_NUMBER,否则将自动机状态置为 MY_LEX_IDENT
  • MY_LEX_BIN_NUMBER:不断匹配 01 直至遇到其他字符,如果之后的字符是 ' 则构造 Token 并返回 BIN_NUM 类型,否则返回 ABORT_SYM 抛出异常。

对于格式为 0b[0-1]+ 的二进制字面值,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 0 时,通过 state_map 映射,将自动机状态置为 MY_LEX_NUMBER_IDENT
  • MY_LEX_NUMBER_IDENT:如果下一个字符是 b,不断匹配 01 直至遇到其他字符,构造 Token 并返回 BIN_NUM 类型。
2.2.2.2 十六进制字面值

对于格式为 [xX]'[A-Fa-f0-9]*' 的十六进制字面值,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 xX 时,通过 state_map 映射,将自动机状态置为 MY_LEX_IDENT_OR_HEX
  • MY_LEX_IDENT_OR_HEX:如果下一个字符是 ' 则将自动机状态置为 MY_LEX_HEX_NUMBER,否则将自动机状态置为 MY_LEX_IDENT
  • MY_LEX_HEX_NUMBER:不断匹配十六进制字符直至遇到其他字符,即大写 AF、小写 af 或数字,则构造 Token 并返回 HEX_NUM 类型,否则返回 ABORT_SYM 抛出异常

对于格式为 0b[A-Fa-f0-9]+ 的二进制字面值,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 0 时,通过 state_map 映射,将自动机状态置为 MY_LEX_NUMBER_IDENT
  • MY_LEX_NUMBER_IDENT:如果下一个字符是 x,不断匹配十六进制字符直至遇到其他字符,构造 Token 并返回 HEX_NUM 类型。
2.2.2.3 Unicode 字符串字面值

Unicode 字符串字面值的格式为 [nN]'string',其中 string 中允许出现转义符,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 nN 时,通过 state_map 映射,将自动机状态置为 MY_LEX_IDENT_OR_NCHAR
  • MY_LEX_IDENT_OR_NCHAR:如果下一个字符不是 ' 则将自动机状态置为 MY_LEX_IDENT;否则,调用 get_text 函数匹配字符串字面值中引号内的部分,构造 Token 并返回 NCHAR_STRING 类型
2.2.2.4 字符串字面值

字符串字面值的格式为 'string',其中 string 中允许出现转义符,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 ' 时,通过 state_map 映射,将自动机状态置为 MY_LEX_STRING
  • MY_LEX_STRING:调用 get_text 函数字面值中引号内的部分,构造 Token 并返回 TEXT_STRING 类型。

如果 sql_mode 没有开启 MODE_ANSI_QUOTES,则支持双引号字符串,其解析逻辑如下:

  • MY_LEX_START:初始状态,遇到 " 时,通过 state_map 映射,将自动机状态置为 MY_LEX_STRING_OR_DELIMITER
  • MY_LEX_STRING_OR_DELIMITER:如果 sql_mode 开启了 MODE_ANSI_QUOTES,则将状态置为 MY_LEX_USER_VARIABLE_DELIMITER,否则将状态置为 MY_LEX_STRING
  • MY_LEX_STRING:逻辑与普通字符串字面值一致。
2.2.2.5 整数字面值

整数字面值的解析逻辑如下:

  • MY_LEX_START:初始状态,遇到数字时,通过 state_map 映射,将自动机状态置为 MY_LEX_NUMBER_IDENT
  • MY_LEX_NUMBER_IDENT:如果开头字符不是 0 或下一个字符不是 bx,则继续不断匹配数字直至遇到其他字符;通过 ident_map 映射,如果下一个字符不是标识符的组成元素,即当前语法元素不是标识符,则将自动机状态置为 MY_LEX_INT_OR_REAL
  • MY_LEX_INT_OR_REAL:如果下一个字符不是 .,则调用 get_token 函数构造 Token 并调用 int_token 函数构造返回值类型
2.2.2.6 浮点字面值

[0-9]+[eE] 开头的浮点数字面值的解析逻辑如下:

  • MY_LEX_START:初始状态,遇到数字时,通过 state_map 映射,将自动机状态置为 MY_LEX_NUMBER_IDENT
  • MY_LEX_NUMBER_IDENT:如果开头字符不是 0 或下一个字符不是 bx,则继续不断匹配数字直至遇到其他字符。下一个字符是 eE,且下一个元素是数字或 +-,如果是 +- 下一个元素是数字,则构造 Token 并返回 FLOAT_NUM 类型;如果下一个字符不是 eE,则将自动机状态置为 MY_LEX_IDENT_START 继续当作标识符进行解析。

[0-9]+. 开头的浮点数字面值的解析逻辑如下:

  • MY_LEX_START:初始状态,遇到数字时,通过 state_map 映射,将自动机状态置为 MY_LEX_NUMBER_IDENT
  • MY_LEX_NUMBER_IDENT:如果开头字符不是 0 或下一个字符不是 bx,则继续不断匹配数字直至遇到其他字符;通过 ident_map 映射,如果下一个字符不是标识符的组成元素,即当前语法元素不是标识符,则将自动机状态置为 MY_LEX_INT_OR_REAL
  • MY_LEX_INT_OR_REAL:下一个字符是 .,将自动机状态重置为 MY_LEX_REAL
  • MY_LEX_REAL:先解析剩余的数字(小数部分),然后尝试解析 eE,如果解析到 eE 则构造 Token 返回 FLOAT_NUM 类型,否则返回 DECIMAL_NUM 类型。

. 开头的浮点数字面值的解析逻辑如下:

  • MY_LEX_START:当前字符为 .,通过 state_map 映射,将自动机状态置为 MY_LEX_REAL_OR_POINT
  • MY_LEX_REAL_OR_POINT:下一个字符为数字,将自动机状态置为 MY_LEX_REAL
  • MY_LEX_REAL:先解析剩余的数字(小数部分),然后尝试解析 eE,如果解析到 eE 则构造 Token 返回 FLOAT_NUM 类型,否则返回 DECIMAL_NUM 类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值