⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 analyse.cpp

📁 此法分析器代码。从测试文件读入输入字符
💻 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 + -