Mysql源码学习――词法分析MYSQLlex(二)

2014-11-24 10:35:15 · 作者: · 浏览: 1
ame */

"", /* comment */

NULL, /* tailoring */

ctype_latin1,

to_lower_latin1,

to_upper_latin1,

sort_order_latin1,

NULL, /* contractions */

NULL, /* sort_order_big*/

cs_to_uni, /* tab_to_uni */

NULL, /* tab_from_uni */

my_unicase_default, /* caseinfo */

NULL, /* state_map */

NULL, /* ident_map */

1, /* strxfrm_multiply */

1, /* caseup_multiply */

1, /* casedn_multiply */

1, /* mbminlen */

1, /* mbmaxlen */

0, /* min_sort_char */

255, /* max_sort_char */

' ', /* pad char */

0, /* escape_with_backslash_is_dangerous */

&my_charset_handler,

&my_collation_8bit_simple_ci_handler

};

  可以看出ctype = ctype_latin1;而ctype_latin1值为:

static uchar ctype_latin1[] = {

0,

32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,

32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,

72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,

132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,

16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,

16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,

2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,

16, 0, 16, 2, 16, 16, 16, 16, 16, 16, 1, 16, 1, 0, 1, 0,

0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 2, 0, 2, 1,

72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,

16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,

2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2

};

  看到这里哥再一次了然了,这些值都是经过预计算的,第一个0是无效的,这也是为什么my_isalpha(s, c)定义里面ctype要先+1的原因。通过_MY_U和_MY_L的定义,可以知道,这些值肯定是按照相应的ASCII码的具体意义进行置位的。比如字符'A',其ASCII码为65,其实大写字母,故必然具有_MY_U,即第0位必然为1,找到ctype里面第66个(略过第一个无意义的0)元素,为129 = 10000001,显然第0位为1(右边起),说明为大写字母。写代码的人确实比较牛X,如此运用位,哥估计这辈子也想不到了,小小佩服下。State的问题点到为止了。

继续进行词法分析,第一个字母为s,其state = MY_LEX_IDENT(IDENTIFIER:标识符的意思),break出来,继续循环,case进入MY_LEX_IDENT分支:

Case MY_LEX_IDENT:

{

由s开始读,直到空格为止

If(读入的单词为关键字)

{

nextstate = MY_LEX_START;

Return tokval; //关键字的唯一标识

}

Else

{

return IDENT_QUOTED 或者IDENT;表示为一般标识符

}

}

  这里SELECT肯定为关键字,至于为什么呢?下节的语法分析会讲。

解析完SELECT后,需要解析@@version_comment,第一个字符为@,进入START分支,state = MY_LEX_USER_END;

进入MY_LEX_USER_END分支,如下:

case MY_LEX_USER_END: // end '@' of user@hostname

switch (state_map[lip->yyPeek()]) {

case MY_LEX_STRING:

case MY_LEX_USER_VARIABLE_DELIMITER:

case MY_LEX_STRING_OR_DELIMITER:

break;

case MY_LEX_USER_END:

lip->next_state=MY_LEX_SYSTEM_VAR;

break;

default:

lip->next_state=MY_LEX_HOSTNAME;

break;

  哥会心的笑了,两个@符号就是系统变量吧~~,下面进入MY_LEX_SYSTEM_VAR分支

case MY_LEX_SYSTEM_VAR:

yylval->lex_str.str=(char*) lip->get_ptr();

yylval->lex_str.length=1;

lip->yySkip();