int GetAWord()//词法分析,获取一个单词 { static char cACharacter=SPACE;//当前字符 int nAWordIndex;//单词数组下标,表示单词第几个字符 int nDigitNumber;//数单词的字符个数 int i; char szAWord[MAX_LENGTH_OF_A_WORD+1]; int nNumberValue; //数的值

//忽略空格、换行和TAB
while((cACharacter==SPACE || cACharacter==RETURN || cACharacter==TABLE) && cACharacter!=EOF)
	cACharacter=GetACharacterFromFile();//从文件中读取一个字符然后返回

if(cACharacter!=EOF)//如果不是文件末尾
{
	if(cACharacter>='a' && cACharacter<='z')//如果当前字符是小写的字母
	{//标识符或保留字以a..z开头
		nAWordIndex=0;//单词的第一个字符
		do{
			if(nAWordIndex<MAX_LENGTH_OF_A_WORD)
				szAWord[nAWordIndex++]=cACharacter;//把当前字符放进单词数组里,单词数组下标加一
		
			cACharacter=GetACharacterFromFile();//从文件中再读取一个字符
		}while((cACharacter>='a' && cACharacter<='z' || cACharacter>='0' && cACharacter<='9') && cACharacter!=EOF);
		//只要后面继续跟a..z或0..9,就要继续看后面的字符
	
		//当前字符不再是a..z或0..9
		if(cACharacter!=EOF)//如果不是文件末尾
		{
			szAWord[nAWordIndex]=0;//以0结尾,在单词数组中组成一个单词字符串
		
			for(i=0;i<NUMBER_OF_RESERVED_WORDS;i++)//从保留字表中查询当前单词字符串是否为某一保留字字符串
				if(strcmp(szAWord,ReservedWordNameVsTypeTable[i].szName)==0)
				{
					//如果是保留字,则赋当前单词类型为相应保留字的单词类型枚举值
					g_Words[g_nWordsIndex].eType=ReservedWordNameVsTypeTable[i].eType;
					break;
				}
			if(i>=NUMBER_OF_RESERVED_WORDS)
			//如果在保留字表中查询不出,则当前单词是标识符,单词类型为单词类型枚举值IDENTIFIER
				g_Words[g_nWordsIndex].eType=IDENTIFIER;
		
			strcpy(g_Words[g_nWordsIndex].szName,szAWord);//识别出的单词放进单词队列g_Words中
			g_Words[g_nWordsIndex].nLineNo=g_nLineNo;//在源代码文件中单词所在的行数
		
			g_nWordsIndex++;//识别出的单词个数加一
		
			return OK;
		}
		else
			return ERROR;
	}
	else
		if(cACharacter>='0' && cACharacter<='9')
		{//数字是以0..9开头
			nDigitNumber=0;//数单词的字符个数
			nNumberValue=0;//数单词的值
			do{
				szAWord[nDigitNumber++]=cACharacter;
				nNumberValue=10*nNumberValue+cACharacter-'0';//计算数单词的值
			
				cACharacter=GetACharacterFromFile();//再取下一个字符
			}while(cACharacter>='0' && cACharacter<='9' && cACharacter!=EOF);//如果是0..9,则继续拼装数单词
		
			//如果不是0..9则数单词结束
			if(cACharacter!=EOF)
			{
				szAWord[nDigitNumber]=0;//以0结尾在单词数组中组成一个数单词字符串
			
				g_Words[g_nWordsIndex].eType=NUMBER;//单词类型为单词类型枚举值NUMBER
				strcpy(g_Words[g_nWordsIndex].szName,szAWord);//识别出的单词放进单词队列g_Words中
				g_Words[g_nWordsIndex].nNumberValue=nNumberValue;//同时将数的值赋给单词的nNumberValue
				g_Words[g_nWordsIndex].nLineNo=g_nLineNo;//在源代码文件中单词所在的行数
			
				g_nWordsIndex++;//识别出的单词个数加一
			
				return OK;
			}
			else
				return ERROR;
		}
		else
			if(cACharacter==':')//当前符号是':'?
			{
				cACharacter=GetACharacterFromFile();//如果当前符号是':',则要再看下一个符号
				if(cACharacter=='=')//如果下一个符号是'='
				{//则单词是赋值符号':='
					g_Words[g_nWordsIndex].eType=ASSIGN;//单词类型为单词类型枚举值ASSIGN
					strcpy(g_Words[g_nWordsIndex].szName,':='); //识别出的单词放进单词队列g_Words中
					g_Words[g_nWordsIndex].nLineNo=g_nLineNo;//在源代码文件中单词所在的行数
				
					g_nWordsIndex++;//识别出的单词个数加一
				
					cACharacter=GetACharacterFromFile();//再取一个符号,为下一步准备
				
					return OK;
				}
			}
		else
			if(cACharacter=='<')//检测是'<'还是'<='单词?
			{
				cACharacter=GetACharacterFromFile();//再取一个符号
				if(cACharacter=='=')
				{//单词是'<='
					g_Words[g_nWordsIndex].eType=LEQ;//单词类型为单词类型枚举值LEQ
					strcpy(g_Words[g_nWordsIndex].szName,'<='); //识别出的单词放进单词队列g_Words中
					g_Words[g_nWordsIndex].nLineNo=g_nLineNo;//在源代码文件中单词所在的行数
				
					g_nWordsIndex++;//识别出的单词个数加一
				
					cACharacter=GetACharacterFromFile();//再取一个符号,为下一步准备
					
					return OK;
				}
				else
				{//单词仅是'<'
					g_Words[g_nWordsIndex].eType=LES;//单词类型为单词类型枚举值LES
					strcpy(g_Words[g_nWordsIndex].szName,'<'); //识别出的单词放进单词队列g_Words中
					g_Words[g_nWordsIndex].nLineNo=g_nLineNo;//在源代码文件中单词所在的行数
				
					g_nWordsIndex++;//识别出的单词个数加一
				
					return OK;
				}
			}
		else
			if(cACharacter=='>')//检测是'>'还是'>='单词?
			{
				cACharacter=GetACharacterFromFile();//再取一个符号
				if(cACharacter=='=')
				{//单词是'>='
					g_Words[g_nWordsIndex].eType=GEQ;//单词类型为单词类型枚举值GEQ
					strcpy(g_Words[g_nWordsIndex].szName,'>='); //识别出的单词放进单词队列g_Words中
					g_Words[g_nWordsIndex].nLineNo=g_nLineNo;
				
					g_nWordsIndex++;//识别出的单词个数加一
				
					cACharacter=GetACharacterFromFile();//再取一个符号,为下一步准备
				}
				else
				{//单词仅是'>'
					g_Words[g_nWordsIndex].eType=GTR;//单词类型为单词类型枚举值GTR
					strcpy(g_Words[g_nWordsIndex].szName,'>'); //识别出的单词放进单词队列g_Words中
					g_Words[g_nWordsIndex].nLineNo=g_nLineNo;
				
					g_nWordsIndex++;//识别出的单词个数加一
				}
				return OK;
			}
		else
			{//当不满足上述条件时,则是单字符
				//通过查表寻找单字符的单词类型枚举值
				g_Words[g_nWordsIndex].eType=SingleCharacterWordTypeTable[cACharacter];
				g_Words[g_nWordsIndex].szName[0]=cACharacter;//单词放进单词队列g_Words中
				g_Words[g_nWordsIndex].szName[1]=0;//以0结尾组成一个字符串
				g_Words[g_nWordsIndex].nLineNo=g_nLineNo;
			
				g_nWordsIndex++;//识别出的单词个数加一
			
				cACharacter=GetACharacterFromFile();//再取一个符号,为下一步准备
			
				return OK;
			}
}
return ERROR;

} 画出以上PL0语言编译程序的流程图,并说明程序中是如何实现单词错误检查(用自然语言进行描述)。内容:编译程序的流程图如下:

  1. 从文件中获取一个字符,忽略空格、换行和TAB。
  2. 如果字符不是文件末尾,判断字符类型。
    • 如果字符是小写字母,则识别为标识符或保留字。
      • 从文件中继续获取字符,直到不是小写字母或数字为止。
      • 判断识别出的字符串是否为保留字,如果是则设置单词类型为对应的保留字类型,否则设置单词类型为标识符类型。
      • 将识别出的单词放入单词队列中。
    • 如果字符是数字,则识别为数。
      • 从文件中继续获取字符,直到不是数字为止。
      • 将识别出的字符串转换为数值,并设置单词类型为数类型。
      • 将识别出的单词放入单词队列中。
    • 如果字符是冒号,则判断下一个字符是否为等号。
      • 如果是,则识别为赋值符号。
        • 将赋值符号放入单词队列中。
        • 继续从文件中获取下一个字符。
      • 如果不是,则识别为冒号。
        • 将冒号放入单词队列中。
    • 如果字符是小于号,则判断下一个字符是否为等号。
      • 如果是,则识别为小于等于符号。
        • 将小于等于符号放入单词队列中。
        • 继续从文件中获取下一个字符。
      • 如果不是,则识别为小于号。
        • 将小于号放入单词队列中。
    • 如果字符是大于号,则判断下一个字符是否为等号。
      • 如果是,则识别为大于等于符号。
        • 将大于等于符号放入单词队列中。
        • 继续从文件中获取下一个字符。
      • 如果不是,则识别为大于号。
        • 将大于号放入单词队列中。
    • 如果字符不满足上述条件,则判断为单字符。
      • 查找单字符在表中的对应类型。
      • 将单字符放入单词队列中。
      • 继续从文件中获取下一个字符。
  3. 返回OK表示获取单词成功。
  4. 如果字符是文件末尾,返回ERROR表示获取单词失败。

单词错误检查是通过判断字符类型和查表来实现的。根据字符的不同类型,程序将其识别为不同的单词类型,并将单词放入单词队列中。如果字符不属于任何已定义的类型,则判断为单字符,并查找该单字符在表中的对应类型。如果字符是文件末尾,则返回错误表示获取单词失败。

PL0 编译器词法分析:获取一个单词

原文地址: https://www.cveoy.top/t/topic/bAiC 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录