在编译原理介绍中,我们已经对前端的工作有了大致的了解词法分析器的任务是读入源程序,对其进行一定的切分,得到记号流
对于字符流和记号流之间的区别,下面给出一个例子来说明
- if (x > 5)
- y = "hello";
- else
- z = 1;
对面上面这段程序,在词法分析器的眼中,是这样表示的:
i, f, " ", (, x, " ",>, " ", 5, ), n, " "," ", y, " ", =, .........
可见词法分析器看到的字符流和我们眼中的字符流是不一样的。 而词法分析器的任务就是对字符进行 切分。将 i 和 f 并在一起做为一个 if 关键字,去除掉没有意义的空格等等对于像 IF,LPAREN,IDENT 等的单词,我们都称为记号
在记号中,有一些记号是没有属性的,类似于 IF 之类的关键字, IDENT (x) 之类的标识符需要表明其中的元素具体是什么
记号的数据结构定义如下:
- enum kind {IF, LPAREN, ID, INTLIT, ...};
- struct token{
- enum kind k;
- char *lexname;
- }
因此,对于语句 if (x> 5) 可以转变为
- token {
- k = IF;
- lexname = 0; //0 表示没有赋任何的值
- }
- token {
- k = LPAREN;
- laxname = 0;
- }
- token {
- k = ID;
- laxname = "x";
- }
- ....
通过上面的学习,我们可以知道词法分析器的任务是将字符流转化为记号流
- 字符流:和被编译的语言密切相关(ASCII(C), Unicode(Java, Swift), or ...)
- 记号流:编译器内部定义的数据结构,编码所识别出的词法单元