syntax.cpp
上传用户:shyefeng
上传日期:2013-04-07
资源大小:80k
文件大小:17k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*******************************************
  2.  语法分析程序
  3.  作者:龚勋         刘栋         罗晓波
  4.  学号:200131500342 200131500350 200131500351
  5.  计科系 13班
  6. ********************************************/
  7. #include<stdlib.h>
  8. #include<stdio.h>
  9. #include<string.h>
  10. /*******************************************/
  11. int count=0;              /*分解的产生式的个数*/
  12. int number;               /*所有终结符和非终结符的总数*/
  13. char start;               /*开始符号*/
  14. char termin[50];          /*终结符号*/
  15. char non_ter[50];         /*非终结符号*/
  16. char v[50];               /*所有符号*/
  17. char left[50];            /*左部*/
  18. char right[50][50];       /*右部*/
  19. char first[50][50],follow[50][50];       /*各产生式右部的FIRST和左部的FOLLOW集合*/
  20. char first1[50][50];      /*所有单个符号的FIRST集合*/
  21. char select[50][50];      /*各单个产生式的SELECT集合*/
  22. char f[50],F[50];         /*记录各符号的FIRST和FOLLOW是否已求过*/
  23. char empty[20];           /*记录可直接推出^的符号*/
  24. char TEMP[50];            /*求FOLLOW时存放某一符号串的FIRST集合*/
  25. int validity=1;           /*表示输入文法是否有效*/
  26. int ll=1;                 /*表示输入文法是否为LL(1)文法*/
  27. int M[20][20];            /*分析表*/
  28. char choose;              /*用户输入时使用*/
  29. char empt[20];            /*求_emp()时使用*/
  30. char fo[20];              /*求FOLLOW集合时使用*/
  31. /*******************************************
  32.  判断一个字符是否在指定字符串中
  33. ********************************************/
  34. int in(char c,char *p)
  35. {
  36. int i;
  37. if(strlen(p)==0)
  38. return(0);
  39. for(i=0;;i++)
  40. {
  41. if(p[i]==c)
  42. return(1);       /*若在,返回1*/
  43. if(i==strlen(p))
  44.     return(0);       /*若不在,返回0*/
  45. }
  46. }
  47. /*******************************************
  48.  得到一个不是非终结符的符号
  49. ********************************************/
  50. char c()
  51. {
  52. char c='A';
  53.     while(in(c,non_ter)==1)
  54. c++;
  55. return(c);
  56. }
  57. /*******************************************
  58.  分解含有左递归的产生式
  59. ********************************************/
  60. void recur(char *point)
  61. {                     /*完整的产生式在point[]中*/
  62.     int j,m=0,n=3,k;
  63. char temp[20],ch;
  64. ch=c();           /*得到一个非终结符*/
  65. k=strlen(non_ter);
  66. non_ter[k]=ch;
  67. non_ter[k+1]='';
  68. for(j=0;j<=strlen(point)-1;j++)
  69. {
  70. if(point[n]==point[0])
  71. {                          /*如果‘|’后的首符号和左部相同*/
  72. for(j=n+1;j<=strlen(point)-1;j++)
  73. {
  74.     while(point[j]!='|'&&point[j]!='')
  75.     temp[m++]=point[j++];
  76. left[count]=ch;
  77. memcpy(right[count],temp,m);
  78. right[count][m]=ch;
  79. right[count][m+1]='';
  80. m=0;
  81. count++;
  82. if(point[j]=='|')
  83. {
  84. n=j+1;
  85. break;
  86. }
  87. }
  88. }
  89. else
  90. {                          /*如果‘|’后的首符号和左部不同*/
  91. left[count]=ch;
  92. right[count][0]='^';
  93. right[count][1]='';
  94. count++;
  95. for(j=n;j<=strlen(point)-1;j++)
  96. {
  97.     if(point[j]!='|')
  98.         temp[m++]=point[j];
  99.     else
  100. {
  101.     left[count]=point[0];
  102.     memcpy(right[count],temp,m);
  103.     right[count][m]=ch;
  104.     right[count][m+1]='';
  105. printf(" count=%d ",count);
  106. m=0;
  107.     count++;
  108. }
  109. }
  110.             left[count]=point[0];
  111.     memcpy(right[count],temp,m);
  112.     right[count][m]=ch;
  113.        right[count][m+1]='';
  114. count++;
  115.     m=0;
  116. }
  117. }
  118. }
  119. /*******************************************
  120.  分解不含有左递归的产生式
  121. ********************************************/
  122. void non_re(char *point)
  123. {
  124.     int m=0,j;
  125. char temp[20];
  126. for(j=3;j<=strlen(point)-1;j++)
  127. {
  128.     if(point[j]!='|')
  129.     temp[m++]=point[j];
  130. else
  131. {
  132.     left[count]=point[0];
  133.     memcpy(right[count],temp,m);
  134.     right[count][m]='';
  135. m=0;
  136. count++;
  137. }
  138. }
  139.     left[count]=point[0];
  140.     memcpy(right[count],temp,m);
  141.     right[count][m]='';
  142.     count++;
  143. m=0;
  144. }
  145. /*******************************************
  146.  读入一个文法
  147. ********************************************/
  148. char grammer(char *t,char *n,char *left,char right[50][50])
  149. {
  150. char vn[50],vt[50];
  151. char s;
  152. char p[50][50];
  153. int i,j,k;
  154. printf("请输入文法的非终结符号串:");
  155.     scanf("%s",vn);
  156. getchar();
  157.     i=strlen(vn);
  158.     memcpy(n,vn,i);
  159. n[i]='';
  160. printf("请输入文法的终结符号串:");
  161.     scanf("%s",vt);
  162. getchar();
  163.     i=strlen(vt);
  164.     memcpy(t,vt,i);
  165. t[i]='';
  166.     printf("请输入文法的开始符号:");
  167. scanf("%c",&s);
  168. getchar();
  169. printf("请输入文法产生式的条数:");
  170.     scanf("%d",&i);
  171. getchar();
  172.     for(j=1;j<=i;j++)
  173. {
  174. printf("请输入文法的第%d条(共%d条)产生式:",j,i);
  175. scanf("%s",p[j-1]);
  176.         getchar();
  177. }
  178.     for(j=0;j<=i-1;j++)
  179. if(p[j][1]!='-'||p[j][2]!='>')
  180. { printf("ninput error!");
  181.     validity=0;
  182. return('');
  183.         }            /*检测输入错误*/
  184.    for(k=0;k<=i-1;k++)
  185.    {                        /*分解输入的各产生式*/
  186.         if(p[k][3]==p[k][0])
  187.             recur(p[k]);
  188. else
  189.     non_re(p[k]);
  190. }
  191. return(s);
  192. }
  193. /*******************************************
  194.  将单个符号或符号串并入另一符号串
  195. ********************************************/
  196. void merge(char *d,char *s,int type)
  197. {                 /*d是目标符号串,s是源串,type=1,源串中的‘ ^ ’一并并入目串;
  198.                type=2,源串中的‘ ^ ’不并入目串*/
  199.     int i,j;
  200. for(i=0;i<=strlen(s)-1;i++)
  201. {
  202.         if(type==2&&s[i]=='^')
  203. ;
  204. else
  205. {
  206. for(j=0;;j++)
  207. {
  208.     if(j<strlen(d)&&s[i]==d[j])
  209.    break;
  210.                 if(j==strlen(d))
  211. {
  212.     d[j]=s[i];
  213.     d[j+1]='';
  214.     break;
  215. }
  216. }
  217. }
  218. }
  219. }
  220. /*******************************************
  221.  求所有能直接推出^的符号
  222. ********************************************/
  223. void emp(char c)
  224. {                   /*即求所有由‘ ^ ’推出的符号*/
  225. char temp[10];
  226. int i;
  227. for(i=0;i<=count-1;i++)
  228. {
  229. if(right[i][0]==c&&strlen(right[i])==1)
  230. {
  231. temp[0]=left[i];
  232. temp[1]='';
  233. merge(empty,temp,1);
  234. emp(left[i]);
  235. }
  236. }
  237. }
  238. /*******************************************
  239.  求某一符号能否推出‘ ^ ’
  240. ********************************************/
  241. int _emp(char c)
  242. {                  /*若能推出,返回1;否则,返回0*/
  243. int i,j,k,result=1,mark=0;
  244. char temp[20];
  245. temp[0]=c;
  246. temp[1]='';
  247. merge(empt,temp,1);
  248. if(in(c,empty)==1)
  249. return(1);
  250. for(i=0;;i++)
  251. {
  252. if(i==count)
  253.             return(0);
  254. if(left[i]==c)         /*找一个左部为c的产生式*/
  255. {
  256.             j=strlen(right[i]);    /*j为右部的长度*/
  257. if(j==1&&in(right[i][0],empty)==1)
  258.     return(1);
  259. else if(j==1&&in(right[i][0],termin)==1)
  260. return(0);
  261. else 
  262. {
  263.                 for(k=0;k<=j-1;k++)
  264.                     if(in(right[i][k],empt)==1)
  265. mark=1;
  266. if(mark==1)
  267. continue;
  268. else
  269.                 {
  270. for(k=0;k<=j-1;k++)
  271. {
  272. result*=_emp(right[i][k]);
  273. temp[0]=right[i][k];
  274. temp[1]='';
  275. merge(empt,temp,1);
  276. }
  277. }
  278. }
  279.     if(result==0&&i<count)
  280.     continue;
  281.     else if(result==1&&i<count)
  282.     return(1);
  283. }
  284. }
  285. }
  286. /*******************************************
  287.  判断读入的文法是否正确
  288. ********************************************/
  289. int judge()
  290. {
  291.     int i,j;
  292. for(i=0;i<=count-1;i++)
  293. {
  294. if(in(left[i],non_ter)==0)
  295. {                    /*若左部不在非终结符中,报错*/
  296. printf("nerror1!");
  297. validity=0;
  298. return(0);
  299. }
  300. for(j=0;j<=strlen(right[i])-1;j++)
  301. {
  302. if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^')
  303. {               /*若右部某一符号不在非终结符、终结符中且不为‘ ^ ’,报错*/
  304. printf("nerror2!");
  305. validity=0;
  306. return(0);
  307. }
  308. }
  309. }
  310. return(1);
  311. }
  312. /*******************************************
  313.  求单个符号的FIRST
  314. ********************************************/
  315. void first2(int i)
  316. {                     /*i为符号在所有输入符号中的序号*/
  317.     char c,temp[20];
  318. int j,k,m;
  319. c=v[i];
  320. char ch='^';
  321. emp(ch);
  322. if(in(c,termin)==1)       /*若为终结符*/
  323.     {
  324.         first1[i][0]=c;
  325.     first1[i][1]='';
  326. }   
  327. else if(in(c,non_ter)==1)       /*若为非终结符*/
  328. {
  329. for(j=0;j<=count-1;j++)
  330. {
  331.             if(left[j]==c)
  332. {
  333.                 if(in(right[j][0],termin)==1||right[j][0]=='^')
  334. {
  335.                     temp[0]=right[j][0];
  336.     temp[1]='';
  337. merge(first1[i],temp,1);
  338. }
  339. else if(in(right[j][0],non_ter)==1)
  340. {
  341. if(right[j][0]==c)
  342. continue;
  343. for(k=0;;k++)
  344. if(v[k]==right[j][0])
  345. break;
  346. if(f[k]=='0')
  347. {   
  348. first2(k);
  349.     f[k]='1';
  350. }
  351. merge(first1[i],first1[k],2);
  352.                     for(k=0;k<=strlen(right[j])-1;k++)
  353. {
  354. empt[0]='';
  355. if(_emp(right[j][k])==1&&k<strlen(right[j])-1)
  356. {
  357.                             for(m=0;;m++)
  358. if(v[m]==right[j][k+1])
  359. break;
  360. if(f[m]=='0')
  361. {
  362. first2(m);
  363. f[m]='1';
  364. }
  365. merge(first1[i],first1[m],2);
  366. }
  367. else if(_emp(right[j][k])==1&&k==strlen(right[j])-1)
  368. {
  369. temp[0]='^';
  370. temp[1]='';
  371. merge(first1[i],temp,1);
  372. }
  373. else 
  374. break;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. f[i]='1';
  381. }
  382. /*******************************************
  383.  求各产生式右部的FIRST
  384. ********************************************/
  385. void FIRST(int i,char *p)
  386. {
  387. int length;
  388. int j,k,m;
  389. char temp[20];
  390. length=strlen(p);
  391. if(length==1)                  /*如果右部为单个符号*/
  392. {
  393. if(p[0]=='^')
  394.         {   
  395. if(i>=0)
  396.             {
  397.     first[i][0]='^';
  398.     first[i][1]='';
  399. }
  400. else
  401. {
  402. TEMP[0]='^';
  403. TEMP[1]='';
  404. }
  405. }
  406. else
  407. {
  408. for(j=0;;j++)
  409. if(v[j]==p[0])
  410. break;
  411. if(i>=0)
  412. {
  413.     memcpy(first[i],first1[j],strlen(first1[j]));
  414.     first[i][strlen(first1[j])]='';
  415. }
  416. else
  417. {
  418. memcpy(TEMP,first1[j],strlen(first1[j]));
  419. TEMP[strlen(first1[j])]='';
  420. }
  421.         }
  422. }
  423. else                      /*如果右部为符号串*/
  424. {
  425. for(j=0;;j++)
  426. if(v[j]==p[0])
  427. break;
  428. if(i>=0)
  429.             merge(first[i],first1[j],2);
  430. else
  431. merge(TEMP,first1[j],2);
  432. for(k=0;k<=length-1;k++)
  433. {
  434. empt[0]='';
  435. if(_emp(p[k])==1&&k<length-1)
  436.                 for(m=0;;m++)
  437. if(v[m]==right[i][k+1])
  438. break;
  439.                 if(i>=0)
  440.     merge(first[i],first1[m],2);
  441. else
  442. merge(TEMP,first1[m],2);
  443. }
  444.             else if(_emp(p[k])==1&&k==length-1)
  445. {
  446.                 
  447. temp[0]='^';
  448. temp[1]='';
  449. if(i>=0)
  450.     merge(first[i],temp,1);   
  451. else
  452. merge(TEMP,temp,1);
  453. }
  454. else if(_emp(p[k])==0)
  455. break;
  456. }
  457. }
  458. }
  459. /*******************************************
  460.  求各产生式左部的FOLLOW
  461. ********************************************/
  462. void FOLLOW(int i)
  463. {
  464. int j,k,m,n,result=1;
  465. char c,temp[20];
  466. c=non_ter[i];             /*c为待求的非终结符*/
  467. temp[0]=c;
  468. temp[1]='';
  469. merge(fo,temp,1);
  470. if(c==start)
  471. {                         /*若为开始符号*/
  472. temp[0]='#';
  473. temp[1]='';
  474. merge(follow[i],temp,1);
  475. }
  476.     for(j=0;j<=count-1;j++)
  477. {
  478. if(in(c,right[j])==1)     /*找一个右部含有c的产生式*/
  479. {
  480. for(k=0;;k++)
  481. if(right[j][k]==c)
  482. break;       /*k为c在该产生式右部的序号*/
  483.             for(m=0;;m++)
  484. if(v[m]==left[j])
  485. break;        /*m为产生式左部非终结符在所有符号中的序号*/
  486. if(k==strlen(right[j])-1)
  487. {              /*如果c在产生式右部的最后*/
  488. if(in(v[m],fo)==1)
  489. {
  490. merge(follow[i],follow[m],1);
  491. continue;
  492.                 }
  493. if(F[m]=='0')
  494. {
  495. FOLLOW(m);
  496. F[m]='1';
  497. }
  498. merge(follow[i],follow[m],1);
  499. }
  500. else 
  501. {              /*如果c不在产生式右部的最后*/
  502. for(n=k+1;n<=strlen(right[j])-1;n++)
  503. {
  504. empt[0]='';
  505. result*=_emp(right[j][n]);
  506. }
  507. if(result==1)
  508. {         /*如果右部c后面的符号串能推出^*/
  509.                     if(in(v[m],fo)==1)
  510. {           /*避免循环递归*/
  511. merge(follow[i],follow[m],1);
  512. continue;
  513. }
  514. if(F[m]=='0')
  515. {
  516.     FOLLOW(m);
  517.     F[m]='1';
  518. }
  519.     merge(follow[i],follow[m],1);
  520. }
  521. for(n=k+1;n<=strlen(right[j])-1;n++)
  522.                     temp[n-k-1]=right[j][n];       
  523. temp[strlen(right[j])-k-1]='';
  524. FIRST(-1,temp);
  525. merge(follow[i],TEMP,2);
  526. }
  527. }
  528. }
  529. F[i]='1';
  530. }
  531. /*******************************************
  532.  判断读入文法是否为一个LL(1)文法
  533. ********************************************/
  534. int ll1()
  535. {
  536.     int i,j,length,result=1;
  537. char temp[50];
  538. for(j=0;j<=49;j++)
  539. {                            /*初始化*/
  540. first[j][0]='';
  541.     follow[j][0]='';
  542. first1[j][0]='';
  543. select[j][0]='';
  544. TEMP[j]='';
  545. temp[j]='';
  546. f[j]='0';
  547. F[j]='0';
  548. }
  549. for(j=0;j<=strlen(v)-1;j++)
  550.     first2(j);                /*求单个符号的FIRST集合*/
  551. printf("nfirst1:");
  552. for(j=0;j<=strlen(v)-1;j++)
  553. printf("%c:%s  ",v[j],first1[j]);
  554.     printf("nempty:%s",empty);
  555. printf("n_emp:");
  556. for(j=0;j<=strlen(v)-1;j++)
  557.         printf("%d  ",_emp(v[j]));
  558. for(i=0;i<=count-1;i++)
  559.     FIRST(i,right[i]);          /*求FIRST*/
  560. for(j=0;j<=strlen(non_ter)-1;j++)
  561.     {                               /*求FOLLOW*/
  562. if(fo[j]==0)
  563. {
  564. fo[0]='';
  565.     FOLLOW(j);
  566. }
  567.     }
  568. printf("nfirst:");
  569. for(i=0;i<=count-1;i++)
  570.     printf("%s ",first[i]);
  571. printf("nfollow:");
  572.     for(i=0;i<=strlen(non_ter)-1;i++)
  573.     printf("%s ",follow[i]);
  574. for(i=0;i<=count-1;i++)
  575. {                          /*求每一产生式的SELECT集合*/
  576.         memcpy(select[i],first[i],strlen(first[i]));
  577.         select[i][strlen(first[i])]='';
  578. for(j=0;j<=strlen(right[i])-1;j++)
  579. result*=_emp(right[i][j]);
  580. if(strlen(right[i])==1&&right[i][0]=='^')
  581. result=1;
  582. if(result==1)
  583. {
  584. for(j=0;;j++)
  585. if(v[j]==left[i])
  586. break;
  587. merge(select[i],follow[j],1);
  588. }
  589. }
  590. printf("nselect:");
  591. for(i=0;i<=count-1;i++)
  592.     printf("%s ",select[i]);
  593. memcpy(temp,select[0],strlen(select[0]));
  594. temp[strlen(select[0])]='';
  595. for(i=1;i<=count-1;i++)
  596. {                 /*判断输入文法是否为LL(1)文法*/
  597.         length=strlen(temp);
  598. if(left[i]==left[i-1])
  599. {
  600. merge(temp,select[i],1);
  601. if(strlen(temp)<length+strlen(select[i]))
  602. return(0);
  603. }
  604. else
  605. {
  606. temp[0]='';
  607.     memcpy(temp,select[i],strlen(select[i]));
  608. temp[strlen(select[i])]='';
  609. }
  610. }
  611. return(1);
  612. }
  613. /*******************************************
  614.  构造分析表M
  615. ********************************************/
  616. void MM()
  617. {
  618.     int i,j,k,m;
  619. for(i=0;i<=19;i++)
  620. for(j=0;j<=19;j++)
  621. M[i][j]=-1;
  622.     i=strlen(termin);
  623.     termin[i]='#';     /*将#加入终结符数组*/
  624.     termin[i+1]='';
  625. for(i=0;i<=count-1;i++)
  626. {
  627.         for(m=0;;m++)
  628. if(non_ter[m]==left[i])
  629. break;      /*m为产生式左部非终结符的序号*/
  630. for(j=0;j<=strlen(select[i])-1;j++)
  631. {
  632. if(in(select[i][j],termin)==1)
  633. {
  634. for(k=0;;k++)
  635. if(termin[k]==select[i][j])
  636. break;        /*k为产生式右部终结符的序号*/
  637.                 M[m][k]=i;
  638. }
  639. }
  640. }
  641. }
  642. /*******************************************
  643.  总控算法
  644. ********************************************/
  645. void syntax()
  646. {
  647. int i,j,k,m,n,p,q;
  648.     char ch;
  649. char S[50],str[50];
  650.     printf("请输入该文法的句型:");
  651. scanf("%s",str);
  652. getchar();
  653. i=strlen(str);
  654. str[i]='#';
  655. str[i+1]='';
  656. S[0]='#';
  657. S[1]=start;
  658. S[2]='';
  659. j=0;
  660. ch=str[j];
  661.     while(1)
  662. {
  663. if(in(S[strlen(S)-1],termin)==1)
  664. {
  665.             if(S[strlen(S)-1]!=ch)
  666. {
  667. printf("该符号串不是文法的句型!");
  668.                 return;
  669. }
  670. else if(S[strlen(S)-1]=='#')
  671. {
  672.                 printf("该符号串是文法的句型.");
  673.                 return;
  674. }
  675. else
  676. {
  677.                 S[strlen(S)-1]='';
  678. j++;
  679. ch=str[j];
  680. }
  681. }
  682. else 
  683. {   
  684.             for(i=0;;i++)
  685. if(non_ter[i]==S[strlen(S)-1])
  686. break;
  687. for(k=0;;k++)
  688. {
  689. if(termin[k]==ch)
  690. break;
  691. if(k==strlen(termin))
  692. {
  693. printf("词法错误!");
  694. return;
  695. }
  696. }
  697. if(M[i][k]==-1)
  698. {
  699. printf("语法错误!");
  700. return;
  701. }
  702. else
  703. {
  704.                 m=M[i][k];
  705.                 if(right[m][0]=='^')
  706. S[strlen(S)-1]='';
  707. else
  708. {
  709.     p=strlen(S)-1;
  710.     q=p;
  711.     for(n=strlen(right[m])-1;n>=0;n--)
  712.                         S[p++]=right[m][n];
  713.     S[q+strlen(right[m])]='';
  714. }
  715. }
  716. }
  717.     printf("S:%s  str:",S);
  718. for(p=j;p<=strlen(str)-1;p++)
  719. printf("%c",str[p]);
  720. printf(" n");
  721. }
  722. }
  723. /*******************************************
  724.  一个用户调用函数
  725. ********************************************/
  726. void menu()
  727. {
  728. syntax();
  729. printf("n是否继续?(y or n):");
  730. scanf("%c",&choose);
  731. getchar();
  732. while(choose=='y')
  733. menu();
  734. }
  735. }
  736. /*******************************************
  737.  主函数
  738. ********************************************/
  739. void main()
  740. {
  741. int i,j;
  742. start=grammer(termin,non_ter,left,right);               /*读入一个文法*/
  743.     printf("count=%d",count);
  744. printf("nstart:%c",start);
  745. strcpy(v,non_ter);
  746. strcat(v,termin);
  747. printf("nv:%s",v);
  748. printf("nnon_ter:%s",non_ter);
  749.     printf("ntermin:%s",termin);
  750. printf("nright:");
  751. for(i=0;i<=count-1;i++)
  752.     printf("%s   ",right[i]); 
  753.     printf("nleft:");
  754. for(i=0;i<=count-1;i++)
  755. printf("%c   ",left[i]);            
  756.     if(validity==1)
  757.     validity=judge();
  758.     printf("nvalidity=%d",validity);
  759. if(validity==1)
  760. {
  761.         ll=ll1();
  762. printf("nll=%d",ll);
  763. if(ll==0)
  764. printf("n该文法不是一个LL1文法!");
  765. else
  766. {
  767.     MM();
  768.             printf("n");
  769.     for(i=0;i<=19;i++)
  770.         for(j=0;j<=19;j++)
  771.         if(M[i][j]>=0)
  772.         printf("M[%d][%d]=%d ",i,j,M[i][j]);
  773.     menu();
  774. }
  775. }
  776. }