PL0 编译器词法分析:获取一个单词
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语言编译程序的流程图,并说明程序中是如何实现单词错误检查(用自然语言进行描述)。内容:编译程序的流程图如下:
- 从文件中获取一个字符,忽略空格、换行和TAB。
- 如果字符不是文件末尾,判断字符类型。
- 如果字符是小写字母,则识别为标识符或保留字。
- 从文件中继续获取字符,直到不是小写字母或数字为止。
- 判断识别出的字符串是否为保留字,如果是则设置单词类型为对应的保留字类型,否则设置单词类型为标识符类型。
- 将识别出的单词放入单词队列中。
- 如果字符是数字,则识别为数。
- 从文件中继续获取字符,直到不是数字为止。
- 将识别出的字符串转换为数值,并设置单词类型为数类型。
- 将识别出的单词放入单词队列中。
- 如果字符是冒号,则判断下一个字符是否为等号。
- 如果是,则识别为赋值符号。
- 将赋值符号放入单词队列中。
- 继续从文件中获取下一个字符。
- 如果不是,则识别为冒号。
- 将冒号放入单词队列中。
- 如果是,则识别为赋值符号。
- 如果字符是小于号,则判断下一个字符是否为等号。
- 如果是,则识别为小于等于符号。
- 将小于等于符号放入单词队列中。
- 继续从文件中获取下一个字符。
- 如果不是,则识别为小于号。
- 将小于号放入单词队列中。
- 如果是,则识别为小于等于符号。
- 如果字符是大于号,则判断下一个字符是否为等号。
- 如果是,则识别为大于等于符号。
- 将大于等于符号放入单词队列中。
- 继续从文件中获取下一个字符。
- 如果不是,则识别为大于号。
- 将大于号放入单词队列中。
- 如果是,则识别为大于等于符号。
- 如果字符不满足上述条件,则判断为单字符。
- 查找单字符在表中的对应类型。
- 将单字符放入单词队列中。
- 继续从文件中获取下一个字符。
- 如果字符是小写字母,则识别为标识符或保留字。
- 返回OK表示获取单词成功。
- 如果字符是文件末尾,返回ERROR表示获取单词失败。
单词错误检查是通过判断字符类型和查表来实现的。根据字符的不同类型,程序将其识别为不同的单词类型,并将单词放入单词队列中。如果字符不属于任何已定义的类型,则判断为单字符,并查找该单字符在表中的对应类型。如果字符是文件末尾,则返回错误表示获取单词失败。
原文地址: https://www.cveoy.top/t/topic/bAiC 著作权归作者所有。请勿转载和采集!