词法分析器的设计(c++实现)
读前必看,此篇词法分析器设计。
第一部分传送门:待更新
步骤
用 Visual C++作为实验开发环境,创建一个Win32 Console Application工程,工程名为你的学号,添加三个文件:
(1)存储结构的定义:以LexerDef.h为文件名;
(2)基本操作和算法的定义:以LexerAlgo.h为文件名;
(3)调用基本操作的主程序:以LexerMain.cpp为文件名。
编写程序:
(1)文件LexerDef.h定义单词符号的二元组结构、全局变量、关键字表的结束标志等。
(2)文件LexerAlgo.h实现词法扫描算法scanner及其所需的各种基本操作算法。
(3)文件LexerMain.cpp调用scanner算法,实现词法分析器的功能。
代码
// LexerDef.h
// An highlighted block
#define _KEY_WORD_END "waiting for your expanding" //定义关键字结束标志
/*单词二元组的结构,可以根据需要继续扩充*/
typedef struct
{
int typenum;
char *word;
}WORD;
// LexerAlgo.h
// An highlighted block
#include "LexerDef.h"
char input[255]; //输入缓冲区
char token[255] = ""; //单词缓冲区
int p_input; //输入换缓冲区指针
int p_token; //单词缓冲区指针
char ch; //当前读入字符
// 可扩充的关键字数组
char * rwtab[] = {"begin", "if", "then", "while", "do", "end", _KEY_WORD_END};
// 从缓冲区读取一个字符到 ch中
char m_getch() {
ch = input[p_input];
p_input = p_input + 1;
return (ch);
}
// 去掉空白符号
void getbc(){
while(ch == ' ' || ch == 10){
ch = input[p_input];
p_input = p_input + 1;
}
}
// 拼接单词
void concat(){
token[p_token] = ch;
p_token = p_token + 1;
token[p_token] = '\0';
}
// 判断是否为字母
int letter() {
if(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') return 1;
else return 0;
}
// 判断是否为数字
int digit(){
if(ch >= '0' && ch <= '9') return 1;
else return 0;
}
// 检索关键字表格
int reserve(){
int i = 0;
while(strcmp(rwtab[i], _KEY_WORD_END)){
if(!strcmp(rwtab[i],token)){
return i+1;
}
i = i+1;
}
return 10;
}
// 回退一个字符
void retract(){
p_input = p_input-1;
}
// 数字转换为二进制
char * dtb(){
return NULL;
}
/*
词法扫描程序
*/
WORD * scaner(){
WORD * myword = new WORD;
myword -> typenum = 10;
myword -> word = "";
p_token = 0;
m_getch();
getbc();
if(letter()){
while(letter() || digit()){
concat();
m_getch();
}
retract();
myword -> typenum = reserve();
myword -> word = token;
return(myword);
}
else if(digit()){
while(digit()){
concat();
m_getch();
}
retract();
myword -> typenum = 20;
myword -> word = token;
return(myword);
}
else switch(ch){
case '=': m_getch();
if(ch == '='){
myword -> typenum = 39;
myword -> word = "==";
return(myword);
}
retract();
myword -> typenum = 21;
myword -> word = "=";
return(myword);
break;
case '+': myword->typenum = 22;
myword->word = "+";
return(myword);
break;
case '-': myword->typenum = 23;
myword->word = "-";
return(myword);
break;
case '*': myword->typenum = 24;
myword->word = "*";
return(myword);
break;
case '/': myword->typenum = 25;
myword->word = "/";
return(myword);
break;
case '(': myword->typenum = 26;
myword->word = "(";
return(myword);
break;
case ')': myword->typenum = 27;
myword->word = ")";
return(myword);
break;
case '[': myword->typenum = 28;
myword->word = "[";
return(myword);
break;
case ']': myword->typenum = 29;
myword->word = "]";
return(myword);
break;
case '{': myword->typenum = 30;
myword->word = "{";
return(myword);
break;
case '}': myword->typenum = 31;
myword->word = "}";
return(myword);
break;
case ',': myword->typenum = 32;
myword->word = ",";
return(myword);
break;
case ':': myword->typenum = 33;
myword->word = ":";
return(myword);
break;
case ';': myword->typenum = 34;
myword->word = ";";
return(myword);
break;
case '>': m_getch();
if(ch == '=')
{
myword->typenum = 37;
myword->word = ">=";
return(myword);
}
retract();
myword->typenum = 35;
myword->word = ">";
return(myword);
break;
case '<': m_getch();
if(ch == '=')
{
myword->typenum = 38;
myword->word = "<=";
return(myword);
}
retract();
myword->typenum = 36;
myword->word = "<";
return(myword);
break;
case '!': m_getch();
if(ch == '=')
{
myword->typenum = 40;
myword->word = "!=";
return(myword);
}
retract();
myword->typenum = -1;
myword->word = "ERROR";
return(myword);
break;
case '\0': myword->typenum = 1000;
myword->word = "OVER";
return(myword);
break;
default: myword->typenum = -1;
myword->word = "ERROR";
return(myword);
}
}
// LexerMain.cpp
// An highlighted block
WORD *scaner(); //词法扫描函数,获得一个单词
int main()
{
int over = 1;
WORD *oneword = new WORD;
printf("Enter Your words (end with #):");
scanf("%[^#]s", input); //读入源程序字符到缓冲区,以#结束,允许多行输入
p_input = 0;
printf("Your words: \n %s \n", input);
//对源程序进行分析,直至结束符#
while(over < 1000 && over != -1)
{
oneword = scaner(); //获取新单词
if (oneword->typenum < 1000)
printf("%d, %s", oneword->typenum, oneword->word); //打印种别码和单词自身的值
over = oneword->typenum;
}
printf("\npress # to exit:"); //按#退出程序
scanf("%[^#]s", input);
return 0;
}
运行截图
(1)源程序begin x:=9; if x>0 then x:=2*x+1/3; end #
(2)输入一段此简单语言的源程序,且包含以下单词符号while <> -
好了,到这里已经结束了,这是词法分析器的实现,有想了解详细过程和原理的可以留言或私信我。