gs语法分析实验报告c语言,C语言语法分析器 编译原理实验报告 308129512@qq.com

满意答案

02ae427d08e371d7e90d5b995e828d6d.png

qqben21

2013.04.17

02ae427d08e371d7e90d5b995e828d6d.png

采纳率:45%    等级:12

已帮助:15320人

#include

void main()

{

int m=0,n=0,n1=0,n2=0,n3=0,zg,fzg,flag;

int bz[7]={1,1,1,1,1,1,1};/*状态改变控制,1 表示可以改变状态zt值,0 表示不可以*/

int zt[7]={2,2,2,2,2,2,2};/*状态值,2表示未定状态,1表示 是,0表示 否*/

char temp[100]="\0";/*用于求first集*/

char z[7];/*非总结符*/

char z1[7];/*总结符*/

char z2[7]="\0";/*gs[]文法中出现的标记个数的辅助字符 01234*/

char gs[100]="\0";/*文法,按顺序排成字符串*/

printf("请依次输入非终结符(不超过7个):");

gets(z);

while(z[m]!='\0')

{m++;}

fzg=m;//zg是非终结符个数

while(n

{z2[n]=n+48;n++;}//生成01234辅助字符

printf("您输入了:");

puts(z);

fflush(stdin);

printf("请依次输入终结符(不超过7个):");

gets(z1);

while(z1[n1]!='\0')

{n1++;}

zg=n1;

printf("您输入了:");

puts(z1);

fflush(stdin);

printf("按照正确格式输入所有文法(总长度不超过100格式如下):");

printf("如果文法为(字符'k'表示空):\n");

printf("S-->AB S-->bC A-->k A-->b\n");

printf("输入:0SAB0SbC1Ak1Ab\n");

printf(" (注:数字01234表示第一二三四个非终结符)\n");

gets(gs);

fflush(stdin);

printf("您输入了:");

puts(gs);

m=0;

//对于输入文法字符串的转换,将每个文法式左部去除

while(gs[m]!='\0')

{

n=m;

if(gs[m]>='0'&&gs[m]<='9')

{

m++;

while(gs[m]!='\0')

{

gs[m]=gs[m+1];

m++;

}

//gs[m-1]='\0';

}

m=++n;

}

m=0;

//puts(gs);

/*情况一,直接判定是 形如: (A-->k) */

while(gs[m]!='\0')

{

if(gs[m]=='k')

{

zt[gs[m-1]-48]=1;

bz[gs[m-1]-48]=0;

}

m++;

}

/*情况二,直接判定--否 形如: (D-->aS ,D-->c) */

for(n=0;n

{

if(bz[n]==1)

{

m=0;

n2=0;

while(gs[m]!='\0')

{

if(z2[n]==gs[m])

{

if(gs[m+1]>=z1[0]&&gs[m+1]<=z1[n1-1])

zt[n]=0;

else {n2=99;break;} //gs[m+1] 是非终结符n2做标记

}

//跳出循环,无法解决该情况,推到下面情况三

m++;

}

if(n2!=99) {zt[n]=0;bz[n]=0;} //完成所有扫描,未出现非终结符,得出结论zt[n]=0.bz[n]=0不允许再改变zt[n]

}

}

/*情况三,最终判定*/

do

{

flag=0;

for(n=0;n

{

if(bz[n]==1) //未得到判定

{ m=0;

while(gs[m]!='\0')

{

if(gs[m]==z2[n]) //判定gs[m]是辅助字符0123

{

m++;

while(gs[m]>='A'&&gs[m]<='Z')

{

n1=0;

for(n2=0;n2

{

if(gs[m]==z[n2])

{

if(zt[n2]==1) //这个非终结符能推出空

zt[n]=1;

else if(bz[n2]==1) //这个非终结符 现在 不能推出空,但它的状态可改即它最终结果还未判定

{zt[n]=2;bz[n]=1;}

else

{zt[n]=0;bz[n]=0;n1=99;} //设 m1 做标记供下一if参考

break; //找到gs[m]是哪个非终结符,for循环完成任务,可以结束

}

}

if(n1==99) break;

m++;

}

}

m++;

}

if(zt[n]==1) bz[n]=0;

if(bz[n]==0) flag=1;//对应for下的第一个if(zt[n]==2)

}

}

}while(flag);

printf("结果是:\n");

for(m=0;m<5;m++)

{

switch(zt[m])

{

case 0:printf("%c---否\n",z[m]);break;

case 1:printf("%c---是\n",z[m]);break;

case 2:printf("%c---未定\n",z[m]);break;

}

}

/*

puts(gs);

puts(zt);

puts(z);

puts(z1);

puts(z2);

printf("%d,,,%d",fzg,zg);

*/

//下面求first集

//下面求first集

for(n=0;n

{bz[n]=0;}

m=0;n=0;n1=0;n2=0;

while(gs[n]>='0'&&gs[n]<='9')

{

for(;m

{

if(n2!=m)

n1=0; //m=n2用于第二次以后的for循环中还原上次m的值

if(gs[n]==z2[m])

{

while(gs[n+1]>'9')

{

if(n1==0)

{temp[m*13+n1]=gs[n+1];n1++;} //如果是第一个直接保存

//不是第一个,先与字符数组中其它字符比较,没相同的才保存

else if(gs[n]>='a'&&gs[n]<='z'&&gs[n+1]>='A'&&gs[n+1]<='Z') //gs[n]是终结符 且 gs[n+1]是非终结符

;//什么也不做,程序继续n++,扫描下一个gs[n]

else

{

for(n3=0;n3<=n1;n3++)

{

if(temp[m*13+n3]==gs[n+1])

break;

}

if(n3>n1) //for循环结束是因为n3而不是break

{temp[m*13+n1]=gs[n+1];n1++;}

}

n++;

}

break; //break位于if(gs[n]==z2[m]),对于gs[n]已找到z2[m]完成任务跳出for循环

}

}

n2=m; //存放该for循环中m的值

n++;

}

//进一步处理集除去非终结符

m=0;n=0;n1=0;n2=0;

for(m=0;m

{

if(flag!=m)

n1=0; //m=flag用于第二次以后的for循环中还原上次m的值

while(temp[m*13+n1]!='\0')

{

while(temp[m*13+n1]>='A'&&temp[m*13+n1]<='Z') //搜索非终结符

{

for(n=0;n

{if(temp[m*13+n1]==z[n])

break;

}

while(temp[m*13+n1]!='\0') //从temp[n*13+n1]开始每个字符依次往前移动一

{temp[m*13+n1]=temp[m*13+n1+1];n1++;}

n1--;

while(temp[n*13+n2]!='\0') //把z[n]对应的first加入temp[m*13+n1]这个first中,每个字符依次加在最后

{

for(n3=0;n3

{

if(temp[m*13+n3]==temp[n*13+n2])

break;

}

if(temp[n*13+n2]=='k'&&zt[m]==0) //那些不能推出 空,但是因为要加入 其他非终结符的first集 而可能含有 空

n2++;

else if(n3>=n1) //for循环结束是因为n3而不是break,即无相同字符

{temp[m*13+n1]=temp[n*13+n2];n2++;n1++;}

else n2++;

}

n1=0;

n2=0;

}

n1++;

}

flag=m; //存放该for循环中m的值

}

//非终结符的first集输出

m=0;n1=0;

for(m=0;m

{

n1=0;

printf("非终结符 %c 的first集是:",z[m]);

while(temp[m*13+n1]!='\0')

{

printf("%c",temp[m*13+n1]);

n1++;

}

printf("\n");

}

}

20分享举报

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值