CSUFT 编译原理实验二LL(1)文法分析

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <stack>
  5 #include <queue>
  6 #include <map>
  7 #include <algorithm>
  8 #include <vector>
  9
 10 using namespace std;
 11
 12 char A[20];/*分析栈*/
 13 char B[20];/*剩余串*/
 14 char v1[20]= {‘i‘,‘+‘,‘*‘,‘(‘,‘)‘,‘#‘}; /*终结符  */
 15 char v2[20]= {‘E‘,‘G‘,‘T‘,‘S‘,‘F‘}; /*非终结符   */
 16
 17 int j=0,b=0,top=0,l;/*L为输入串长度 */
 18    char x,ch;
 19     int k=1;
 20     int m,n;
 21     int flag=0,finish=0;
 22
 23 typedef struct type/*产生式类型定义      */
 24 {
 25     char origin;/*大写字符  */
 26     char array[5];/*产生式右边字符 */
 27     int length;/*字符个数      */
 28 } type;
 29
 30 type e,t,g,g1,s,s1,f,f1,cha;/*结构体变量  */
 31 type C[10][10];/*预测分析表      */
 32
 33 void init()
 34 {
 35     e.origin=‘E‘;
 36     strcpy(e.array,"TG");
 37     t.origin=‘T‘;
 38     strcpy(t.array,"FS");
 39     g.origin=‘G‘;
 40     strcpy(g.array,"+TG");
 41     g1.origin=‘G‘;
 42     g1.array[0]=‘^‘;
 43     s.origin=‘S‘;
 44     strcpy(s.array,"*FS");
 45     s1.origin=‘S‘;
 46     s1.array[0]=‘^‘;
 47     f.origin=‘F‘;
 48     strcpy(f.array,"(E)");
 49     f1.origin=‘F‘;
 50     f1.array[0]=‘i‘;
 51
 52     for(int m=0; m<=4; m++) /*初始化分析表*/
 53         for(int n=0; n<=5; n++)
 54             C[m][n].origin=‘N‘;/*全部赋为空*/
 55     /*填充分析表*/
 56     C[0][0]=e;
 57     C[0][3]=e;
 58     C[1][1]=g;
 59     C[1][4]=g1;
 60     C[1][5]=g1;
 61     C[2][0]=t;
 62     C[2][3]=t;
 63     C[3][1]=s1;
 64     C[3][2]=s;
 65     C[3][4]=C[3][5]=s1;
 66     C[4][0]=f1;
 67     C[4][3]=f;
 68 }
 69
 70 void print()/*输出分析栈  */
 71 {
 72     int a;/*指针*/
 73     for(a=0; a<=top+1; a++)
 74         printf("%c",A[a]);
 75     printf("\t\t");
 76 }
 77
 78 void print1()/*输出剩余串*/
 79 {
 80     int j;
 81     for(j=0; j<b; j++) /*输出对齐符*/
 82         printf(" ");
 83     for(j=b; j<=l; j++)
 84         printf("%c",B[j]);
 85     printf("\t\t\t");
 86 }
 87 int main()
 88 {
 89     init();
 90     //测试样例反例
 91     //i+i(i+i)#
 92     //i()#
 93     //正确样例
 94     //i+i*i#
 95
 96
 97     do/*读入分析串*/
 98     {
 99         scanf("%c",&ch);
100         if ((ch!=‘i‘) &&(ch!=‘+‘) &&(ch!=‘*‘)&&(ch!=‘(‘)&&(ch!=‘)‘)&&(ch!=‘#‘))
101         {
102             printf("输入串中有非法字符\n");
103             exit(1);
104         }
105         B[j]=ch;
106         j++;
107     }while(ch!=‘#‘);
108     l=j;/*分析串长度*/
109     ch=B[0];/*当前分析字符*/
110     A[top]=‘#‘;
111     A[++top]=‘E‘;/*‘#‘,‘E‘进栈*/
112     printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n");
113
114         do{
115             flag = 0;
116         if(finish) break;
117         x=A[top--];/*x为当前栈顶字符*/
118         printf("%d",k++);
119         printf("\t\t");
120
121
122
123
124         for( j=0; j<=5; j++) /*判断是否为终结符*/
125         {
126             if(x==v1[j])
127             {
128                 flag=1;
129                 break;
130             }
131         }
132             if(flag==1)/*如果是终结符*/
133             {
134                 if(x==‘#‘)
135                 {
136                     finish=1;/*结束标记*/
137                     printf("acc!\n");/*接受 */
138                     getchar();
139                     getchar();
140                     exit(1);
141                 }
142                 if(x==ch)
143                 {
144                     print();
145                     print1();
146                     printf("%c匹配\n",ch);
147                     ch=B[++b];/*下一个输入字符*/
148                     flag=0;/*恢复标记*/
149                 }
150                 /*else //出错处理
151                 {
152                     print();
153                     print1();
154                     printf("%c出错\n",ch);//输出出错终结符
155                     exit(1);
156                 }*/
157             }
158             else/*非终结符处理*/
159             {
160                 for(j=0; j<=4; j++)
161                     if(x==v2[j])
162                     {
163                         m=j;/*行号*/
164                         break;
165                     }
166                 for(j=0; j<=5; j++)
167                     if(ch==v1[j])
168                     {
169                         n=j;/*列号*/
170                         break;
171                     }
172                 cha=C[m][n];
173                 if(cha.origin!=‘N‘)/*判断是否为空*/
174                 {
175                     print();
176                     print1();
177                     printf("%c->",cha.origin);/*输出产生式*/
178                     int len = strlen(cha.array); //长度是array的长度
179                     for(j=0; j<len; j++)
180                         printf("%c",cha.array[j]);
181                     printf("\n");
182                     for(j=(len-1); j>=0; j--) /*产生式逆序入栈*/
183                         A[++top]=cha.array[j];
184                     if(A[top]==‘^‘)/*为空则不进栈*/
185                         top--;
186                 }
187                 else //出错处理 调整顺序
188                 {
189                     print();
190                     print1();
191                     printf("%c出错\n",ch);//输出出错终结符
192                     exit(1);
193                 }
194
195             }
196
197         }while(top!=-1); //当分析栈不为空
198
199     return 0;
200 }

送人玫瑰手留余香。。。。

时间: 2024-08-12 06:07:38

CSUFT 编译原理实验二LL(1)文法分析的相关文章

编译原理实验二:LL(1)语法分析器

一.实验要求 不得不想吐槽一下编译原理的实验代码量实在是太大了,是编译原理撑起了我大学四年的代码量... 这次实验比上次要复杂得多,涵盖的功能也更多了,我觉得这次实验主要的难点有两个(其实都是难点...): 1. 提取左公因子或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下面我贴出实验的一些关键代码和算法思想. 二.基于预测分析表法的语法分析 2.1 代码结构 2.1.1  Grammar类    功

编译原理 - 实验二 - FLEX词法分析器

FLEX词法分析器 一.Lex和Yacc介绍 Lex 是一种生成扫描器的工具.扫描器是一种识别文本中的词汇模式的程序. 一种匹配的常规表达式可能会包含相关的动作.这一动作可能还包括返回一个标记. 当 Lex 接收到文件或文本形式的输入时,它试图将文本与常规表达式进行匹配. 它一次读入一个输入字符,直到找到一个匹配的模式. 如果能够找到一个匹配的模式,Lex 就执行相关的动作(可能包括返回一个标记). 另一方面,如果没有可以匹配的常规表达式,将会停止进一步的处理,Lex 将显示一个错误消息. Ya

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

哈工大软件学院编译原理实验1——词法分析

这次实验被"过来人"们定位非常easy,实验内容例如以下: ----------------------------------------------------------------------------------- 对例如以下工作进行展开描写叙述 (1) 给出语言的词法规则描写叙述 · 标识符.keyword.整常数.字符常数.浮点常数 · 单界符:+,-,×,;,- · 双界符:/*,:=,>=,<=,!=,- · 凝视 (2) 针对这样的单词的状态转换图和程

[Vue源码]一起来学Vue模板编译原理(二)-AST生成Render字符串

本文我们一起通过学习Vue模板编译原理(二)-AST生成Render字符串来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学Vue模板编译原理(一)-Template生成AST 一起来学Vue模板编译原理(二)-AST生成Render字符串 一起来学Vue虚拟DOM解析-Virtual Dom实现和Dom-diff算法 这些文章统一放在我的git仓库:https://github.com/yzsunlei/javascri

编译原理 实验3 语法分析

语法分析 一. 实验目的 算术表达式的文法可以是(你可以根据需要适当改变): E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 程序输入/输出示例: 如参考C语言的运算符.输入如下表达式(以分号为结束)和输出结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)/3+4-(5+6/7); 输出:正

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一.实验要求 实验二 基于预測方法的语法分析程序的设计 一.实验目的 了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法. 二.实验内容 1.了解编译程序的基于预測方法的语法分析过程. 2.依据预測分析原理设计一个基于预測方法的语法分析程序. 三.实验要求 对给定文法G[S]: S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m 当中,$表示空串. 1.推断上

编译原理(二)

一.简单表达式的翻译器 通过上一篇知道,预测语法分析不能处理左递归的文法(比如对stmt分析,则遇到多个以stmt开头的产生式,这使得向前看符号无法匹配一个分支,而右递归则是可以使用预测分析法处理). 1. 抽象语法和具体语法 抽象语法:每个内部结点代表一个运算符,该结点的子结点表示这个运算符的分量.比如表达式 9 -5 + 2,其抽象语法树为 将前面介绍的使用终结符和非终结符表示的语法分析树称为具体语法树,相应的文法为具体语法.这里介绍的为抽象语法树. 考虑前文介绍的一个文法: expr ->

编译原理实验:java实现语法分析器

实验方法:递归下降分析法基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分.因此需要分别构造 E,E’,T,T’,F 函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能. java程序实现: import java.util.Scanner; public class GrammarAnalysis { static char[] s = new char[100]; static int sing; static int i; //用来