📄 analyse.cpp
字号:
// Analyse.cpp : 定义控制台应用程序的入口点。
//
// Parse.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "analyse.h"
/* states in scanner DFA */
typedef enum
// = /* < > / != */
{ START,INASSIGN,INCOMMENT,INNUM,INID,INLITTLE,INLARGE,INDIVIDE,UNEQUAL,INREFOVER,DONE }
StateType;
/* lexeme of identifier or reserved word */
char tokenString[MAXTOKENLEN+1];
CToken::CToken(FILE *InFile,FILE *OutFile)
{
source=InFile;
listing=OutFile;
linepos = 0; /* current position in LineBuf */
bufsize = 0; /* current size of buffer string */
lineno = 0;
EOF_flag = false;
}
CToken::~CToken()
{
fclose(source);
fclose(listing);
}
char CToken::getNextChar(void)
{
if (!(linepos < bufsize))
{
lineno++;
if (fgets(lineBuf,BUFLEN-1,source))
{
bufsize = strlen(lineBuf); //get the line's length
linepos = 0;
return lineBuf[linepos++];
}
else
{
EOF_flag = true;
return EOF;
}
}
else return lineBuf[linepos++];
}
void CToken::ungetNextChar(void)
{
if (!EOF_flag) linepos-- ;
}
/* 保留字表 */
static struct
{ char* str;
TokenType tok;
} reservedWords[MAXRESERVED]
= {{"if",IF},{"int",INT},{"else",ELSE},{"return",RETURN},
{"void",VOID},{"while",WHILE}};
TokenType CToken::reservedLookup (char * s)
{
int i;
for (i=0;i<MAXRESERVED;i++)
if (!strcmp(s,reservedWords[i].str))
return reservedWords[i].tok;
return ID;
}
void CToken::getToken(void)
{
/* index for storing into tokenString */
int tokenStringIndex = 0;
/* holds current token to be returned */
TokenType currentToken;
/* current state - always begins at START
StateType类型包括:START,INASSIGN,INCOMMENT,INNUM,INID,DONE,INLITTLE,INLARGE,UNEQUAL
*/
StateType state = START;
/* flag to indicate save to tokenString */
bool save = false;
while (state != DONE)
{
char c = getNextChar();
save = true;
switch (state)
{
case START: //开始状态时,有穷自动机遇到各种输入字符的转换函数
if (isdigit(c))
state = INNUM;
else if (isalpha(c))
state = INID;
else if (c == '=')
state = INASSIGN;
else if (c == '<')
state = INLITTLE;
else if (c == '>')
state = INLARGE;
else if (c == '!')
state = UNEQUAL;
else if ((c == ' ') || (c == '\t') || (c == '\n'))
save = false;
else if (c == '/')
state = INDIVIDE;
else
{ state = DONE;
switch (c)
{
case EOF:
save = false;
currentToken = ENDFILE;
break;
case '+':
currentToken = PLUS;
break;
case '-':
currentToken = MINUS;
break;
case '*':
currentToken = MULTIP;
break;
case '(':
currentToken = LPARENl;
break;
case ')':
currentToken = RPAREN1;
break;
case '[':
currentToken = LPAREN2;
break;
case ']':
currentToken = RPAREN2;
break;
case '{':
currentToken = LPAREN3;
break;
case '}':
currentToken = RPAREN3;
break;
case ';':
currentToken = SEMI;
break;
case ',':
currentToken = COMMA;
case '\0':
currentToken=ENDFILE;
break;
default:
currentToken = ERROR; //处理错误,ERROR
break;
}
}
break;
case INCOMMENT: //注释语句状态时,分析注释语句(注意与一般语法语句的区别
save = false;
if (c == EOF) //注释/*与*/ 不匹配
{
state = DONE;
currentToken = WRONGCOMMENT;
}
else if (c == '*') state = INREFOVER;//注释中又出现*字符
else state = INCOMMENT;//注释语句还未结束
break;
case INDIVIDE: // 当下一个字符为/时
state = DONE;
if(c == '*') //注释语句状态时
{
tokenStringIndex--;
save = false;
state = INCOMMENT;
}
else //不是注释语句状态,是除法操作符
{
ungetNextChar();
save = false;
currentToken = DIVIDE;
}
break;
//对注释的处理
case INREFOVER:
save = false;
if (c == '/')//注释语句开始
{
state = START;
}
else if(c == '*')
state = INREFOVER;
else state = INCOMMENT;
break;
// 识别符号“== ”
case INASSIGN:
state = DONE;
if (c == '=') //当第一个字符为=时,区分‘=’和‘==’
currentToken = EQ;
else //否则是赋值
{
ungetNextChar();
save = false;
currentToken = ASSIGN;
}
break;
//识别小于等于“<=”和"<"
case INLITTLE:
state = DONE;
if (c == '=')
{
currentToken = LTE;
}
else
{
ungetNextChar();
save = false;
currentToken = LT;
}
break;
//识别大于等于“>=”和">"
case INLARGE:
state = DONE;
if(c == '=')
{
currentToken = GTE;
}
else
{
ungetNextChar();
save = false;
currentToken = GT;
}
break;
case UNEQUAL:
state = DONE;
if(c == '=')//此时的字串为“!=”
{
currentToken = DIF;
}
else//出现的不是“=”,则认为是非法字符
{
ungetNextChar();
save = false;
currentToken = WRONGDIF;
}
break;
case INNUM:
if (!isdigit(c))
{/* backup in the input */
ungetNextChar();
save = false;
state = DONE;
currentToken = NUM;
}
break;
case INID:
if (!isalpha(c))
{ /* backup in the inpu */
ungetNextChar();
save = false;
state = DONE;
currentToken = ID;
}
break;
case DONE://停止扫描
default: /* should never happen */
cout<<"Scanner Bug: state="<<state<<endl;
state = DONE;
//对于非法字符串的处理
currentToken = ERROR;
break;
}
if ((save) && (tokenStringIndex <= MAXTOKENLEN))
tokenString[tokenStringIndex++] = (char) c;
if (state == DONE)
{
tokenString[tokenStringIndex] = '\0';
if (currentToken == ID)
currentToken = reservedLookup(tokenString);
else if (currentToken == WRONGCOMMENT)
cout<<"Scanner Bug: state="<<state<<" Wrong Comment! may be you forget '/' ?"<<endl;
else if (currentToken == WRONGDIF)
cout<<"Scanner Bug: state="<<state<<" Wrong Different! may be you forget '=' ?"<<endl;
fprintf(listing,"Line:%4d TokenCode:%4d values: %s\n",lineno,(int)currentToken,tokenString);
}
}
}
//参数分别为:输入的测试源文件名,接受token的目标文件名
void main(int argc,char *argv[])
{
if(argc< 2)
{
cout<<"Error Parameter! please enter your sourcefile and tokenfile!\n"<<endl;
return;
}
FILE *InFile,*OutFile;
if ((InFile=fopen(argv[1],"r"))==NULL)
{
cout<<"Can't open sourcefile!"<<endl;
return;
}
if ((OutFile=fopen(argv[2],"w"))==NULL)
{
cout<<"Can't create tokenfile!"<<endl;
return;
}
CToken mToken(InFile,OutFile);
cout<<"Starting scan..."<<endl;
while(!mToken.EOF_flag)
{
mToken.getToken();
}
cout<<"Done!"<<endl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -