编译原理词法分析程序实现实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理词法分析程序实现实验报告实验一词法分析程序实现
一、实验内容
选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,,,*,/, ( , ) 构成的算术表达式,如
1.5E+2,100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
二、设计部分
因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:
输入字符p指向第一个字符
符号识别*p=+||-||*||/
YYNN*p=0~9*p=E*p=0~9||"."
N无效符号Y
*p=“.”GOTO 2
GOTO 1
GOTO 1:
NY无符号数GOTO 1*p=0~9*p='/0'
YN
P++NNP++*p=E*p='+'||'-'
YY
P++P++continue
YY
*p=0~9*p=0~9
NN
无符号数无符号数
P++P++
continuecontinue
GOTO 2:
GOTO 2
*p=Econtinue
Y
无符号数
P++
continue
三、源程序代码部分
#include <stdio.h>
#include<stdlib.h>
#include <math.h>
#define MAX 100
#define UNSIGNEDNUMBER 1 #define PLUS 2
#define SUBTRACT 3
#define MULTIPLY 4
#define DIVIDE 5
#define LEFTBRACKET 6 #define RIGHTBRACKET 7 #define INEFFICACIOUSLABEL 8 #define FINISH 111
int count=0;
int Class;
void StoreType();
int Type[100];
char Store[20]={'\0'}; void ShowStrFile();//已经将要识别的字符串存在文件a中 void Output(int a,char *p1,char *p2);//字符的输出过程 int Sign(char *p);//'+''-''*''/'整体识别过程
int UnsignedNum(char *p);//是否适合合法的正整数0~9 int LegalCharacter(char *p);//是否是合法的字
符:Sign(p)||UnsignedNum(p)||'E'||'.'
void DistinguishSign(char *p);//'+''-''*''/'具体识别过程 void TypyDistinguish();//字符的识别过程
void ShowType();//将类别码存储在Type[100]中,为语法分析做准备
void ShowStrFile()//已经将要识别的字符串存在文件a中 {
FILE *fp_s;
char ch;
if((fp_s=fopen("a.txt","r"))==NULL)
{printf("The FILE cannot open!");
exit(0);
}
else
ch=fgetc(fp_s);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp_s);
}
printf("\n");
}
void StoreStr()//将文件中的字符串存储到数组Store[i] { FILE *fp=fopen("a.txt","r");
char str;
int i=0;
while(!feof(fp))
{
fscanf(fp,"%c",&str);
if(str=='?')
{
Store[i]='\0';
break;
}
Store[i]=str;
i++;
}
Store[i]='\0';
}
void ShowStore()
{int i;
for (i=0;Store[i]!='\0';i++)
printf("%c",Store[i]);
printf("\n");
}
void Output(int a,char *p1,char *p2)
{
printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");
while(p1<=p2)
{
printf("%c",*p1);
p1++;
}
printf("\n");
}
int Sign(char *p)
{
char ch=*p;
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;
else
return 0;
}
int UnsignedNum(char *p) {
char ch=*p;
if('0'<=ch&&ch<='9')
return 1;
else
return 0;
}
int LegalCharacter(char *p) {
char ch=*p;
if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.') return 1;
else return 0;
}
void DistinguishSign(char *p) { int Class;
char ch=*p;
switch(ch)
{
case '+':
Output(PLUS,p,p);Type[count++]=PLUS;break;
case '-':
Output(SUBTRACT,p,p);Type[count++]=SUBTRACT;break; case '*':
Output(MULTIPLY,p,p);Type[count++]=MULTIPLY;break; case '/':
Output(DIVIDE,p,p);Type[count++]=DIVIDE;break; case '(':
Output(LEFTBRACKET,p,p);Type[count++]=LEFTBRACKET;break; case ')':
Output(RIGHTBRACKET,p,p);Type[count++]=RIGHTBRACKET;break; default:
break;
}
}
void TypyDistinguish()
{
printf("词法开始,分析结果如下:\n");
char *p;
p=&Store[0];
while(*p!='\0')
{
if(Sign(p))
{
DistinguishSign(p++);
continue;
}
else if(UnsignedNum(p)||*p=='.')
{
char *p1=p;
if(UnsignedNum(p))
{
while(UnsignedNum(p))
p++;
if(*p=='\0')
{
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
else if(*p=='E')
{
p++;
if(UnsignedNum(p))
{
while(UnsignedNum(p))
p++;
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
else if(*p=='+'||*p=='-')
{
p++;
while(UnsignedNum(p))
p++;
Output(UNSIGNEDNUMBER,p1,--p);
Type[count++]=UNSIGNEDNUMBER;
p++;
continue;
}
else
{
Output(INEFFICACIOUSLABEL,p1,--p);
printf("输入的这个符号是不合法的~"); break; Type[count++]=INEFFICACIOUSLABEL;
p++;
continue;
}
}
else if(*p=='.')
{
p++;
while(UnsignedNum(p))
p++;
if(*p=='\0')
{
Output(UNSIGNEDNUMBER,p1,--p);
Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
else if(*p=='E')
{
p++;
if(UnsignedNum(p))
{
while(UnsignedNum(p))
p++;
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
else if(*p=='+'||*p=='-')
{
p++;
if(UnsignedNum(p))
{
while(UnsignedNum(p))
p++;
Output(UNSIGNEDNUMBER,p1,--p);
Type[count++]=UNSIGNEDNUMBER;
p++;
continue;
}
else
{
Output(INEFFICACIOUSLABEL,p1,--p);
printf("输入的这个符号是不合法的~ /n");
break;
Type[count++]=INEFFICACIOUSLABEL;
p++;
continue;
}
}
else
{
Output(INEFFICACIOUSLABEL,p1,--p);
printf("输入的这个符号是不合法的~因为他的后面既不是0~9也不是“+”或者“-…");
break;//1.5E*2这样的字符串不是无符号数
Type[count++]=INEFFICACIOUSLABEL;
p++;
continue;
}
}
else
{
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
}
else
{
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
}
if(*p=='.')
{
p++;
if(UnsignedNum(p))
{
p++;
while(UnsignedNum(p))
p++;
if(*p=='\0')
{
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
else if(*p=='E')
{
p++;
if(UnsignedNum(p))
{
while(UnsignedNum(p))
p++;
Output(UNSIGNEDNUMBER,p1,--p); Type[count++]=UNSIGNEDNUMBER; p++;
continue;
}
else if(*p=='+'||*p=='-')
{
p++;
while(UnsignedNum(p))
p++;
Output(UNSIGNEDNUMBER,p1,--p);
Type[count++]=UNSIGNEDNUMBER;
p++;
continue;
}
}
else
{
Output(UNSIGNEDNUMBER,p1,--p);
Type[count++]=UNSIGNEDNUMBER;
p++;
continue;
}
}
else
{
Output(INEFFICACIOUSLABEL,p1,--p);
printf("输入的这个符号是不合法的~"); break; Type[count++]=INEFFICACIOUSLABEL;
p++;
continue;
}
}
}
else if(*p=='E')
{
Output(INEFFICACIOUSLABEL,p,p); break;
Type[count++]=INEFFICACIOUSLABEL;
printf("输入的这个符号是不合法的~");
p++;
continue;
}
}
printf("\n\n词法分析完毕~");
}
void ShowType()//将类别码存储在Type[100]中,为语法分析做准备{
printf("\n用类别码表示输入的字符如下:\n");
int i;
printf("\n");
for(i=0;Type[i]!=FINISH;i++)
{printf("%d",Type[i]);
}
printf("\n\n");
}
void main()
{
//词法分析部分
StoreStr();
ShowStore();
TypyDistinguish();
Type[count]=FINISH;
ShowType();
}
四、实验结果
正确的结果:
错误的结果:
输入的字符串中有1.5E*2
因为实验是以文件的形式进行读取的所以,在读取不合法的过程中只是将存在project 中的a.txt 中的内容改变改为1.5E*2+100*555
实验结果如下:
结果分析:
对于正确的结果,我以二元式的形式输出,包括他的值和他的类别码,其中将类别码存放在另外的一个数组中,为了在实验二中的语法识别打下基础。
对于错误的结果,我选择的是跳出这个程序,并且能过分析出错的原因。
改进设计:
(1)字符串是以文件的形式输出的,连续重复输入存在局限性
(2)能够跳过错误的字符继续识别剩下的字符
实验一扩展
李晓萌 088330
一、实验内容:
试对基础实验识别的单词种类进行扩充,构造识别以下单词的词法分析程序。
语言中具有的单词包括五个有代表性的关键字begin、end、if、then、else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符。
二、设计部分
基础实验和扩展实验的差别在基础实验的关键在于无符号数的判断,但是,扩展实验的关键在于关键字和标识符的识别。
关于关键字的识别,通过和题目中给出的几个关键字的对比,若相同则可以确定是关键字,否则,就可自动确定为标识符
具体实现的流程图如下:
入口
N
*p=Letter
Y
YN*p=Letter||digitcode="关键字"关键字
NY
标识符p++&&删掉空格
N
*p=digit关系运算的识别并输出类别码
Y
N*p=digit||"."类别码int
Y
p++&&删掉空格
三、源程序代码部分
#include<iostream.h> #include<string.h> #define BEGIN 1 #define END 2
#define IF 3
#define THEN 4
#define ELSE 5
# define ID 6
# define INT 7
# define LT 8
# define LE 9
# define EQ 10
# define NE 11
# define GT 12
# define GE 13
#define IS 14
#define PL 15
#define MI 16
#define MU 17
#define DI 18
char *KeyWord[5]={"begin","end","if","then","else"};
int i=0,j=0,k=0,t=0;//搜索指示器
char ch;//存放最新读入的原程序字符
char strToken[20];//存放构成单词符号的字符串
char * chr_form[100];//字符表
char * int_form[100];//常数表
char form[1000];
int q=0;
int temp;
void GetChar()//将下一个字符读入ch中,搜索指示器前移一字符位
{
ch=form[k];
k++;
}
void GetBC()//检查ch中的字符是否为空白,若是则调用Getchar直至ch中进入
//一个非空白字符
{
while(ch==' ')
{
//k--;
GetChar();
}
}
void Concat()//将ch中的字符连接到strToken之后, {
strToken[i]=ch;
i++;
}
bool IsLetter()//判断ch中的字符是否为字符
{
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))) return (1);
else
return(0);
}
bool IsDigit()//判断ch中的字符是否为数字
{
//k--;
if(((ch)<='9')&&( (ch)>='0'))
return (1);
else
return (0);
}
int Reserve()//对strToken中的字符串查找保留字表,若它是一个保留字//则返回它的编码,否则返回-1值
{
for(int q=0;q<5;q++)
{
if(strcmp(KeyWord[q],strToken)==0)
return q;
if(q==4)
return -1;
}
}
void Retract()//将搜索指示器回调一个字符位置,将ch置为空白字符{
k--;
ch=NULL;
}
char*InsertId()//将strToken中的标识符插入符号表,返回符号表的指针{
chr_form[j]=strToken;
j++;
return chr_form[0];
}
char * InsertConst()//将strToken中的常数插入常数表,返回常数表指针{
int_form[t]=strToken;
t++;
return int_form[0];
}
int code;
//////////////////////////////////////////////////////////////////// //
void Output(int a,char *p1,char *p2)
{
cout<<"\t类别码(CLASS):"<<a<<"\t 单词值(VALUE):";
while(p1<=p2)
{
cout<<*p1;
p1++;
}
cout<<endl;
}
void analyze()
{
GetChar();
GetBC();
//cout<<"此处没有错"<<endl;
if(IsLetter())
{
while(IsLetter()||IsDigit())
{
Concat();
GetChar();
}
//cout<<"此处没有错"<<endl;
Retract();
code=Reserve();
switch(code)
{
case 0:cout<<"需检测的的单词:"<<strToken<<" 类别码为: "<<BEGIN <<endl;break;
case 1:cout<<"需检测的的单词:"<<strToken<<" 类别码为:
"<<END<<endl;break;
case 2:cout<<"需检测的的单词:"<<strToken<<" 类别码为:
"<<IF<<endl;break;
case 3:cout<<"需检测的的单词:"<<strToken<<" 类别码为:
"<<THEN<<endl;break;
case 4:cout<<"需检测的的单词:"<<strToken<<" 类别码为:
"<<ELSE<<endl;break;
default:
cout<<"需检测的的单词:"<<strToken<<" 类别码为: "<<ID<<endl;break; }
}
else
{
if(IsDigit())
{
while(IsDigit()||ch=='.')
{
Concat();
GetChar();
}
Retract();
cout<<"需检测的的单词:"<<strToken<<" 类别码为: "<<INT<<endl;
}
else
{
switch (ch)
{ case '+': cout<<"需检测的的单词:+ 类别码为: "<<PL<<endl;break; case'-': cout<<"需检测的的单词:- 类别码为: "<<MI<<endl;break; case'*': cout<<"需检测的的单词:* 类别码为: "<<MU<<endl;break; case'/': cout<<"需检测的的单词:/ 类别码为: "<<DI<<endl;break; case':':GetChar();
if(ch=='=')
{ cout<<"需检测的的单词::= 类别码为: "<<IS<<endl;break;}
else
{
Retract();
cout<<"需检测的的单词为非法输入~"<<endl;break;
}
case'=':cout<<"需检测的的单词:= 类别码为: "<<EQ<<endl;break; case'>':GetChar();switch(ch)
{case'=':
cout<<"需检测的的单词:>= 类别码为: "<<GE<<endl;break;
default:Retract();
cout<<"需检测的的单词:> 类别码为: "<<GT<<endl;break;
}
case'<':GetChar();
switch(ch)
{case'=':cout<<"需检测的的单词:<= 类别码为: "<<LE<<endl;break; case'>':cout<<"需检测的的单词:<> 类别码为: "<<NE<<endl;break; default:Retract();
cout<<"需检测的的单词:< 类别码为: "<<LT<<endl;break;
}
}
}
}
while(k<q)
{
for(int p=0;p<50;p++)
strToken[p]='\0';
i=0;
analyze();
}
}
void main()
{
cout<<"请输入一段程序,以#号结束:"<<endl; form[0]=cin.get();
for( q=1;form[q-1]!='##';q++)
{
form[q]=cin.get();
if(form[q]=='#')
{
cout<<"你输入的程序段为\n";
cout.write(form,q);
break;
}
}
cout<<endl;
analyze();
}
四、实验结果:
结果分析:
实验的程序只是完成了最基本的部分,能够把题目中给出的关键字begin、end、if、then、
else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符顺利的识别出来,
还是存在缺陷
改进设计:
(1)关键字的数目太少
(2)只是识别了整数,应该能够将基本实验中的无符号数识别出来 (3)实现多次循环输入
(4)判断出错的功能是很强大
实验二语法分析程序实现
李晓萌 088330
一、实验内容:
通过设计、编制、调试典型的SLR(1)语法分析程序,实现对实验一所得词法分
析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
二、设计部分
(1)
首先根据算术四则运算的语法定义,构造SLR(1)分析表。
无符号数的算术四则运算的语法可表示为:
S->E(自己添加的)
E->E+T| E-T|T
T->T*F| T/F|F
F->(E)|i
该表1是根据下一页的图画出来的:
+ - * / ( ) i # E T F 0 S4 S5 1 2 3 1 S6 S7 acc 2 R3 S8 S9 R3 R3 3
R6 R6 R6 R6 R6 R6 4 S4 S5 10 2 3 5 R8 R8 R8 R8 R8 R8 6 S4 S5 11 3 7 S4 S5 12 3 8 S4 S5 13 9 S4 S5 14 10 S6 S7 S15 11 R1 R1 S8 S9 R1 R1 12 R2 R2 S8 S9 R2 R2 13 R4 R4 R4 R4 R4 R4 14 R5 R5 R5 R5 R5 R5 15 R7 R7 R7 R7 R7 R7
表1
(I11)*I8E->E+T./T->T.*F(I6)TI9T->T./F
E->E+.T+T->.T*FFT->.T/FI3T->.F(I4F->.(E))F->.iI5
(I1)(I12)(I7)E'->E.T-*E->E-T.I8EE->E.+TT->T.*FE->E-.T/E->E.-TI9T-
>T./FT->.T*F
T->.T/FFI3T->.F(I0)(F->.(E)I4(I2)T)F->.iE'->.EI5T->T.*FE->.E+TT-
>T./F*E->.E-TFE->T.(I13)E->.T/T->T*F.(I8)T->.T*F
T->.T/F(T->T*.FI4T->.FF(I3)F->(E)F->.(E)T->F.F->iiF->.iI5
(F
i
(I14)Fi(I5)(I4)T->T/F.(I9)F->i.F->(.E)(E->.E+TI4T->T/.FE->.E-TF-
>(E)E->.TF->iT->.T*FiI5T->.T/F
T->.F
F->.(E)(EF->.iF(I15)(I10)F->(E).
F->(E.)(I4E->E.+TiE->E.-TI5
(2)对实验一得字符串1.5E+2+100*555进行验证:经过自己的推理所得的表2
步骤状态栈符号栈输入串 ACTION GOTO 1 0 # i+i*i S5 2 05 #i +i*i#
R8 GOTO[0,F]=3 3 03 #F +i*i# R6 GOTO[0,T]=2 4 02 #T +i*i# R3 GOTO[0,E]=1
5 01 #E +i*i# S6
6 016 #E+ i*i# S5
7 0165 #E+i *i# R8 GOTO[0,F]=3
8 0163 #E+F *i# R6 GOTO[0,T]=2
9 0162 #E+T *i# S8
10 01628 #E+T* i# S5
11 016285 #E+T*i # R8 GOTO[0,F]=3
12 016283 #E+T*F # R6 GOTO[0,T]=2
13 01611 #E+T # R1 GOTO[0,E]=1
成功~~~ 14 01 #E # acc
表2
程序设计:
(1)设置输入缓冲区
用结构buf[]实现输入字符的存储,包括值和类型的存储(为实验三做准备),为后续的
语法分析和词法分析做准备
(2)状态栈
state []作为状态栈,存储归约和移进过程状态的变化
(3)符号栈
Symbol作为符号栈,栈顶的符号不断地进行着归约和移进的动作 (4)运用c语言编写了相应的程序进行移近和归约以及接受的动作,需要注意的是,在规约的过程中不仅需要弹出数目确定的字符,还要有相应的字符入栈注意:在实验设计过程中,从读取存有算数字符的文件开始,就获得了每一个算术表达式的字符个数(除去”->”的剩余部分)并存储在数组VNum[]中
三、源程序代码
实验代码部分将会在实验三给出
四、实验结果
见实验三
实验三语义分析程序实现
李晓萌 088330 一、实验内容:
通过设计、编制、调试一个简单的语义处理分析程序,实现对实验一和实验二所得单词和语句的语义信息简单处里,进一步掌握语义处理的内容和简单方法。
二、设计部分
(1)需要将实验一的1.5E+2+100*555中的每一个无符号数相应的算出最终的结果:
如:1500.000000+2.000000+100.000000*555.000000
(2)在进行归约的过程中,不仅仅是弹出需要进行归约的字符,还要进行值的传递和计算
计算
(3)设计思路:[1] Calculate_UnsignedFigure(char *p1,char *p2) 函数能过准确的计算出无符
号的值
[2] Quarternary_Out(int a1,double a2,double a3,double a4)语义分析四元式输
出
[3] Store_Resuction[MAX]在语法分析的过程中,把归约过程都标记在这个
数组中&& UnsignedFigure[]在计算的过程中也已经把相应的算数字符
的值存储在这个数组
[4]调用相应的归约过程,利用UnsignedFigure[]存储的值进行计算,最后获
得运算结果结果
可以对实验二得标进一步完善
语义步骤状态栈符号栈输入串生成ACTION GOTO
处理中间
代码
1 0 # i+i*i S5
2 05 #i +i*i# R8 GOTO[0,F]=
3 i1.value
=
1500.000000
3 03 #F +i*i# R6 GOTO[0,T]=2 F1.value
=
1500.000000
4 02 #T +i*i# R3 GOTO[0,E]=1 T1.value
=
1500.000000
5 01 #E +i*i# S
6 E1.value
=
1500.000000
6 016 #E+ i*i# S5
7 0165 #E+i *i# R
8 GOTO[0,F]=3 i2.value
=
100.000000 8 0163 #E+F *i# R6 GOTO[0,T]=2 F2.value
=
100.000000 9 0162 #E+T *i# S8 T2.value
=
100.000000 10 01628 #E+T* i# S5 11 016285 #E+T*i # R8 GOTO[0,F]=3 I3.value
=
555.000000
( 12 016283 #E+T*F # R6 GOTO[0,T]=2 F3.value
*, =
T2, 100.000000
F3,
Q1
)
( 13 01611 #E+T # R1 GOTO[0,E]=1 Q1.value
+,=
Q1,55500.000000
E1,
Q2
)
成功~~~ 14 01 #E # acc Q2.value
=
55650.000000 由此表可以看出,最终的结果因该是55650.000000 三、源程序代码
#include <stdio.h>
#include<stdlib.h>
#include <math.h>
#define MAX 100
#define UNSIGNEDNUMBER 1
#define PLUS 2
#define SUBTRACT 3
#define MULTIPLY 4
#define DIVIDE 5
#define LEFTBRACKET 6
#define RIGHTBRACKET 7
#define INEFFICACIOUSLABEL 8 #define FINISH 111
//词法分析定义的部分
int count=0;//记录类型的13145
int count1=0;//词法分析结果缓冲表
int Class;
int Type[100];
char Store[20]={'\0'}; double result=0.0;
//词法分析的缓冲区
struct aa
{
int type;
double value;
}buf[1000];
struct aa oth;
/*_____________语法分析定义的部分______________*/
char Input[20];//存放类别码转化的字符
char Store_Grammar[20][10]={'\0'};//用来存放语法分析产生式 char
V_T[10],V_N[10]; char AVT[8]={'+','-','*','/','(',')','i','#'};
char GVN[3]={'E','T','F'}; int vnNum,vtNum,stateNum=16; int VNum[10];
int grammarNum;
typedef struct{
char *base;
char *top;
}SymbolStack;
typedef struct{
int *base;
int *top;
}StateStack;
StateStack state;
SymbolStack symbol;
/*_______________词法分析子函数部分___________*/ bool Tag=false;
void StoreType();
void ShowStrFile();
void Output(int a,char *p1,char *p2);
int Sign(char *p);
int UnsignedNum(char *p); int LegalCharacter(char *p); void DistinguishSign(char *p);
void TypyDistinguish(); void ShowType();
//语法分析子函数
void ChangStyle();
/*______语义分析的相关函数_____*/ double
CalculateStack[MAX],*p_trcal;//定义计算数值用的计算栈和指向它的首地址的指针
double UnsignedFigure[MAX];//存放每个无符号数的值 int Num2=0;
int Num3=0;
int Num4=0;
int Num5=0;
bool Mark=true;
int Store_Resuction[MAX];//语义分析时的归约动作所用产生式代号栈
//语法分析SLR[1]表
int ACTION[16][8]=
{
0,0,0,0,104,0,105,0, 106,107,0,0,0,0,-1,-1, 53,53,108,109,0,53,0,53, 56,56,56,56,0,56,0,56, 0,0,0,0,104,0,105,0, 58,58,58,58,0,58,58,58,
0,0,0,0,104,0,105,0, 0,0,0,0,104,0,105,0, 0,0,0,0,104,0,105,0,
0,0,0,0,104,0,105,0, 106,107,0,0,0,115,0,0, 51,51,108,109,0,51,51,51, 52,52,108,109,0,52,0,52, 54,54,54,54,0,54,54,54, 55,55,55,55,0,55,0,55, 57,57,57,57,0,57,0,57 };
int GOtO[16][3]=
{
1,2,3,
0,0,0,
0,0,0,
0,0,0,
10,2,3,
0,0,0,
0,11,3,
0,12,3,
0,0,13,
0,0,14,
0,0,0,
0,0,0,
0,0,0,
0,0,0,
0,0,0,
0,0,0,
};
void ShowStrFile() {
FILE *fp_s;
char ch;
if((fp_s=fopen("a.txt","r"))==NULL) {printf("The FILE cannot open!"); exit(0);
}
else
ch=fgetc(fp_s);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp_s);
}
printf("\n"); }
void StoreStr() {
FILE *fp=fopen("a.txt","r");
char str;
int i=0;
while(!feof(fp))
{
fscanf(fp,"%c",&str);
if(str=='?')
{
Store[i]='\0';
break;
}
Store[i]=str;
i++;
}
Store[i]='\0';
}
void ShowStore()
{int i;
for (i=0;Store[i]!='\0';i++)
printf("%c",Store[i]);
printf("\n");
}
void Output(int a,char *p1,char *p2)
{
printf("%3s\t%d\t%s\t","CLASS",a,"VALUE"); while(p1<=p2)
{
printf("%c",*p1);
p1++;
}
// printf("\n");
}
double Calculate_DecimalPart(char *p1,char *p2)
{
char *p_1=p1,*p_2=p2;
int i,j,m;
double sum=0.0;
m=p_2-p_1;
i=0;
while(p_1<=p_2&&i<=m)
{
double k=1;
double temp=double(*p_1-48);
for(j=0;j<=i;j++)
k*=0.1;
temp*=k;
sum+=temp;
p_1++;
i++;
}
return sum;
}
int Calculate_IntegerPart(char *p1,char *p2)//计算整数部分 { char *p_1=p1,*p_2=p2;
int i,j,sum=0;
i=p_2-p_1;
while(p_1<=p_2)
{
int k=1;
int temp=int(*p_1-48);
for(j=0;j<i;j++)
k*=10;
temp*=k;
sum+=temp;
p_1++;
i--;
}
return sum;
}
double Calculate_ScientificFigure(double a,char b,int c)//计算科学计数
{
double ScientificFigure;
int i;
if(b=='+')//E+
{
int k=1;
for(i=0;i<c;i++)
k*=10;
a*=k;
ScientificFigure=a;
}
else if(b=='-')//E-
{
double k=1.0;
for(i=0;i<c;i++)
k*=0.1;
a*=k;
ScientificFigure=a;
}
return ScientificFigure; }
//计算无符号数的值
double Calculate_UnsignedFigure(char *p1,char *p2)
{
double Result;
char *p_1=p1,*p_2=p2;
int Label1=0,Label2=0,Label3=0,Label4=0;//label1:标记. label2标记E label3标记+-号 label4标记本函数的switch分支
while(p_1<=p_2)
{
if(*p_1=='.')
Label1=1;
if(*p_1=='E')
Label2=1;
if(*p_1=='+'||*p_1=='-')
Label3=1;
p_1++;
}
p_1=p1,p_2=p2;//再次初始化
if(Label1==1&&Label2==1&&Label3==1) Label4=1;//情况1:.123E+4或者123.4E+5 else if(Label1==1&&Label2==1&&Label3==0) Label4=2;//情况2: .123E4或者123.E4
else if(Label1==0&&Label2==1&&Label3==1) Label4=3;//情况3:123E+4
else if(Label1==1&&Label2==0&&Label3==0) Label4=4;//情况4:.123或者123.4
else if(Label1==0&&Label2==1&&Label3==0) Label4=5;//情况5:123E4
else if(Label1==0&&Label2==0&&Label3==0) Label4=6;//情况6:123
switch(Label4)
{
case 1:
goto Circs1;//情况1
break;
case 2:
goto Circs2;
break;
case 3:
goto Circs3;
break;
case 4:
goto Circs4;
break;
case 5:
goto Circs5;
break;
case 6:
goto Circs6;
break;
default:
break;
}
Circs1:
{
if(*p_1=='.')//情况1:.123E+4 {
char *p_3=++p_1;//标记
while(*p_1!='E')
p_1++;
--p_1;
double k1=Calculate_DecimalPart(p_3,p_1);//E前数p_1+=3;
int k2=Calculate_IntegerPart(p_1,p_2);//E后数
p_1--;
if(*p_1=='+')
{
Result=Calculate_ScientificFigure(k1,'+',k2); }
else if(*p_1=='-')
{
Result=Calculate_ScientificFigure(k1,'-',k2); }
}
else//情况1:123.4E+5
{
char *p_3=p_1;//标记
while(*p_1!='.')
p_1++;
--p_1;
int k1=Calculate_IntegerPart(p_3,p_1);
p_1+=2;
p_3=p_1;
while(*p_1!='E')
p_1++;
--p_1;
double k2=Calculate_DecimalPart(p_3,p_1); double k3=double(k1)+k2;//E前数
p_1+=3;
int k4=Calculate_IntegerPart(p_1,p_2);//E后数p_1--;
if(*p_1=='+')
{
Result=Calculate_ScientificFigure(k3,'+',k4); }
else if(*p_1=='-')
{
Result=Calculate_ScientificFigure(k3,'-',k4); }
}
}
return Result;
Circs2:
{
if(*p_1=='.')//情况2:.123E4
{
char *p_3=++p_1;//标记
while(*p_1!='E')
p_1++;
--p_1;
double k1=Calculate_DecimalPart(p_3,p_1);//E前数p_1+=2;
int k2=Calculate_IntegerPart(p_1,p_2);//E后数Result=Calculate_ScientificFigure(k1,'+',k2); }
else//情况2:123.E4
{
char *p_3=p_1;//标记
while(*p_1!='.')
p_1++;
--p_1;
int k1=Calculate_IntegerPart(p_3,p_1);
p_1+=2;
p_3=p_1;
while(*p_1!='E')
p_1++;
--p_1;
double k2=Calculate_DecimalPart(p_3,p_1); double k3=double(k1)+k2;//E前数
p_1+=2;
int k4=Calculate_IntegerPart(p_1,p_2);//E后数Result=Calculate_ScientificFigure(k3,'+',k4);
}
}
return Result;
Circs3://情况3:123E+4
{
char *p_3=p_1;//标记
while(*p_1!='E')
p_1++;
--p_1;
int k1=Calculate_IntegerPart(p_3,p_1);//E前数p_1+=3;
int k2=Calculate_IntegerPart(p_1,p_2);//E后数p_1--;
double k3=double(k1);
if(*p_1=='+')
{
Result=Calculate_ScientificFigure(k3,'+',k2); }
else if(*p_1=='-')
{
Result=Calculate_ScientificFigure(k3,'-',k2); }
}
return Result;
Circs4:
{
if(*p_1=='.')//情况4:.123
{
++p_1;
Result=Calculate_DecimalPart(p_1,p_2);
}
else//情况4:123.4
{
char *p_3=p_1;//标记
while(*p_1!='.')
p_1++;
--p_1;
int k1=Calculate_IntegerPart(p_3,p_1);
p_1+=2;
double k2=Calculate_DecimalPart(p_1,p_2); Result=double(k1)+k2;
}
}
return Result;
Circs5://情况5:123E4
{
char *p_3=p_1;//标记
while(*p_1!='E')
p_1++;
--p_1;
int k1=Calculate_IntegerPart(p_3,p_1);
p_1+=2;
int k2=Calculate_IntegerPart(p_1,p_2);
double k3=double(k1);
Result=Calculate_ScientificFigure(k1,'+',k2);
}
return Result;
Circs6://情况6:123
{
Result=Calculate_IntegerPart(p_1,p_2);
}
return Result;
}
int Sign(char *p)
{
char ch=*p;
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;
else
return 0;
}
int UnsignedNum(char *p) {
char ch=*p;
if('0'<=ch&&ch<='9')
return 1;
else
return 0;
}
int LegalCharacter(char *p) {
char ch=*p;
if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')
return 1;
else return 0;
}
void DistinguishSign(char *p) {
char ch=*p;
switch(ch)
{
case '+':
Output(PLUS,p,p);buf[count1++].type =PLUS;printf("\t\t值为
NULL\n");break;
case '-':
Output(SUBTRACT,p,p);buf[count1++].type =SUBTRACT;printf("\t\t值为NULL\n");break;
case '*':。