参考文章
http://www.zengl.com/html/genlanmu/zenglbianchengyuyan/article-2.html
enum TOKENTYPE getToken()
{
enum STATES state = START;//设置起始状态为START
enum TOKENTYPE token;
while(state!=DOWN)//当state状态为DOWN时,表示找到一个变量或者别的token(一般变量,加减符号,数字等每个扫描出来的元素都称作token)
{
char ch = getNextchar(); //打开一个文件,并从中读取一个字符
switch(state)
{
词法分析函数();
}//switch(state)
}//while(state!=DOWN)
return token;
}//enum TOKENTYPE getToken()
***********************************************************
词法分析函数();
case START:
START处理函数();
break;
case INID:
INID处理函数();
break;
case INNUM:
INNUM处理函数();
break;
可以看出,词法分析函数分成来 三个部分,
***************************************************
START处理函数();
if(ch==' ' || ch=='t' || ch=='n') //如果是换行回车之类的就跳过。
continue;
else if(isalpha(ch)) //判断读取的字符是否是英文字母。
{
state=INID; //如果是字母,我们就将state状态机设置为INID 。
makeTokenStr(ch); //然后将读取出来的ch字符通过函数makeTokenStr加入到TokenString动态字符串里
}
else if(isdigit(ch)) //判断读取的字符是否是数字
{
state=INNUM; //如果是数字,我们就将state状态机设置为INNUM 。
makeTokenStr(ch); //然后将读取出来的ch字符通过函数makeTokenStr加入到TokenString动态字符串里
}
else
{
处理ch函数();
}//switch(ch)
makeTokenStr(ch);
}
******************************************************
INID处理函数();
if(isalpha(ch)) //在INID状态下,一直读取字符,直到该字符不是字母为止,并将读取的字母通过makeTokenStr构成完整的标示符。
makeTokenStr(ch);
else
{
state = DOWN;
token = ID; //将token设为ID表示读取到了一个标示符。ID即identifier 英文缩写。
ungetchar(); //因为多读取了一个非字母的字符,所以用ungetchar函数来回退一个字符,供下一次扫描使用。
}
********************************************************
INNUM处理函数();
if(isdigit(ch)) //在INNUM状态下,一直读取字符,直到该字符不是数字为止,并将读取的单个数字通过makeTokenStr构成完整的数值。
makeTokenStr(ch);
else
{
state = DOWN;
token = NUM; //将token设为NUM表示读取到了一个数字。
ungetchar();
}
************************************************************
其实词法扫描器就是循环读取文件里的字符。
并通过读取到的首字符判断是哪种类型的token,如果是字母,说明当前读到的部分是标示符,就将state状 态机由START开始读取的状态转为INID(在identifier的状态即处于标示符的读取状态),在INID的switch case里将后面的连续的字母和首字母一起构成一个完整的标示符,并将这些连续的字母存放到TokenString动态字符串里,这样就找到了一个 token了。
其他的数字,运算符之类的Token也是同理查找。
************************************************************
enum TOKENTYPE{
ID,NUM,PLUS,MINIS,TIMES,DIVIDE,ASSIGN,ENDFILE,ERROR
};
enum STATES{
START,INID,INNUM,DOWN
};
***********************************************************
处理ch函数();
state = DOWN; //如果字符是‘+’号就将state状态机设为DOWN,这样就可以结束循环,并把token设为PLUS枚举值,表示找到加号运算符。
token = PLUS;
break;
case '-':
state = DOWN; //和上面同理
token = MINIS;
break;
case '*':
state = DOWN; //和上面同理
token = TIMES;
break;
case '/':
state = DOWN; //和上面同理
token = DIVIDE;
break;
case '=':
state = DOWN; //和上面同理
token = ASSIGN;
break;
case EOF:
state = DOWN; //EOF字符表示读取到了文件的结尾,则返回ENDFILE的token,在外层main函数的主循环就会结束扫描。
token = ENDFILE;
break;
default:
state = DOWN; //其他情况下表示读取到了未定义的token,那么就返回ERROR。
token = ERROR;
break;
*******************************************************************************
其它的函数刚开始都可以理解成黑盒子,即直接使用,其具体实现可以以后再理解,这样不影响编译器学习,也不至于负担太重。
getNextchar();
isalpha();
isdigit();
makeTokenStr();
ungetchar()。