编译原理之LR(0)分析算法的c实现
来源:互联网 发布:轩辕网络新三板股票 编辑:程序博客网 时间:2024/05/17 00:10
LR(0)分析器的构造算法如下:
对一个文法构造了它的LR(0)分析表后就可以在LR分析器的总控程序(驱动程序)控制下对输入串进行分析,即根据输入串的当前符号和分析栈的栈顶状态查找分析表应采取的动作,对状态栈和符号栈进行相应的操作即移进、归约、接受或报错。具体说明如下:
(1)若ACTION[S,a]=Sj,a为终结符,则把a移入符号栈,j移入状态栈;
(2)若ACTION[S,a]=rj,a为终结符或#号,则用第j个产生式归约,并将两个栈的指针减去k,其中k为第j个产生式右部的符号串长度,这时当面临符号为第j个产生式左部的非终结符,不妨设为A,归约后栈顶状态设为n,则再进行GOTO[n,A];
(3)若ACTION[S,a]=acc,a应为“#”号,则为接受,表示分析成功;
(4)若GOTO[S,A]=j,A为非终结符,表明前一动作是用关于A的产生式归约的,当前面临非终结符A应移入符号栈,j移入状态栈。对于终结符GOTO[S,a]已和ACTION[S,a]重合。(此算法摘自《编译原理》(第2版)张素琴等著,清华大学出版社)
下面就以一个例子来说明LR(0)分析器的构造过程:
已知文法G[S]为:
(1)SàaAcBe
(2)Aàb
(3)AàAb
(4)Bàd
其LR(0)分析表如下:
ACTION
GOTO
a
c
e
b
d
#
S
A
B
0
S2
1
1
acc
2
S4
3
3
S5
S6
4
r2
r2
r2
r2
r2
r2
5
S8
7
6
r3
r3
r3
r3
r3
r3
7
S9
8
r4
r4
r4
r4
r4
r4
9
r1
r1
r1
r1
r1
r1
根据文法G[S]的LR(0)分析表构造LR(0)分析器:
分析器构造程序如下:
/*根据基于LR(0)分析的行动表和状态转换表构造LR(0)分析器*/
#include<stdio.h>
typedef int Action[10][6];//定义二维行动表Action
typedef int Goto[10] [3];//定义二维状态转换表Goto
typedef int Integer[40];//定义一维整型数组Integer
typedef char String[40];//定义一维字符型数组String
void char2Int(String string,Integer integer);//根据编码表将输入字符串string转换为整型串
int findInArray(Integer integer,int findNValue);//查找数组integer中值第一个不等于findNValue的下标
void Push(Integer stack,int topValue);//将topValue压入stack栈顶
void print(Integer statusStack,Integer charStack);//打印栈stack中的非-1内容
void LR_0_AnalyseDevice(String string,Action actionTable,Goto gotoTable);//创建LR(0)分析器,参数中,string为输入字符串,
//actionTable为行动表,gotoTable为状态转换表
int main(){
String string;
Action actionTable = {12,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,10,
-1,-1,-1,14,-1,-1,
-1,15,-1,16,-1,-1,
2,2,2,2,2,2,
-1,-1,-1,-1,18,-1,
3,3,3,3,3,3,
-1,-1,19,-1,-1,-1,
4,4,4,4,4,4,
1,1,1,1,1,1};//根据编码表初始化行动表actionTable,编码表为:-1->空动作,1->r1,2->r2,3->r3,4->r4,10->acc,
//12->S2,14->S4,15->S5,16->S6,18->S8,19->S9,行动表行下标为即为状态,列下标为终结符编码,其编码表为:
//a->0,c->1,e->2,b->3,d->4,#->5
Goto gotoTable = {1,-1,-1,
-1,-1,-1,
-1,3,-1,
-1,-1,-1,
-1,-1,-1,
-1,-1,7,
-1,-1,-1,
-1,-1,-1,
-1,-1,-1,
-1,-1,-1};//初始化状态转换表gotoTable,状态转换表行下标为状态,列下标为非终结符编码,其编码表为:
//S->0,A->1,B->2
printf("******************************************\n");
printf("Please input string...\nString = ");
scanf("%s",string);
printf("\n------------------------------------------\n");
printf("Status Stack Char Stack\n");
printf("+ + + + + + + + + + + + + + + + + + + + + \n");
LR_0_AnalyseDevice(string,actionTable,gotoTable);
printf("******************************************\n");
return 0;
}
void char2Int(String string,Integer integer){
//根据编码表将输入字符串string转换为整型串,编码表为:a->0,c->1,e->2,b->3,d->4,S->5,A->6,B->7,#->8
for(int index = 0;index < 40;index++){
integer[index] = -1;
}
int index = 0;
for(index;string[index] != '\0';index++){//原码到编码的转换
switch (string[index]){
case 'a':integer[index] = 0;break;
case 'c':integer[index] = 1;break;
case 'e':integer[index] = 2;break;
case 'b':integer[index] = 3;break;
case 'd':integer[index] = 4;break;
case 'S':integer[index] = 5;break;
case 'A':integer[index] = 6;break;
case 'B':integer[index] = 7;break;
default:printf("The char you have inputed is invalid!");integer[index] = -1;//输入字符串中出现额外字符
}
}
integer[index] = 8;
}
int findInArray(Integer integer,int findNValue){
//查找数组integer中值第一个不等于findNValue的下标
int findindex = 0;
for(findindex;integer[findindex] == findNValue && findindex < 40;findindex++){
}
if(findindex < 40)
return findindex;
else{//在数组integer中没有找到指定要求的值
printf("Invalid operation!");
return -1;
}
}
void Push(Integer stack,int topValue){
//将topValue压入stack栈顶
int index = 0;
for(index;index < 40;index++){
if(stack[index] != -1){
stack[index-1] = topValue;
break;
}
}
if(index > 40)
printf("Stack index out of boundary!");
}
void print(Integer statusStack,Integer charStack){
//打印状态栈statusStack和字符栈charStack中的内容
int count = 0;
for(int index = 39;index >= 0;index--){//打印状态栈中的信息
if(statusStack[index] != -1){
printf("%d",statusStack[index]);
count++;
}
}
if(count < 25){//确定打印文本中状态和字符的间距,用于美化输出文本
for(int i = 0;i < 25-count;i++){
printf(" ");
}
}
for(int index = 39;index >= 0;index--){//打印字符栈中的信息
if(charStack[index] != -1){
switch (charStack[index]){//字符编码到原码转换
case 0:printf("a");break;
case 1:printf("c");break;
case 2:printf("e");break;
case 3:printf("b");break;
case 4:printf("d");break;
case 5:printf("S");break;
case 6:printf("A");break;
case 7:printf("B");break;
case 8:printf("#");break;
}
}
}
printf("\n");
}
void LR_0_AnalyseDevice(String string,Action actionTable,Goto gotoTable){
//创建LR(0)分析器,参数中,string为输入字符串,actionTable为行动表,gotoTable为状态转换表
int expressions[4][2] = {5,5,1,6,2,6,1,7};//各产生式右部符号串长度
Integer statusStack;//创建状态栈
Integer charStack;//创建符号栈
Integer integer;
char2Int(string,integer);// 将输入字符串转换为整型
for(int index = 0;index < 40;index++){
statusStack[index] = -1;
charStack[index] = -1;
}
statusStack[39] = 0;
charStack[39] = 8;
int index = 0;
int a,A,S,firststatus,firstinput,Sj,inputindex = 0;
print(statusStack,charStack);
while(findInArray(charStack,-1) != 5){//LR(0)分析开始
firststatus = findInArray(statusStack,-1);
S = statusStack[firststatus];//取状态栈栈顶元素
a = integer[inputindex++];//取输入字符串待取字符
if(a == 8)
a = 5;
if(actionTable[S][a] == 10){//分析成功
printf("\n Congratulation!\n Acceptable!\n");
return;
}else if(actionTable[S][a] > 10){//进入其他状态
Push(charStack,a);
Push(statusStack,actionTable[S][a]-10);
print(statusStack,charStack);
}else if(actionTable[S][a] < 10 && actionTable[S][a] > -1){//进入归约程序
int i = firststatus;
for(i;i < firststatus+expressions[actionTable[S][a]-1][0];i++){
statusStack[i] = -1;
charStack[i] = -1;
}
charStack[i-1] = expressions[actionTable[S][a]-1][1];//字符进栈
statusStack[i-1] = gotoTable[statusStack[i]][charStack[i-1]-5];//状态进栈
print(statusStack,charStack);
inputindex--;
}else if(actionTable[S][a] == -1){//出错处理
print(statusStack,charStack);
printf(". . .\n Analysis stoped by accident!\n Sorry,refused!\n");
return ;
}
if(inputindex == 40)//边界括号防越界处理
inputindex = 39;
}
}
- 编译原理之LR(0)分析算法的c实现
- 编译原理(九) LR(0)文法分析法(算法描述和C++代码实现)
- 编译原理(九) LR(0)文法分析法(算法描述和C++代码实现)
- 编译原理(九) LR(0)文法分析法-算法描述
- JAVA语言实现编译原理的LR分析过程模拟
- 【编译原理】自下而上的语法分析之LR分析法
- 编译原理LR分析法c++实现
- 编译原理之算术表达式文法的预测分析算法c实现
- 编译原理之算术表达式的词法分析算法c实现
- 编译原理-LR(0)分析法
- 编译原理 LR(0)项目集规范族的构造 LR(0)分析表+分析语句 详解分析+代码
- 编译原理 LR分析(主要是LR(0)分析)
- LR(0)分析算法
- 编译原理实验——LR(0)分析法
- 编译原理上机作业4——LR(0)分析的DFA生成
- LR(1)分析法 ---编译原理-----
- 编译原理手记07-LR分析法
- 逻辑回归算法的原理及实现(LR)
- Debug和masm对指令的不同处理
- ArcSDE操作非空间数据表
- 忘我的工作,更要有忘我的运动
- Jquery ThickBox的使用
- LeetCode: N-Queens II
- 编译原理之LR(0)分析算法的c实现
- nginx入门学习—— 在已安装好的nginx上添加nginx_upstream_check_module模块(三)
- centos 优先使用本地源
- Zepto源码分析之二~三个API
- AttributeError: 'module' object has no attribute 'randint'
- 怀疑点
- GPU的硬件结构
- typeid
- Github使用学习笔记