Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3549167
  • 博文数量: 1805
  • 博客积分: 135
  • 博客等级: 入伍新兵
  • 技术积分: 3345
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-19 20:01
文章分类

全部博文(1805)

文章存档

2017年(19)

2016年(80)

2015年(341)

2014年(438)

2013年(349)

2012年(332)

2011年(248)

分类:

2012-10-28 11:10:50


代码下载: git clone git://git.code.sf.net/p/redy/code redy-code

这一章的内容有:
关键字的识别

(1)简介

在Redy中,总共有这么一些关键字:
  1.     'class' 'attr' 'end' 'inhrit' 'vfunc' 'func'
  2.     'import' 'as' 'to' 'from'
  3.     'break' 'continue' 'for' 'while' 'do' 'in'
  4.     'if' 'elif' 'else' 'then'
  5.     'return' 'and' 'or' 'not'
  6.     'print' 'try' 'catch' 'finally
在前面,我们是把关键字和识别与变量的识别结合再一起来,这样做是因为为关键字构造状态机是一件很烦锁的事情,如果要构造一个能成功识别上面关键字的状态机,至少需要100多个状态,无论是编写,绘图,还是维护都是一件费脑力与体力的活,所以,我们也关键字的识别与变量识别结合在一起,当词法识别系统识别到一个变量的词文时,我们再来对判断该词文是否真的是变量,还是关键字。

第一步:我们用一个结构体来表示关键字:
  1. struct keyword
  2. {
  3.     char* k_name;
  4.     int k_token;
  5. };
其中成员k_name表示该关键字的名称,k_token用于表示该关键字的词文类型,用于后面的语法分析。

第二步:用一个数组来保存这些关键字,关键字按字典顺序排列。
  1. struct keyword key_words[]=
  2. {
  3.     {"and",TOKEN_AND},
  4.     {"as",TOKEN_AS},
  5.     {"attr",TOKEN_ATTR},
  6.     {"break",TOKEN_BREAK},
  7.     {"catch",TOKEN_CATCH},
  8.     {"class",TOKEN_CLASS},
  9.     {"continue",TOKEN_CONTIUNE},
  10.     {"do",TOKEN_DO},
  11.     {"elif",TOKEN_ELIF},
  12.     {"else",TOKEN_ELSE},
  13.     {"end",TOKEN_END},
  14.     {"finally",TOKEN_FINALLY},
  15.     {"for",TOKEN_FOR},
  16.     {"from",TOKEN_FROM},
  17.     {"func",TOKEN_FUNC},
  18.     {"if",TOKEN_IF},
  19.     {"import",TOKEN_IMPORT},
  20.     {"in",TOKEN_IN},
  21.     {"inhrit",TOKEN_INHRIT},
  22.     {"not",TOKEN_NOT},
  23.     {"or",TOKEN_OR},
  24.     {"print",TOKEN_PRINT},
  25.     {"return",TOKEN_RETURN},
  26.     {"then",TOKEN_THEN},
  27.     {"to",TOKEN_TO},
  28.     {"try",TOKEN_TRY},
  29.     {"vfunc",TOKEN_VFUNC},
  30.     {"while",TOKEN_WHILE},
  31. };

第三步:因为我们前面已经对关键字按照字典顺序排序,这样做的目的为,我们可以使用二分查找算法来加速整个查找的过程。我们这里用一个函数来实现查找,如果参数symbol是关键字,则返回关键字的类型,否则说明该词文是一个变量,则返加TOKEN_ID。
  1. int symbol_type(char* symbol)
  2. {
  3.     int begin=0;
  4.     int end=KEYWORD_NUM-1;
  5.     int middle;
  6.     while(begin<=end) /*采用二分查找算法*/
  7.     {
  8.         middle=(begin+end)/2;
  9.         int ret=strcmp(symbol,key_words[middle].k_name);
  10.         printf("cmp %s ,%s =%d\n",key_words[middle].k_name,symbol,ret);

  11.         if(ret<0)
  12.         {
  13.             end=middle-1;
  14.         }
  15.         else if(ret >0)
  16.         {
  17.             begin=middle+1;

  18.         }
  19.         else
  20.         {
  21.             return key_words[middle].k_token;
  22.         }
  23.     }
  24.     return TOKEN_ID;
  25. }

第四步:写一个小程序测试程序来判断前面的程序是否工作正常。
  1. int main()
  2. {
  3.     char buf[1024];
  4.     printf("input __quit__ exit\n");
  5.     printf("input:\n");
  6.     scanf("%s",buf);
  7.     while(strcmp(buf,"__quit__")!=0)
  8.     {
  9.         int token=symbol_type(buf);
  10.         printf("it's %s\n",token_info[token]);
  11.         printf("input:\n");
  12.         scanf("%s",buf);
  13.     }
  14.     return 0;
  15. }
运行结果:
 大家在tutorial/lexical/keywords下面找到源程序。
阅读(447) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~