📄 语法分析程序.txt
字号:
/*************************************************************************
* 语法分析1:递归子程序法
*
* 问题描述:设定好自己的文法
* 从控制台读取文件,运用以上文法进行语法分析。
* 将分析结果显示在屏幕上并存入另一文件中。
*
* 说明:1、采用功能独立的小函数段实现。
* 2、使用递归子程序法。
* 3、内码对照表见《编译方法》(马知行,曹启君编)P167。
* 4、本程序实现过程未参照上述书上。
* 5、本程序在原有词法分析程序基础上修改而成。
* 6、所读取文件和存储文件在本工程所在目录下。
* 7、定义文法:(读取文件以"#"结尾)
* (1)主函数:S()
* void main()
* {
* 整型定义;
* 整型定义;
* for循环;
* if判断;
* return;
* }
* (2)整型定义或赋值(a为任一标示符):A()
* int a=2;
* 或:
* a=3;
* (3)for循环:B()
* for(i=0;i<3;i++)(i为任一标示符)
* {
* 整型赋值;
* }
* (4)if判断:C()
* if(a=0)
* {
* 整型赋值;
* }
*
************************************************************************/
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<process.h>
#include<iostream.h>
#define LENKEY 15
#define LENSIGN 17
#define WRITEFILE "D:\\write.txt"
struct{
char name[31];
int addr;
}word[1000]; //word[1000]: 存储已分析单词的名称和内码
char *keyword[LENKEY] = {"program","const","var","integer","long","procedure","if","then","while","do","read","write","begin","end","odd"};
char *sign[LENSIGN] = {"+","-","*","/","=","<>","<","<=",">",">=",".",",",";",":",":=","(",")"};
FILE *f,*fw;
int totalwords = 0; //totalwords: 当前已分析单词的数量
int next=0; //next: 当前的单词序号
char w[20];
void SaveWords(int,char *[]); //SaveWords(): 将文件中的单词存入word[]中
void get_w(); //get_w(): 读取一个单词
void S(); //S(): 分析main()函数
void A(); //A(): 分析整型定义和赋值
void B(); //B(): 分析for循环
void C(); //C(): 分析if判断
void OpenFile(char *,char *); //OpenFile(): 打开文件
void ReadLine(FILE *,char []); //ReadLine(): 读取文件中一行
void DealLine(char []); //DealLine(): 处理一行
bool Analyse(char []); //Analyse(): 分析一个单词
bool AnalyseSign(char []); //AnalyseSign(): 分析一个符号单词
bool AnalyseAlpha(char a[]); //AnalyseAlpha(): 分析一个关键字或标示符单词
bool AnalyseNum(char n[]); //AnalyseNum(): 分析一个整数单词
void DealError(char []); //DealError(): 处理错误信息
void DealResult(FILE *); //DealResult(): 输出结果,并将结果写入文件
/*************************************************************************
* 主函数
************************************************************************/
void main(int argc,char *argv[])
{
SaveWords(argc,argv);
//语法分析
get_w();
S();
get_w();
if(strcmp(w,"#")!=0)
{
cout<<""<<endl;
fprintf(fw,"Error!");
}
return;
fclose(fw);
}
/*************************************************************************
* 函数名称:
* get_w()
* 参数:
* 无。
* 返回值:
* 空。
* 功能:
* 从word[]中读取一个单词。
************************************************************************/
void get_w()
{
strcpy(w,word[next].name);
next++;
}
/*************************************************************************
* 函数名称:
* S()
* 参数:
* 无。
* 返回值:
* 空。
* 功能:
* 分析主函数。
************************************************************************/
void S()
{
if(strcmp(w,"void")==0)
{
get_w();
if(strcmp(w,"main")==0)
{
get_w();
if(strcmp(w,"(")==0)
{
get_w();
if(strcmp(w,")")==0)
{
get_w();
if(strcmp(w,"{")==0)
{
get_w();
A(); //定义整型变量
get_w();
A(); //定义整型变量
get_w();
B(); //判断for循环
get_w();
C(); //判断if判断
get_w();
if(strcmp(w,"return")==0)
{
get_w();
if(strcmp(w,";")==0)
{
get_w();
if(strcmp(w,"}")==0)
{
cout<<"符合所定义语法"<<endl;
fprintf(fw,"符合所定义语法");
return;
}
}
}
}
}
}
}
}
cout<<"不符合所定义语法"<<endl;
fprintf(fw,"不符合所定义语法");
return;
}
/*************************************************************************
* 函数名称:
* A()
* 参数:
* 无。
* 返回值:
* 空。
* 功能:
* 分析整型定义或赋值。
************************************************************************/
void A()
{
if(strcmp(w,"int")==0)
{
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,";")==0)
return;
}
}
}
}
else if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,";")==0)
return;
}
}
}
cout<<"A不符合整型定义"<<endl;
fprintf(fw,"A不符合整型定义");
return;
}
/*************************************************************************
* 函数名称:
* B()
* 参数:
* 无。
* 返回值:
* 空。
* 功能:
* 分析for循环。
************************************************************************/
void B()
{
if(strcmp(w,"for")==0)
{
get_w();
if(strcmp(w,"(")==0)
{
get_w();
A(); //i=0
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"<")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,";")==0)
{
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"+")==0)
{
get_w();
if(strcmp(w,"+")==0)
{
get_w();
if(strcmp(w,")")==0)
{
get_w();
if(strcmp(w,"{")==0)
{
get_w();
A();
get_w();
if(strcmp(w,"}")==0)
{
return;
}
}
}
}
}
}
}
}
}
}
}
}
cout<<"B不符合for循环定义"<<endl;
fprintf(fw,"B不符合for循环定义");
}
/*************************************************************************
* 函数名称:
* C()
* 参数:
* 无。
* 返回值:
* 空。
* 功能:
* 判断if语句。
************************************************************************/
void C()//if判断
{
if(strcmp(w,"if")==0)
{
get_w();
if(strcmp(w,"(")==0)
{
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,")")==0)
{
get_w();
if(strcmp(w,"{")==0)
{
get_w();
A();
get_w();
if(strcmp(w,"}")==0)
{
return;
}
}
}
}
}
}
}
}
}
cout<<"C不符合if循环定义"<<endl;
fprintf(fw,"C不符合if循环定义");
}
/*************************************************************************
* 函数名称:
* SaveWords()
* 参数:
* int argc2 - 控制台输入的参数个数;
* char *argv2[] - 控制台输入的参数。
* 返回值:
* 空。
* 功能:
* 将文件中读取的单词存入word[]中。
************************************************************************/
void SaveWords(int argc2,char *argv2[])
{
FILE *fread,*fwrite;
char line[200];
//打开文件
OpenFile(argv2[2],"w");
fw=f;
OpenFile(argv2[1],"r");
fread=f;
if(argc2<3)OpenFile(WRITEFILE,"w");
else OpenFile(argv2[2],"w");
fwrite=f;
//读取一行,处理一行
while(!feof(fread))
{
ReadLine(fread,line);
DealLine(line);
}
//关闭文件
fclose(fread);
fclose(fwrite);
}
/*************************************************************************
* 函数名称:
* OpenFile()
* 参数:
* char *route - 文件所在路径;
* char *manner - 文件打开方式。
* 返回值:
* 空。
* 功能:
* 打开文件。
************************************************************************/
void OpenFile(char *route,char *manner)
{
if((f = fopen(route,manner))==NULL)
{
printf("connot open the file\n");
exit(0);
}
}
/*************************************************************************
* 函数名称:
* ReadLine()
* 参数:
* FILE *f - 所要读取的文件;
* char line[] - 读到的一行。
* 返回值:
* 空。
* 功能:
* 读取文件中的一行。
************************************************************************/
void ReadLine(FILE *f,char line[])
{
if(feof(f))return;
int i=0;
char ch = fgetc(f);
while(ch!='\n'&&!feof(f))
{
line[i]=ch;
i++;
ch = fgetc(f);
}
line[i] = '\0';
return;
}
/*************************************************************************
* 函数名称:
* DealLine()
* 参数:
* char line[] - 已读取的文件中的一行。
* 返回值:
* 空。
* 功能:
* 处理已读取的文件中的一行。
************************************************************************/
void DealLine(char line[])
{
int i=0,n=0;
char str[30];
while(line[i]!='\0')
{
//略去空格
while(isspace(line[i]))
i++;
//关键字、标示符、无符号整数(字母、数字、下划线的组合)
while((line[i]!='\0')&&(isalnum(line[i])||isalpha(line[i])||line[i]=='_'))
{
str[n]=line[i];
n++;
i++;
}
if(n>0)
{
str[n]='\0';
if(!Analyse(str))
{
i=i-strlen(str);
str[0]=line[i];
str[1]='\0';
i++;
Analyse(str);
}
n=0;
}
//符号、错误词法
while((line[i]!='\0')&&(!isalnum(line[i]))&&(!isalpha(line[i]))&&(line[i]!='_'))
{
while(isspace(line[i]))
i++;
if((line[i]!='\0')&&((isalnum(line[i]))||(isalpha(line[i]))||(line[i]=='_')))break;
str[n]=line[i];
n++;
i++;
}
if(n>0)
{
str[n]='\0';
if(!Analyse(str))
{
i=i-strlen(str);
str[0]=line[i];
str[1]='\0';
i++;
Analyse(str);
}
n=0;
}
}
return;
}
/*************************************************************************
* 函数名称:
* Analyse()
* 参数:
* char str[] - 在一行中提取的一个单词。
* 返回值:
* true - 处理无异常。
* false - 该单词包含相邻的字符,需退出重新划分单词。
* 功能:
* 分析一个单词。
************************************************************************/
bool Analyse(char str[])
{
int n=0,i=0,num=0;
//以字母或下划线开头
if((isalpha(str[0]))||(str[0]=='_'))
AnalyseAlpha(str);
//以数字开头
else if(isalnum(str[0]))
{
if(!AnalyseNum(str))
DealError(str);
}
//其它情况
else
{
//多个符号相邻的情况
if((strlen(str)>1)&&(strcmp(str,"<>")!=0)&&(strcmp(str,"<=")!=0)&&(strcmp(str,">=")!=0)&&(strcmp(str,":=")!=0))
return false;
if(!AnalyseSign(str))
DealError(str);
}
return true;
}
/*************************************************************************
* 函数名称:
* AnalyseAlpha()
* 参数:
* char a[] - 待分析的字母和数字组合单词。
* 返回值:
* true - 属于内部码中的单词。
* 功能:
* 分析一个单词是否是关键字或标示符。
************************************************************************/
bool AnalyseAlpha(char a[])
{
int i=0;
for(i=0;i<LENKEY;i++)
{
if(!strcmp(a,keyword[i]))
{
strcpy(word[totalwords].name,keyword[i]);
word[totalwords].addr = i+1;
totalwords++;
return true;
}
}
strcpy(word[totalwords].name,a);
word[totalwords].addr = 34;
totalwords++;
return true;
}
/*************************************************************************
* 函数名称:
* AnalyseNum()
* 参数:
* char n[] - 待分析的符号单词。
* 返回值:
* true - 属于内部码中的单词。
* false - 不属于内部码中的无符号整数。
* 功能:
* 分析一个单词是否是内部码中的无符号整数。
************************************************************************/
bool AnalyseNum(char n[])
{
int i=0;
for(i=0;i<(int)strlen(n);i++)
if(n[i]<'0'||n[i]>'9')
return false;
strcpy(word[totalwords].name,n);
word[totalwords].addr = 33;
totalwords++;
return true;
}
/*************************************************************************
* 函数名称:
* AnalyseSign()
* 参数:
* char s[] - 待分析的符号单词。
* 返回值:
* true - 属于内部码中的单词。
* false - 不属于内部码中的符号单词。
* 功能:
* 分析一个单词是否是内部码中的符号单词。
************************************************************************/
bool AnalyseSign(char s[])
{
int i=0;
for(i=0;i<LENSIGN;i++)
{
if(!strcmp(s,sign[i]))
{
strcpy(word[totalwords].name,s);
word[totalwords].addr = i+16;
totalwords++;
return true;
}
}
if(!strcmp(s,"#"))
{
strcpy(word[totalwords].name,s);
word[totalwords].addr = 35;
totalwords++;
return true;
}
return false;
}
/*************************************************************************
* 函数名称:
* DealError()
* 参数:
* char str[] - 错误的单词。
* 返回值:
* 空。
* 功能:
* 处理错误单词。
************************************************************************/
void DealError(char str[])
{
strcpy(word[totalwords].name,str);
word[totalwords].addr = 36;
totalwords++;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -