📄 test.cpp
字号:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stack>
#include <queue>
#include <ctype.h>
#include "RecurAnalyser.h"
using namespace std;
#define true 1
#define false 0
//全局常量
int KEYINDEX[16]={4,14,10,8,5,11,6,3,1,15,12,7,13,2,9,16}; //关键字编码表
char* KEYWORD[16]={"begin","call","do","else","end","for","if","procedure","program","read","step"
,"then","until","var","while","write"}; //关键字表
char* signCache[5]; //保留规约时从符号栈弹出的字符,以便语义分析时使用。
//全局变量
char buffer[50]; //预输入缓冲区
char readchar; //分析时存放读入的新字符
char strToken[21]; //分析时存放构成的单词符号串
//用户自定义标识符最多20个字符,否则只取前20个
int linenum; //行数
int searchpoint; //搜索指示器
FILE* sfp; //源文件指针
FILE* dfp; //目的文件指针
DuaDualist Dualist; //二元式链表
Quatype Qualist[100]; //四元式表,不得超过200条四元式
stack<Operand> place; //变量栈
stack<int> chain; //回填链栈
stack<int> quad; //比较运算符栈
stack<int> spro; //调用子过程时,将该子过程在过程表中的序号保存
queue<Operand> part; //参数队列
int K; //临时变量序号
int PC; //四元式表指针
Duatype WORD; //读入单词符号
vtable VariableTable; //变量表
ptable ProcTable; //过程名表
my_stack ProcStack; //过程栈,用于查过程名表
int level; //当前分析所在过程深度
int counter; //变量相对个数
int errflag_prog;
char errtext[19][20]; //错误信息存储区
stack<int> clusterSta; //状态栈
stack<char*> signSta; //符号栈
bool isTrue; //如果语法分析出现错误,则置为false,不再产生四元式。
//PL数组:下标表示产生式编号(为与讲义协调,数组第一个元素不使用),内容表示此产生式右部长度。
int PL[43]={1,2,1,2,3,3,2,2,2,3,5,2,4,4,3,3,3,1,3,3,4,3,1,1,3,1,1,1,3,3,3,3,2,
3,1,1,3,1,1,1,1,1,1};
//AL数组:第一列表示产生式编号(为与讲义协调,数组第一个元素不使用),第二列存放此产生式左部符号名称。
char AL[43][5]={{'P','L','\0'},{'L','\0'},{'L','\0'},{'L','S','\0'},{'S','\0'},{'S','\0'},
{'S','\0'},{'S','\0'},{'S','\0'},{'S','\0'},{'S','\0'},{'S','\0'},
{'S','\0'},{'S','\0'},{'C','\0'},{'T','p','\0'},{'W','d','\0'},
{'W','\0'},{'F','3','\0'},{'F','2','\0'},{'F','1','\0'},
{'P','A','R','T','\0'},{'P','A','R','T','\0'},{'T','T','\0'},
{'I','\0'},{'I','\0'},{'I','D','\0'},{'E','X','P','\0'},{'E','\0'},
{'E','\0'},{'E','\0'},{'E','\0'},{'E','\0'},{'E','\0'},{'E','\0'},
{'E','\0'},{'L','E','\0'},{'R','O','P','\0'},{'R','O','P','\0'},
{'R','O','P','\0'},{'R','O','P','\0'},{'R','O','P','\0'},{'R','O','P','\0'}};
//以下四个数组用于存放LR分析表
///////////////////////////////////////////////////////////////////////////////////////////////
//SL数组与SA数组配合,存放了ACTION表中内容:
//SL数组:下标表示状态号,内容为对应下标所表示的状态在SA数组中从第几行开始。
int SL[85]={0,9,12,21,22,23,24,33,35,44,53,62,64,66,68,70,75,80,81,83,85,87,90,91,96,97,99,100,
101,102,111,112,114,119,120,121,124,125,130,131,133,136,137,138,139,141,142,144,147,
148,150,151,158,163,164,166,167,172,173,178,179,181,186,187,188,189,190,191,192,193,
198,203,208,209,210,215,220,225,230,233,236,237,238,239,245};
//SA数组:第一列存放单词编码,第二列存放动作。
int SA[246][2]={{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},{5,999},{33,4},
{0,0},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
{-1,-2},{-1,-3},{-1,-1},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
{23,23},{0,0},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
{10,29},{0,0},{17,31},{0,0},{30,39},{0,0},{30,46},{0,0},
{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
{-1,-17},{13,56},{0,0},{12,58},{0,0},{17,60},{0,0},{5,22},{33,4},{0,0},
{-1,-4},{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-5},{8,26},{-1,-6},{-1,-15},{-1,-7},
{-1,-8},{4,6},{6,15},{9,17},{11,20},{14,12},{15,13},{16,14},{17,7},{0,0},
{-1,-9},{30,32},{-1,-11},{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-22},
{-1,-23},{31,36},{32,37},{0,0},{-1,-10},{17,72},{18,73},{20,70},{30,71},{0,0},
{-1,-21},{17,42},{0,0},{31,43},{32,44},{0,0},{-1,-25},{-1,-26},{-1,-12},{17,42},
{0,0},{-1,-24},{17,42},{0,0},{31,48},{32,44},{0,0},{-1,-13},{7,50},{0,0},
{-1,-14},{24,63},{25,64},{26,65},{27,66},{28,67},{29,68},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
{-1,-36},{10,55},{0,0},{-1,-16},{17,72},{18,73},{20,70},{30,71},{0,0},
{-1,-18},{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-19},{23,61},{0,0},
{17,72},{18,73},{20,70},{30,71},{0,0},{-1,-20},{-1,-37},{-1,-38},{-1,-39},
{-1,-40},{-1,-41},{-1,-42},{19,74},{20,75},{21,76},{22,77},{-1,-27},
{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
{-1,-34},{-1,-35},{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
{17,72},{18,73},{20,70},{30,71},{0,0},{17,72},{18,73},{20,70},{30,71},{0,0},
{21,76},{22,77},{-1,-28},{21,76},{22,77},{-1,-29},{-1,-30},{-1,-31},{-1,-32},
{19,74},{20,75},{21,76},{22,77},{31,84},{0,0},{-1,-33}};
///////////////////////////////////////////////////////////////////////////////////////////////
//NL数组与GL数组配合,存放GOTO表中内容:
//NL数组:下标表示产生式编号(为与讲义协调,数组第一个元素不使用),内容表示此产生式左部非终结符
// 在GOTO表中从GL数组的第几行开始。
int NL[43]={-1,0,0,2,3,3,3,3,3,3,3,3,3,3,9,10,11,12,13,14,15,16,16,17,19,19,21,23,31,31,31,
31,31,31,31,31,38,40,40,40,40,40,40};
//GL数组:第一列存放原状态,第二列存放下一状态。
int GL[41][2]={{0,1},{-1,21},{-1,2},{2,5},{8,25},{9,27},{10,28},{29,30},{-1,3},{-1,8},{-1,9},
{-1,10},{-1,16},{-1,11},{-1,18},{-1,19},{-1,35},{32,33},{-1,38},{39,40},{-1,47},
{44,45},{-1,41},{23,24},{32,34},{37,34},{52,53},{56,57},{58,59},{61,62},{-1,51},
{70,82},{71,83},{74,78},{75,79},{76,80},{77,81},{-1,69},{15,49},{-1,54},{-1,52}};
//////////////////////////////////////////////////////////////////////////////////////////////
//此函数初始化各公共变量
void initilize(){
linenum=1;
searchpoint=0;
readchar='\0';
Dualist.head=(Duatype*)malloc(sizeof(Duatype)); //带头结点
Dualist.head->index=0;
Dualist.head->value=NULL;
Dualist.head->next=NULL;
Dualist.tail=Dualist.head;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//此函数从二元式链表中读出一个单词符号,放入WORD中
void getWord(){
Duatype* temp;
if(Dualist.head->next==NULL){ //二元式链表读完,WORD.index=0作为标志
WORD.index=0;
Dualist.tail=Dualist.head;
}
else{
temp=Dualist.head->next;
Dualist.head->next=temp->next; //从链表中删除已读二元式
while(temp->index==35){
linenum++;
free(temp);
temp=Dualist.head->next;
if(temp==NULL)
break;
Dualist.head->next=temp->next;
}
if(temp==NULL){ //二元式链表读完,WORD.index=0作为标志
WORD.index=0;
Dualist.tail=Dualist.head;
}
else{
WORD.value=(char*)malloc((strlen(temp->value)+1)*sizeof(char));
strcpy(WORD.value,temp->value); //读入单词所在二元式
WORD.index=temp->index;
free(temp); //释放已读二元式空间
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断源程序文件是否存在
//存在函数返回true,不存在函数返回false
int isFile(){
char fname[20]; //源程序文件名
printf("Please input the name of the source file:");
scanf("%s",fname);
sfp=fopen(fname,"r");
if(sfp==NULL){
printf("This file does not exit!Please input the name of the source file again!");
return false;
}
else{
printf("Success!\n");
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断readchar读入字符是否为字母
//若是字母,则返回true;否则返回false
int isLetter(char readchar){
if(readchar>='a' && readchar<='z')
return true;
else
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////
//此函数判断readchar读入字符是否为数字
//若是数字,则返回true;否则返回false
int isDigit(char readchar){
if(readchar>='0' && readchar<='9')
return true;
else
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////
//此函数清空指定字符缓冲区中已有字符
//参数为缓冲区首地址和缓冲区长度
void Clear(char* strBuffer,int lengthBuffer){
int i;
for(i=0;i<lengthBuffer;i++) //清空strBuffer,以备下次使用
strBuffer[i]='\0';
}
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数从源程序文件中预输入到缓冲区buffer(buffer1和buffer2配合使用)
//参数为缓冲区首地址,若源文件读完返回true;未读完而缓冲区满返回false
int BeforehandInput(char* buffer){
int i=0;
readchar=fgetc(sfp);
while(readchar!=EOF && i<50){
if(readchar>='A' && readchar<='Z'){
readchar=readchar+32; //大写字母转化成小写,便于后续处理,源程序中不区分大小写
buffer[i]=readchar;
i++;
readchar=getc(sfp);
}
else if(readchar==' ' || readchar=='\t'){ //连续空格只保留一个
if(buffer[i-1]==' ' || buffer[i-1]=='\n')
readchar=getc(sfp);
else{
buffer[i]=' '; //制表符转化程空格,便于后续处理
i++;
readchar=getc(sfp);
}
}
else{
buffer[i]=readchar;
i++;
readchar=getc(sfp);
}
}
if(i>=50){
fseek(sfp,-1,SEEK_CUR);
if(readchar==EOF) return true;
else return false;
}
else{
buffer[i]='\0'; //把EOF转化为'/0'放入缓冲区,作为源文件输入结束的标志
fclose(sfp);
return true;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//此函数相当于哈希函数,辅助查询关键字表
//参数为需识别标识符strtoken首字符,返回值为以此字母开头的关键字在关键字表中的起始位置(下标值)
int LocinKEYWORD(char fc){
switch(fc){
case 'b':
return 0;
break;
case 'c':
return 1;
break;
case 'd':
return 2;
break;
case 'e':
return 3;
break;
case 'f':
return 5;
break;
case 'g':
case 'h':
case 'i':
return 6;
break;
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
return 7;
break;
case 'q':
case 'r':
return 9;
break;
case 's':
return 10;
break;
case 't':
return 11;
break;
case 'u':
return 12;
break;
case 'v':
return 13;
break;
case 'w':
return 14;
break;
default:
return 16;
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数把从缓冲区读入的字符readchar和strToken中字串相拼接
void Concat(){
char temp[2]={readchar,'\0'};
strcat(strToken,temp);
}
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数对strToken中字串查找关键字表
//返回值为关键字编码;若不是关键字,返回17
int SearchKey(){
int start,end,i;
start=LocinKEYWORD(strToken[0]);
end=LocinKEYWORD(strToken[0]+1);
if(start==16)
return 17; //非关键字;
else
for(i=start;i<end;i++){ //根据首字符索引查找关键字,提高效率,返回相应编码
if((strcmp(strToken,KEYWORD[i]))==0)
return KEYINDEX[i];
}
return 17; //关键表中查不到
}
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数对分析出的单词符号生成二元式结点并插入二元式链表
void Insert(){
Duatype* temp;
temp=(Duatype*)malloc(sizeof(Duatype));
temp->value=(char*)malloc((strlen(strToken)+1)*sizeof(char));
strcpy(temp->value,strToken);
temp->next=NULL;
Dualist.tail->next=temp;
Dualist.tail=temp;
}
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数清查上一个缓冲区中剩余的字符串或数字串
void CheckLeft(){
if(isalpha(strToken[0])){
Insert();
Dualist.tail->index=SearchKey();
Clear(strToken,21);
}
else if(isdigit(strToken[0])){
Insert();
Clear(strToken,21);
Dualist.tail->index=18;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//此函数为词法分析过程
//参数为缓冲区首地址,生成二元式链表
void WordAnalyse(char* buffer){
searchpoint=0;
while(searchpoint<50){
readchar=buffer[searchpoint];
searchpoint++;
if(isLetter(readchar)){
do{
if(strlen(strToken)<20) //用户标识符最多20个字符,多余的略过不读
Concat();
if(searchpoint>=50)
break;
readchar=buffer[searchpoint];
searchpoint++;
}while(isLetter(readchar) || isDigit(readchar));
if(isLetter(readchar) || isDigit(readchar))
break;
searchpoint--;
Insert();
Dualist.tail->index=SearchKey();
Clear(strToken,21);
continue;
}
else if(isDigit(readchar)){
do{
if(strlen(strToken)<20) //用户标识符最多20个字符,多余的略过不读
Concat();
if(searchpoint>=50)
break;
readchar=buffer[searchpoint];
searchpoint++;
}while(isDigit(readchar));
if(isDigit(readchar))
break;
searchpoint--;
Insert();
Clear(strToken,21);
Dualist.tail->index=18;
continue;
}
else if(readchar==' '){
if(searchpoint>=50)
break;
else if(isLetter(strToken[0])){
Insert();
Dualist.tail->index=SearchKey();
Clear(strToken,21);
}
else if(isDigit(strToken[0])){
Insert();
Dualist.tail->index=18;
Clear(strToken,21);
}
else
continue; //空格跳过
}
else if(readchar=='+'){
CheckLeft();
Concat();
Insert();
Clear(strToken,21);
Dualist.tail->index=19;
if(searchpoint>=50)
break;
}
else if(readchar=='-'){
CheckLeft();
Concat();
Insert();
Clear(strToken,21);
Dualist.tail->index=20;
if(searchpoint>=50)
break;
}
else if(readchar=='*'){
CheckLeft();
Concat();
Insert();
Clear(strToken,21);
Dualist.tail->index=21;
if(searchpoint>=50)
break;
}
else if(readchar=='/'){
CheckLeft();
Concat();
Insert();
Clear(strToken,21);
Dualist.tail->index=22;
if(searchpoint>=50)
break;
}
else if(readchar==':'){
CheckLeft();
Concat();
if(searchpoint>=50)
break;
readchar=buffer[searchpoint];
searchpoint++;
if(readchar=='='){
Concat();
Insert();
Clear(strToken,21);
Dualist.tail->index=23;
if(searchpoint>=50)
break;
}
else{
searchpoint--;
}
}
else if(readchar=='='){
CheckLeft();
Concat();
Insert();
if(strlen(strToken)==2){ //":="
if(strToken[0]==':')
Dualist.tail->index=23;
else if(strToken[0]=='<') //"<="
Dualist.tail->index=29;
else if(strToken[0]=='>') //">="
Dualist.tail->index=27;
}
else
Dualist.tail->index=24; //"="
Clear(strToken,21);
if(searchpoint>=50)
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -