📄 布尔表达式的翻译.cpp
字号:
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#include <stdlib.h>
//全局变量定义
//-------------------------------------------定义词法分析全局变量---------------------------
#define BMaxlen 10000
#define KEY_No 12
#define WMaxlen 11
#define Sign_No 12
#define Limit_No 6
#define Maxtype '5' //定义单词的总类型共有5种 1关键字 2标志符 3shuzi 4运算符 5界符
#define Longtype '8' //定义单词不合法且过长时的类型
#define Errtype '7' //定义单词不合法但没超过长度的类型
//------------------------------------------词法分析函数声明及定义------------------------------
int getch();//用来从缓冲区中取一个字符
char getw();//从缓冲区中取一个单词
char Str[BMaxlen];//建立缓冲区
int pStr=-1; //用来表示从缓冲区取字母时的指针,定义为-1,为使以下的程序++pStr可以先指到缓冲区的第一个字母
char ch; //用来表示从缓冲区中取出的一个字母
char *KEY[KEY_No]={{"if"},{"int"},{"for"},{"while"},{"do"},{"return"},{"break"},{"continue"},{"else"},{"and"},{"or"},{"not"}};
char *Sign[Sign_No]={{"+"},{"-"},{"*"},{"/"},{"%"},{"="},{"<"},{">="},{"<="},{"!="},{"=="},{">"}};
char *Limit[Limit_No]={{","},{";"},{"{"},{"}"},{"("},{")"}};
int Fbuffer;//标志缓冲区中是否还有字母,如果没有的话,则Fbuffer的值为-1;如果还有的话,则其值为1
char Word[WMaxlen];//用来标识标识取出的单词
char CType;//用来标识得到的单词的类型
char Lasttype;//用来标识是其前面的单词的类型
char ty;//定义在调用取单词后取出的单词的类型
int getch()//用来从缓冲区中取一个字符,如果成功,则返回1,否则为-1
{
ch=Str[++pStr];
if (ch=='\0') return(-1);//当取出的字符是'\0',则表明缓冲区中已无字符,返回值为-1
else return(1);
}
char getw()//从缓冲区中取一个单词
{
bool flag=false;//用来表示取出的单词是否为关键词,如果是则flag的值为true,否则为false
int k=-1; //表示取出的字符放在单词数组的指针
CType='0'; //预先定义的取出的单词的类型
Lasttype='0'; //初始化先前的类型,此变量为判断正负数用
while (ch<=32 && ch>0)//去掉不能显示的字符
Fbuffer=getch();
if (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z')//取出标识符或者是关键词
{
k=-1;
while(true)//取出的单词长度不超过WMaxlen,如果超过,则其后的字符无效
{
if((++k)<WMaxlen)//(++k)为了使取出的单词最长为WMaxlen
{
Word[k]=ch;
}
Fbuffer=getch();
//如果取出的当前的字符不是字母或是数字,则此次取单词结束
if (!(ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z'||ch>='0' && ch<='9'))
break;
}
Word[++k]='\0';//以'\0'标识取出单词的结束,以方便后面的判断此单词是标识符还是关键词
for (int i=0;i<KEY_No;i++)//用来判断取出的当前单词是不是关键词
if (strcmp(Word,KEY[i])==0)
{
flag=true;
break;
}
if (flag) CType='1';//如果是关键词,则把此单词的类型定义为1型
else CType='2'; //否则是标识符,其类型为2
}
else if (ch>='0' && ch<='9')//判断是不是为整数
{
Word[++k]=ch;
Fbuffer=getch();
while(true)//如果是数字,则一直接受,且定义它的类型为3
if(ch>='0' && ch<='9')
{
Word[++k]=ch;
Fbuffer=getch();
}
else {CType='3';break;}//不是数字则跳出循环
//如果以字母开头,且长度不超过WMaxlen,且下面跟有字母,则此整数非法,输出类型为8,在主程序中输出出错信息
if (k<WMaxlen)
if (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z')
{
Word[++k]=ch;
Fbuffer=getch();
//取这个非法整数的单词,其中可包含英文字母和数字
while (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z'|| ch>='0' && ch<='9'||Fbuffer==-1)
if (k<WMaxlen)
{
Word[++k]=ch;
Fbuffer=getch();
}
else
{
Fbuffer=getch();
k++;
}
if (k>WMaxlen)//如果长度大于取出单词定义的最大长度,则返回类型为8,在主程序中打出出错信息
CType=Longtype;
else CType=Errtype;//否则返回类型7,在主程序出错,并明确写出此单词的具体内容
}
Word[++k]='\0';
}
else if (ch=='+'||ch=='-'||ch=='*'||ch=='/')//取出是运算符号的单词
{
Word[++k]=ch;
if (ch=='+' || ch=='-')//如果是+号或者是-号,则还要判断是不是正负数
if (Lasttype=='6')//判断其取出的当前字母的前一个单词是6号类型的,即是<、>、<=、>=、==、=时则可判断现在取出的是整数
{
Fbuffer=getch();
while(ch>='0' && ch<='9')//取出整数
{
Word[++k]=ch;
Fbuffer=getch();
}
CType='3';//如果正负整数,则直接返回类型为3,则表示此单词为整数
return(CType);
}
else Fbuffer=getch();//如果不是整数,则定义当前取出的单词是运算符,定义此类型为4
Word[++k]='\0';
CType='y';
}
else if (ch=='>'||ch=='<'||ch=='='||ch=='!')//取出运算符的另几类,即<、<=、>、>=、==、=、!=
{
Word[++k]=ch;Fbuffer=getch();
if( ch=='=')//判断是不是<=、>=、==、!=
{
Word[++k]=ch;
Fbuffer=getch();
}
Word[++k]='\0';
for (int i=0;i<Sign_No;i++)//判断取出的单词是不是运算符
if (strcmp(Sign[i],Word)==0)
{
flag=true;
break;
}
if (flag) CType='4';
Lasttype='6';
}
else if (ch==','||ch==';'||ch=='{'||ch=='}'||ch=='('||ch==')')//判断当前取出的单词是不是界符,如果是界符,则定义其类型为5
{
CType='5';
Word[++k]=ch;
Word[++k]='\0';
Fbuffer=getch();
}
return(CType);
}
//---------------------------------词法分析变量及函数定义结束-----------------------
//---------------------------------声明输出四元式用到的全局变量---------------------------
struct token{
char value[10];//dan ci
int pose;//wei zhi
char type;//lei xin
};
struct token token_list[20];
struct token pp(char * word,int pos1,char ty)
{
struct token itoken;
itoken.pose=pos1;
itoken.type =ty;
strcpy(itoken.value,word);
return itoken;
}
//--------------------------------------------------------------------------------------
//----------------------------------定义语法分析全局变量-------------------------------------------
#define MAX 100
char analyzed_sentence[MAX]="";
char s[MAX]="";
char stack[MAX]="";
char top;
char *temp;
char identified[MAX]="";
int n=0;
char par_list[10];
//定义LL(1)分析表
char Vn_array[] = "EATBFGSMQ";
char Vt_array[] = "+*!IDO()#";
char *LL1_array[][9] = {
{" ", " ", "TA", "TA", "TA", " ","TA"," "," "},
{"+TA", " ", " ", " ", " ", " ", " ", "u", "u"},
{" ", " ", "FB", "FB", "FB", " ","FB"," ", " "},
{"u", "*FB", " ", " ", " ", " ", " ", "u", "u"},
{" ", " ", "!G", "G", "G", " ","G"," ", " "} ,
{" ", " ", " ", "S", "S", " ", "(E)", " ", " "},
{" ", " ", " ", "MQ", "MQ", " ", " ", " ", " "},
{" ", " ", " ", "I", "D", " ", " ", " ", " "},
{"u", "u", " ", " ", " ", "OM", " ", "u", "u"}
};
//----------------------------------语法分析函数声明及定义 ---------------------------------------------
void input(); //输入字符流
void init_stack(); //初始化堆栈
int ll1_analyzing(); //主分析程序
void ll1array_push(char); //将得到的产生式字符串压入堆栈中
int is_Vt(); //判断栈顶符号是否终结符号
int is_ll1array(char); //分析当前栈和流首符号能否在LL1表中找到产生式
int Vn_index(); //获得栈顶字符在非终结符集中的位置
int Vt_index(char); //获得输入流首元素在终结符集中的位置
void pop(); //将堆栈中首符号弹出 修改栈顶符号
void push(char); //将字符压入堆栈 修改栈顶符号
void reverse(); //将LL1表中的产生式字符串倒序 该函数定义有错误
int printerror();
void input()
{
strcpy(analyzed_sentence,par_list);
}
void init_stack()
{
stack[0] = '#';
stack[1] = Vn_array[0]; //开始符进栈
cout << stack[1] << "->";
}
int ll1_analyzing()
{
top = stack[1];
int error;
for (int i=0;i<=strlen(analyzed_sentence);i++) {
int test;
test = is_Vt(); //判断当前堆栈首字符是否是终结符号
if (1 == test) {
if (top == analyzed_sentence[i]) { //如果堆栈和输入流首字符都是一样的终结符号
identified[n++] = top;
pop(); //弹出栈顶字符
continue;
}
else {
printerror();
break;
}
}
else if ('#' == top) { //结束,将最终的表达式打印出来,除了'#'
for (int p=0;p<strlen(analyzed_sentence)-1;p++) {
printf("%c", analyzed_sentence[p]);
}
break;
}
else { //当前堆栈首字符是非终结符号
do {
int judge=0;
judge = is_ll1array(analyzed_sentence[i]); //判断LL1表中对应项是否有产生式
if (judge == 1) {
if (1 == is_Vt()) { //假设有符号不匹配,出错 “好象着段用不着”
error=printerror();
break;
}
ll1array_push(analyzed_sentence[i]);
}
else {
error = printerror();
break;
}
}
while (top != analyzed_sentence[i]);
if (error == 1)
break;
identified[n++] = top;
if (top != '#')
pop();
}
}
if(error==1)return 0;
else
{cout << "这是一句合法的句子!" <<endl;
return 1;}
}
void ll1array_push(char currentchar)
{
int i,j;
i=Vn_index(); //求栈顶元素在Vn数组里面的下标
j=Vt_index(currentchar); //求当前处理的符号在Vt数组里面的下标
temp=LL1_array[i][j];
reverse();
pop();
int k;
for(k=0;k<strlen(temp);k++)
{
push(temp[k]);
}
printf("%s", identified);
for (int m=strlen(stack)-1;m>0;m--)
cout << stack[m] ;
cout << "->";
if (top == 'u')
pop();
}
void pop()
{
int topnum;
topnum = strlen(stack)-1;
stack[topnum] = '\0';
top = stack[topnum-1];
}
void push(char element)
{
int topnum;
topnum = strlen(stack);
stack[topnum] = element;
top = element;
}
int is_Vt()
{
int i;
int hit=0;
for (i=0;i<strlen(Vt_array);i++) {
if(top == Vt_array[i])
hit = 1;
}
if (top == '#')
hit = 0;
if (hit == 1)
return 1;
else
return -1;
}
int is_ll1array(char currentchar)
{
int i,j;
i=Vn_index(); //求栈顶元素在Vn数组里面的下标
j=Vt_index(currentchar); //求当前处理的符号在Vt数组里面的下标
if (LL1_array[i][j] == " ") {
return -1;
}
else
return 1;
}
int Vn_index()
{
for(int i=0;i<strlen(Vn_array);i++) {
if (top == Vn_array[i])
return i;
}
return -1;
}
int Vt_index(char index_array)
{
for(int i=0;i<strlen(Vt_array);i++) {
if (index_array == Vt_array[i])
return i;
}
return -1;
}
void reverse() //逆序处理
{
strcpy(s, temp);
int i,j;
char tem;
i=0;
while (s[i] != '\0')
++i;
--i;
if (s[i] == '\n')
--i;
j=0;
while (j<i)
{
tem = s[j];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -