在上一篇文章中已经介绍了读文件的操作,那么这一篇文章中将会细致解释词法分析。
在源文件里解析出的单词流必须识别为保留字,标识符,常量,操作符和界符五大类
1.显然我们须要列举出全部的保留字,而这里与保留字相似的那么就是标识符,在C语言中,保留字都是以小写字母开头,并且当中的字母仅仅能是小写字母,而标识符的第一个字母则必须为字符(小写大写皆可)后面能够接大写和小写字母和字符 ‘_’, 在我写的这个编译器中,标识符不能超过100,在C语言中的标识符定义的长度大小远远大于此。
2.对于常量,这里须要注意的是整型和浮点型常量。
3.运算符依照的是以下的表:
C语言运算符表
运算符依照优先级大小由上向下排列,在同一行的运算符具有同样优先级。第二行是全部的一元运算符。
|
|
|
() [] -> . | 括号(函数等),数组,两种结构成员訪问 |
|
! ~ ++ -- + -
* & |
否定,按位否定,增量,减量,正负号,
间接,取地址 |
|
* / % | 乘,除,取模 |
|
+ - | 加,减 |
|
<< >> | 左移,右移 |
|
< <= >= > | 小于,小于等于,大于等于,大于 |
|
== != | 等于,不等于 |
|
& | 按位与 |
|
^ | 按位异或 |
|
| | 按位或 |
|
&& | 逻辑与 |
|
|| | 逻辑或 |
|
? : | 条件 |
|
= += -= *= /=
&= ^= |= <<= >>= |
各种赋值 |
|
, | 逗号(顺序) |
|
4.界符:“;”“{}”,单引號,双引號
接下来我介绍的是对保留字的归类,为了查找方便,将保留字依照a-z的顺序排好,根据数组的下标定位,降低寻找的时间
/* * keyword.h * * Created on: Jun 12, 2014 * */ #ifndef KEYWORD_H_ #define KEYWORD_H_ struct keyword{ char *keyName; }; static struct keyword key__[]={ {"__int64"}, {"end"} }; static struct keyword key_A[]={ {"auto"}, {"end"} }; static struct keyword key_B[]={ {"break"}, {"end"} }; static struct keyword key_C[]={ {"case"}, {"char"}, {"const"}, {"continue"}, {"end"} }; static struct keyword key_D[]={ {"default"}, {"do"}, {"double"}, {"end"} }; static struct keyword key_E[]={ {"else"}, {"enum"}, {"extern"}, {"end"} }; static struct keyword key_F[]={ {"float"}, {"for"}, {"end"} }; static struct keyword key_G[]={ {"goto"}, {"end"} }; static struct keyword key_H[]={ {"end"} }; static struct keyword key_I[]={ {"if"}, {"int"}, {"end"} }; static struct keyword key_J[]={ {"end"} }; static struct keyword key_K[]={ {"end"} }; static struct keyword key_L[]={ {"long"}, {"end"} }; static struct keyword key_M[]={ {"end"} }; static struct keyword key_N[]={ {"end"} }; static struct keyword key_O[]={ {"end"} }; static struct keyword key_P[]={ {"end"} }; static struct keyword key_Q[]={ {"end"} }; static struct keyword key_R[]={ {"register"}, {"return"}, {"end"} }; static struct keyword key_S[]={ {"short"}, {"signed"}, {"sizeof"}, {"static"}, {"struct"}, {"switch"}, {"end"} }; static struct keyword key_T[]={ {"typedef"}, {"end"} }; static struct keyword key_U[]={ {"union"}, {"unsigned"}, {"end"} }; static struct keyword key_V[]={ {"void"}, {"volatile"}, {"end"} }; static struct keyword key_W[]={ {"while"}, {"end"} }; static struct keyword key_X[]={ {"end"} }; static struct keyword key_Y[]={ {"end"} }; static struct keyword key_Z[]={ {"end"} }; // size is 27 static struct keyword *keywords[]={ key__,key_A,key_B,key_C,key_D,key_E, key_F,key_G,key_H,key_I,key_J,key_K, key_L,key_M,key_N,key_O,key_P,key_Q, key_R,key_S,key_T,key_U,key_V,key_W, key_X,key_Y,key_Z }; #endif /* KEYWORD_H_ */
以下是词法分析的源代码;
/* * lex.h * * Created on: Jun 13, 2014 * */ #include "input.h" #include "keyword.h" #define isDigit(c) (c>='0' && c<='9') #define isUpperLetter(c) (c>='A' && c <='Z') #define isLowerLetter(c) (c>='a' && c<='z') #define isLetter(c) (isUpperLetter || isLowerLetter)
/* * lex.c * * Created on: Jun 13, 2014 * */ #include "zcc.h" #include "lex.h" #define curr source.cursor int getToken() { char a[100]; int a_length, i, flag; /* *skip ' ',' ' and '' */ while (*curr == ' ' || *curr == 10 || *curr == 9) { curr++; if (*curr == END_OF_FILE) { return -1; } } /* name or keyword on first is a-z */ a_length=0; if (*curr >= 'a' && *curr <= 'z') { IDAndKey: a_length = 0; do { a[a_length++] = *curr++; } while ( isDigit(*curr) || isUpperLetter(*curr) || isLowerLetter(*curr) || *curr == '_'); a[a_length] = '