Chinaunix首页 | 论坛 | 博客
  • 博客访问: 319180
  • 博文数量: 32
  • 博客积分: 424
  • 博客等级: 准尉
  • 技术积分: 465
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-02 10:23
文章分类

全部博文(32)

文章存档

2012年(32)

分类: Python/Ruby

2012-03-02 11:03:23



(一)简介
代码下载: git clone git://git.code.sf.net/p/redy/code redy-code
这一章内容有:
用状态矩阵的方法识别变量

(二)变量识别

1)命名规则
 Redy中变量的命名规则为:首字符必须为字母,下划线或者字符'@',后面紧接数字,字母,下划线。
2)BNF文法
  1. identifier ::=(letter|'_'|'@')(letter|digit|"_")*
  2. digit ::='0'..'9'
  3. letter ::=lowercase|uppercase
  4. lowercase ::='a'..'z'
  5. uppercase ::='A'..'Z'
3)状态图:
4)状态矩阵
对于变量来说,可以把字符分为这么几类:
  1. 数字(digit)
  2. 字母(letter)
  3. 下划线(underline)
  4. 符号@(s_at)
  5. 除上面字符以外其它字符(other)

状态有两个,一个为 identifier_begin,一个为identifier。其中开始状态为identifier_begin,结束状态为identifier

状态矩阵为:

状态\输入

Other

Digit

Letter

Underline

s_at

identifier_begin



identifier

identifier

identifier

identifier


identifier

identifier

identifier



其中空格的地方表示,在当前状态下,并不能识别该输入类型的字符。
5)程序数据
我们用一个一维数组来映射每个字符所属的类型:

  1. #define ID_ERR 0
  2. #define ID_DIGIT 1
  3. #define ID_LETTER 2
  4. #define ID_UNDERLINE 3
  5. #define ID_S_AT 4
  6. char identifier_type_map[ASSIC_NUM]=
  7. {
  8.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  9.     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,
  10.     4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,3,
  11.     0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,
  12.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  13.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  14.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  15.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  16. };

状态转换矩阵虽然是一个二维的矩阵,但是我们这里用一个一维组数来表于:

  1. #define ID_STATE_TYPES 2
  2. #define ID_INPUT_TYPES 5

  3. #define ID_STATE_BEGIN 0
  4. #define ID_STATE_IDENTIFIER 1
  5. #define ID_STATE_ERROR -1

  6. /*Other | Digit | Letter | Underline | S_AT */
  7. int identifier_automaton[ID_STATE_TYPES*ID_INPUT_TYPES]=
  8. {
  9.     /*ID_STATE_BEGIN*/
  10.     ID_STATE_ERROR,ID_STATE_ERROR,ID_STATE_IDENTIFIER,ID_STATE_IDENTIFIER,ID_STATE_IDENTIFIER,
  11.     /* ID_STATE_IDENTIFIER*/
  12.     ID_STATE_ERROR,ID_STATE_IDENTIFIER,ID_STATE_IDENTIFIER,ID_STATE_IDENTIFIER,ID_STATE_ERROR
  13. };
然后再用一个一维数组来表示每一个状态是否为终态:

  1. char id_state[ID_STATE_TYPES]={0,1};
现在我们经完成了大部份的数据。

6)驱动程序
上面这们用状态矩阵法实现了状态机模型,但是状态矩阵是只是一组数据,要让它变得有用,还需要一个驱动程序,驱动程序懂数据的逻辑。为了方面,我们用一个结构体来管理这一组数据

  1. #define ASSIC_NUM 256
  2. #define LEX_ERR -1
  3. struct automaton
  4. {
  5.     int states_num; /*状态的数量*/
  6.     int inputs_num; /*输入类型的数量*/
  7.     char* type_map; /*字符映射到输入类型的数组*/
  8.     int begin_state;    /*开始状态*/
  9.     int* states_matrix; /*状态矩阵*/
  10.     char* states_info; /*状态信息*/
  11. };
驱动程序为:

  1. /*返回值-1则表示识别错误,其它值表示能识别的最大位置*/

  2. int driver(struct automaton* am,char* str)
  3. {
  4.     int length=strlen(str); /*字符串长度*/
  5.     int i;
  6.     int cur_state=am->begin_state; /*得到开始状态*/
  7.     int last_final=-1;
  8.     for(i=0;i<length;i++)
  9.     {
  10.         int input_type=am->type_map[str[i]]; /*根据当前字符得到输入类型*/
  11.         
  12.         /*根据当前状态和输入类型,查状态转换表,得到下一个状态*/
  13.         int next_state=am->states_matrix[cur_state*am->inputs_num+input_type];
  14.         
  15.         /*当前状态是否能识别当前输入类型*/
  16.         if(next_state==LEX_ERR)
  17.         {
  18.             return last_final;
  19.         }
  20.         else
  21.         {
  22.             cur_state=next_state;
  23.             /*如果当前状态为终态,则记录下来识别位置*/
  24.             if(am->states_info[cur_state]==1)
  25.             {
  26.                 last_final=i;
  27.             }
  28.         }
  29.     }
  30.     return last_final;
  31. }

下面我们来写一个小的测试程序来验证我们的程序是否工作正常

  1. int main()
  2. {
  3.     char buf[2048];
  4.     char buf_copy[2048];
  5.     printf("input:__quit__ exit\n");
  6.     printf("input:");
  7.     scanf("%s",buf);
  8.     while(strcmp(buf,"__quit__")!=0)
  9.     {
  10.         int ret=driver(&am_id,buf);
  11.         if(ret==-1)
  12.         {
  13.             printf("sorry,Error String\n");
  14.         }
  15.         else
  16.         {
  17.             memcpy(buf_copy,buf,ret+1);
  18.             buf_copy[ret+1]='\0';
  19.             printf("Recongise: %s\n",buf_copy);
  20.             if(ret+1==strlen(buf))
  21.             {
  22.                 printf("It's Variable\n");
  23.             }
  24.             else
  25.             {
  26.                 printf("It's Not Variable\n");
  27.             }
  28.         }
  29.         printf("\ninput:");
  30.         scanf("%s",buf);
  31.     }
  32.     return 0;
  33. }


(7)运行结果


上面的所有代码都位于:tutorial/lexical/identifier文件夹里面


返回文档首页




阅读(2737) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~