1、前序这是编译原理的实验,自认为是上大学以来做过的最难的一个实验。
实验用到的基础知识:C语言、数据结构、汇编(只需简单的了解)。
开发工具:VC
2、问题描述编译整数四则运算表达式,将整数四则运算表达式翻译为汇编语言代码。
消除左递归后的文法:
E→TE'
E'→+TE' |ε
T→FT'
T'→*FT' |ε
F→(E) | i
消除左递归后的翻译模式:
E ::= T {E'.i:=T.nptr}
E' {E.nptr:=E'.s}
E'::= + T {E'1.i:=mknode(‘+',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= - T {E'1.i:=mknode(‘-',E'.i,T.nptr)}
E'1 {E'.s:=E1.s}
E'::= ε {E'.s:= E'.i}
T ::= F {T'.i:=F.nptr}
T' {T.nptr:=T'.s}
T'::= * F {T'1.i:=mknode(‘*',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T'::= / F {T'1.i:=mknode(‘/',T'.i,F.nptr)}
T'1 {T'.s:=T1.s}
T' ::= ε {T'.s:= T'.i}
F ::= (E) {F.nptr:=E.nptr}
F ::= num {F.nptr:=mkleaf(num,num.val)}
3、全局定义
test.c文件
#ifndef TEST_C
#define TEST_C
/**
* 全局变量和全局函数文件
**/
#include
#include
#include
#include
/************************* 以下是全局变量(函数)的定义 *******************/
//输入的表达式最大长度,可以看做是缓冲区的长度
#define MAX_EXPRESSION_LENGTH 50
//存放输入的表达式
char expression[MAX_EXPRESSION_LENGTH];
//表达式字符数组的下标
int expression_index=0;
//存放一个单词符号
char strToken[MAX_EXPRESSION_LENGTH/2];
//判断是否是数字
int isNum(char * strToken)
{
int i=0;
while(strToken[i]){
if(!isdigit(strToken[i]))
break;
i++;
}
return strToken[i]==0;
}
//错误处理程序
void error(char* errerMessage)
{
printf("\nERROR:%s\n",errerMessage);
exit(0);
}
/************************* 以上是全局变量(函数)的定义 ******************/
#endif
4、词法分析词法分析的要求是:接受一个表达式,输出该表达式中的各类单词符号
一般有两种方法来进行词法分析,一种是用状态图来实现,一种是用状态转换表。下面采用状态图实现
首先定义单词符号的种类和所属类型
typedef enum Symbol { ERR = -1, END, NUM, PLUS, MINUS, TIMES, SLASH, LPAREN, RPAREN } Symbol;
然后转态转换图如下所示:
test1.c文件用代码表示如下:
#ifndef TEST1_C
#define TEST1_C
/**
* 采用状态图进行词法分析以及测试词法分析
*
**/
#include"test.c"
//枚举类型
typedef enum Symbol { ERR = -1, END, NUM, PLUS, MINUS, TIMES,
SLASH, LPAREN, RPAREN } Symbol;
//获取一个单词符号,该单词符号存放在strToken中。返回该单词符号的枚举类型
Symbol getToken();
//根据传入的枚举类型输出对应的单词符号
void printToken(Symbol i);
//测试词法分析
void testLexAnalyse();
//获取一个单词符号,该单词符号存放在strToken中。返回该单词符号的枚举类型
Symbol getToken()
{
char ch;
int state=0;//每次都是从状态0开始
int j=0;
//表达式遍历完成,单词符号为'#'
if(expression[expression_index]=='\0'){
strToken[0]='#';
strToken[1]='\0';
return END;
}
while(1){
switch(state){
case 0:
//读取一个字符
ch=strToken[j++]=expression[expression_index++];
if(isspace(ch)){
j--;//注意退格
state=0;
}
else if(isdigit(ch))
state=1;
else if(ch=='+')
state=2;
else if(ch=='-')
state=3;
else if(ch=='*')
state=4;
else if(ch=='/')
state=5;
else if(ch=='(')
state=6;
else if(ch==')')
state=7;
else
return ERR;
break;
case 1:
ch=strToken[j++]=expression[expression_index++];
if(isdigit(ch))
state=1;
else{
expression_index--;
strToken[--j]=0;
return NUM;
}
break;
case 2:
strToken[j]=0;
return PLUS;
case 3:
strToken[j]=0;
return MINUS;