返回文档首页
(一)简介
代码下载: git clone git://git.code.sf.net/p/redy/code redy-code
这一章的内容有:
这一章大家会看到一个完整的大的状态机,用于识别Redy语言中的所有词文。
(二)词文
在前面我们基本上讲完了Redy中大部份词文,其中有变量,字符串,注释,整数,长整数,浮点数,运算符。但还有一小部份词文在前面还没有提到过,分别为:
- 关键字(如if,else,while,for等)
- 语句分隔符(符号‘;‘和换行符),在Redy中每一条语句占用一行(组合语句除外),如果相把多条语句写在一行的,那么就需要用‘;’来分开。
- 白空格(由多个空格或制表符组成),白空格对于我们语言来说没有用处,所以当我们识别到白空格时就把它抛弃。
因为变量识别里面,会一同识别关键字,所以关键字和识别是在识别到词文变量以后再来进行第二次判断,最终到底里什么类型的关键字,或者还是变量。对于分隔符和白空格,这里就不细说,他们的识别都非常的简单,我只是给出他们的状态机
(三)综合识别
(1)简介
在前面我们已经讲过整数,长整数,浮点数的合并,其实这已经完成了七成的工作了,后面的几个状态机的合并要简单得多,为了表述方便,我们把整数,长整数,浮点数都称为数。下一步的目标是得到一个大的状态机。(2)状态机合并
现在我们总共有字符串,变量,数,运算符,注释,语句分格符,白空格这么七个小的状态机,为了实现综合识别,我们需要把它们合并在一起,相比前面的整数与浮点数的合并来说,这次合并要简单的多,如果仔细观察可以发现,
- 字符串识别的状态机的开始状态只在双引号下发生状态转移
- 语句分格符状态机的开始状态只在符号‘;’和符号‘\n‘发生状态转移
- 数识别的汰态机的开始状态只在数字0到9和点号下发生状态转移
- 变量识别的状态机的开始状态只在字母a到z,字母A到Z,下划线,符号‘@'下发生状态转移
- 白空格识别的状态机的开始状态只在空白符和制表符下发生状态转移
- 注释识别的状态机的开始符叼只在符号‘/’下发生状态转移
上面这6个状态机的开始状态能识别的输入类型两两不同,没有冲突,所以合并这6个非常的简单七个状态机已经讨论了6个,只剩下一个运算符,而这6个状态机与运算符突冲的也只有数的点号,这次冲突处理起来都很简单。只需要为冲突的状态建立一个等价的新状态,新状态的后继状态者是单个,没有组合状态。具体的合并就不细讲,下面我给出状态图:
图1
图2
由于在一张图中不好绘制,所以绘制了两张状态图。从上面的状态图,大家可以看出,七个状态机在合并后,总共增加了二个状态,为这二个状态构造状态链,把这7个状态机连接在一起,一个大的综合性的状态机就这么形成了。(3)状态链的构造
二个状态里面,最复杂的是LexicalBegin,因为它能接受的输入类型最多,第二个状态LexicaiPoint能接受的类型只有一个,构造成来非常简单首先,我们来申明这两个状态
/*merge parts*/ extern struct state me_begin; extern struct state me_period;
第二步,为每一个状态构造状态链a)状态LexicalBegin
输入类型有下面这么27种:
- 符号@,下画线,以及字母 (TO_ID)
- 数字0 (D_0)
- 数字1到9 (D1_9)
- 双引号 (D_QUOTE)
- 空格和制表符 (WS)
- 换行符 (NewLine)
- 分号 (Semicolon)
- 19种运算符
'(' ')' '[' ']' '.' ',' '+' '-' '~' '*' '/' '%' '<' '>' '=' '!' '&' '^' '|'
- 除以上字符以外的所有字符
状态LexicalBegin的输入类型映射数组为:
enum MERGE_INPUT_TYPE { ME_OTHER=0, ME_TO_ID, ME_D0, ME_D1_9, ME_QUOTE, ME_WS, ME_NEWLINE, ME_SEMICOLON, ME_COMMA, ME_PERIOD, ME_REVERSE, ME_L_RB, ME_R_RB, ME_L_SB, ME_R_SB, ME_EXCLAMATION, ME_AMPERSAND, ME_BAR, ME_CARET, ME_STAR, ME_PERCENT, ME_MINUS, ME_PLUS, ME_DIVIDE, ME_EQUAL, ME_GREATER, ME_LESS, ME_INPUT_NUM }; char merge_input_map[ASCII_NUM]= { 0,0,0,0,0,0,0,0,0,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 5,15,4,0,0,20,16,0,11,11,19,22,8,21,9,23,2,3,3,3,3,3,3,3,3,3,0,7,26,24,25,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,13,0,14,18,0, 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,17,0,10,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
后继状态为:
struct state* me_begin_targets[]= { &lex_state_err, /*ME_OTHER*/ &id_identifier, /*ME_TO_ID*/ &nu_zero, /*ME_D0*/ &nu_number, /*ME_D1_9*/ &st_string, /*ME_QUOTE*/ &ws_ws, /*ME_WS*/ &sb_newline, /*ME_NEWLINE*/ &sb_semicolon, /*ME_SEMICOLON*/ &op_comma, /*ME_COMMA*/ &me_period, /*ME_PERIOD*/ &op_reverse, /*ME_REVERSE*/ &op_l_rb, /*ME_L_RB*/ &op_r_rb, /*ME_R_RB*/ &op_l_sb, /*ME_L_SB*/ &op_r_sb, /*ME_R_SB*/ &op_not_equal_begin,/*ME_EXCLAMATION*/ &op_bits_and, /*ME_AMPERSAND*/ &op_bits_or, /*ME_BAR*/ &op_bits_xor, /*ME_CARET*/ &op_multiply, /*ME_STAR*/ &op_mod, /*ME_PERCENT*/ &op_minus, /*ME_MINUS*/ &op_plus, /*ME_PLUS*/ &op_divide, /*ME_DIVIDE*/ &op_assign, /*ME_EQUAL*/ &op_greater_than, /*ME_GREATER*/ &op_less_than, /*ME_LESS*/ };
状态LexicalBegin为:
struct state me_begin= { "me_begin", TOKEN_UNKOWN, ME_INPUT_NUM, merge_input_map, 0, me_begin_targets, 0, };
b)状态lexicalPoint只在输入类型D0_9下转移到Float::FractionBegin.
我们也为LexicalPoint建立一个输入映射数组
char me_period_input_map[ASCII_NUM]= { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
后继状态为:
struct state* me_period_targtes[]= { &lex_state_err, &ft_fraction, };
状态LexicalPoint
struct state me_period= { "me_period", TOKEN_DIVIDE, 2, me_period_input_map, 0, me_period_targtes, 1, };
到现在为止,我们已经把两个状态的状态链数据构造完成,七个小的状态机就被这两个状态链接了在一起,形成一个大的综合性的状态机,该状态机可以识别Redy语言中的所有词文。
(4)运行结果
这里贴几张运行的结果图来结大家看看,这部份的代码可以在tutorial/lexical/merge2下面找到