[精文优选]编译原理实验报告FIRST集和FOLLOW集.doc

合集下载

转First集合和Follow集合的求法(修改含例子)

转First集合和Follow集合的求法(修改含例子)

转First集合和Follow集合的求法(修改含例⼦)对于终结符和⾮终结符的理解:终结符:通俗的说就是不能单独出现在推导式左边的符号,也就是说终结符不能再进⾏推导。

⾮终结符:不是终结符的都是⾮终结符。

如:A->B,则A是⾮终结符;A->id,则id是终结符。

(⼀般书上终结符⽤⼩写,⾮终结符⽤⼤写。

)⽂法产⽣语⾔句⼦的基本思想:从识别符号(开始符)开始,把当前产⽣的符号串中的⾮终结符替换为相应规则右部的符号串,直到全部由终结符组成。

所以⽂法产⽣句⼦的基本思想就是基于产⽣式(例如A->num)的替换,当所有的⾮终结符都被终结符替换时,推导结束。

FIRST集求法:我对First集的理解:first集应该就是求⼀个表⽰⽂法的字串(⼀般指⾮终结符,终结符的first集就是它⾃⾝)开头的所有可能出现的字符的集合。

例如A->aC | bB | cD,根据这个产⽣式,就可以知道,⾮终结符A,被替换后,它开头可能出现字符有a、b 、c, 所以 {a,b,c}是First(A)的⼀个⼦集。

求First集的步骤:1. 若X->a..,则将终结符a加⼊FIRST(X)中;(注意⾮终结符的情况)2. 若X->e ,则将终结符e加⼊FIRST(X)中(e表⽰空集);3. 若 X->BC..D,则将First(B)所有元素(除了空集)加⼊First(A),然后检测First(B),若First(B)中不存在空集, 即e,则停⽌,若存在则向B的后⾯查看,将First(C)中所有元素(除了空集)加⼊First(A),然后再检测First(C)中是否有e...直到最后,若D之前的所有⾮终结符的First集中都含有e,则检测到D时,将First(D)也加⼊First(A),若First(D)中含有e,则将 e加⼊First(A)。

对于第三条,其实也很好理解,就是说当X推导出⼀个字串时,D前⾯的⾮终结符都可能推出空串,这个时候,X推出的串的⾸部,就不是那些推出空串的⾮终结符了,⽽是这些推出空串的⾮终结符后⾯的⽂法符号所推导出的字串。

编译原理(求First集)

编译原理(求First集)

4、运行结果分析 5、总结
2、分析、设计、实现 通过对产生式的顺序扫描,运用上述规则,把每种规则都转换为相应的算法,经过规则后 将产生的 First 集存下来。 流程图 3、函数与过程的功能(MFC) CString CFirstAndFollow::First(char Vn,char PVn) { CString result,tmpresult; char tmpmid; int tmpflag; if(Vns.Find(Vn,0)==-1&&Vn!=';'&&Vn!='|') { result.Insert(result.GetLength(),Vn); return result; } for(int ix=0;ix<Vpro.GetLength();ix++) { ix=Vpro.Find(Vn,ix); if(Vpro.GetAt(ix-1)==';') { tmpflag=ix; break; } } tmpflag+=3; for(ቤተ መጻሕፍቲ ባይዱnt index=tmpflag;index<Vpro.GetLength();index++) { char tmp=Vpro.GetAt(index); tmpmid=tmp; if(Vns.Find(tmp,0)>=0) // Vn { if(tmp==PVn || tmp==Vn) { do
1、问题描述
题目: First 集和 Follow 集生成算法模拟 设计一个由正规文法生成 First 集和 Follow 集并进行简化的算法动态模拟。 动态模拟算法的基本功能是: ⅰ. 输入一个文法 G; ⅱ. 输出由文法 G 构造 FIRST 集的算法; ⅲ. 输出 First 集; ⅳ. 输出由文法 G 构造 FOLLOW 集的算法; ⅴ. 输出 FOLLOW 集。

编译原理词法分析,语法分析实验报告

编译原理词法分析,语法分析实验报告

char left[50];
/* 左部 */
char right[50][50];
/* 右部 */
char first[50][50],follow[50][50];
/* 各产生式右部的 FIRST 和左部的 FOLLOW 集合 */
char first1[50][50];
/* 所有单个符号的 FIRST 集合 */
int i,j,k,result=1,mark=0;
char temp[20];
temp[0]=c;
temp[1]='\0';
merge(empt,temp,1);
if(in(c,empty)==1)
return(1);
for(i=0;;i++)
{
if(i==count)
return(0);
if(left[i]==c)
}
/*******************************************
将单个符号或符号串并入另一符号串 ********************************************/
void merge(char *d,char *s,int type)
{
/*d 是目标符号串, s 是源串, type=1,源串中的‘ ^ ’一并并入目串;
int count=0;
/* 分解的产生式的个数 */
int number;
/* 所有终结符和非终结符的总数 */
char start;
/* 开始符号 */
char termin[50];
/* 终结符号 */
char non_ter[50];

编译原理实验报告一_计算机15班 西安交通大学

编译原理实验报告一_计算机15班 西安交通大学

实验报告实验课程:编译原理学生姓名:高君宇学号:2110505112专业班级:计算机15班2013年11月25日一、题目描述M=128=27,二、算法描述1、输入产生式;2、构造数组储存VT符号、VN符号、产生式右部符号;3、用结构体MAP存储预测分析表;4、构造Select集,Select集的作用是将first集和follow集进行合并,如果两个文法的左端都是A,若他们的select集交集为空,表明他们是两个无关的,不会产生不确定性的文法,反之,则表明文法不是LL(1)文法,这里假定在(1)、(2)问的条件下,已经知道了First集合Follow集;5、根据Select集产生预测分析表;6、实现函数char * Analyse (char* word) , 用于递归分析:6.1 把’#’压入栈stak;6.2 把第一个输入符号读进字符变量word[k];6.3 循环做{读栈顶符号p;若p是终结符则作判断p = work[k]?;若等于则读进下一符号work[k+1]否则错误;若不是,且p = ‘#’若p = work[k] 则退出循环;否则错误;若不是,且有MAP[A,p]则把MAP[A,p]反向推入栈中;否则错误;}7、输出结果。

三、程序源代码#include <iostream>#include <cstdio>#include <stack>#include<string>using namespace std;struct Node1{ char vn;char vt;char s[15];}MAP[20];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;//用R代表E',W代表T',e代表空M代表F'char start='E';int len=13;charG[13][15]={"E->TR","R->+E","R->e","T->FW","W->T","W->e","F->PM","M->*M","M->e","P->(E)","P->a","P->b","P->^"};//存储文法中的产生式char VN[7]={'E','R','T','W','F','M','P'};//存储非终结符char VT[8]={'a','b','+','*','(',')','#','^'};//存储终结符charSELECT[13][15]={"(,a,b,^","+","),#","(,a,b,^","(,a,b,^","+,),#","a,b,^","*","(,a,b,^,+,),#","(","a","b ","^"};//存储文法中每个产生式对应的SELECT集charRight[13][15]={"->TR","->+E","->e","->FW","->T","e","->PM","->*M","->e","->(E)","->a","-> b","->^"};bool compare(char *a,char *b){ int i,la=strlen(a),j,lb=strlen(b);for(i=0;i<la;i = i+2 )for(j=0;j<lb;j++){ if(a[i]==b[j])return 1;}return 0;}char *Find(char vn,char vt){ int i;for(i=0;i<k;i++){if(MAP[i].vn==vn && MAP[i].vt==vt)return MAP[i].s;}return "error";}char * Analyse(char* word){cout<<word;stack <char> stak;char p,action[20],output[20];int i=1,j,l=strlen(word),k=0,l_act,m;while(!stak.empty())stak.pop();stak.push('#');stak.push(start);printf("___________________________________________________________\n");printf("\n 对符号串%s的分析过程\n",word);printf(" -----------------------------------------------------------------------\n");printf("\n");printf(" 步骤栈顶元素剩余输入串动作\n");printf(" -----------------------------------------------------------------------\n");p=stak.top();while(p!='#'){ printf("%7d ",i++);p=stak.top();stak.pop();printf("%6c ",p);for(j=k,m=0;j<l;j++)output[m++]=word[j];output[m]='\0';printf("%10s",output);if(p==word[k]){if(p=='#'){printf(" 分析成功\n");return "SUCCESS";}printf(" 匹配终结符%c\n",p);k++;}else{ strcpy(action,Find(p,word[k]));if(strcmp(action,"error")==0){ printf(" 没有可用的产生式\n");return "ERROR";}printf(" 展开非终结符%c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}}if(strcmp(output,"#")!=0)return "ERROR";}int main (){char *source;int i,j,flag,l,m;printf("\n****为了方便编写程序,用R代表E',W代表T',M代表F',e代表空*****\n\n");printf("该文法的产生式如下:\n");for(i=0;i<len;i++)printf(" %s\n",G[i]);printf("___________________________________________________________\n");printf("\n该文法的SELECT集如下:\n");for(i=0;i<len;i++){printf(" SELECT(%s) = { %s }\n",G[i],SELECT[i]);}printf("___________________________________________________________\n");//判断是否是LL(1)文法flag=1;for(i=0;i<13;i++){for(j=i+1;j<13;j++){if(G[i][0]==G[j][0]){if(compare(SELECT[i],SELECT[j])){flag=0;break;}}} if(j!=13)break;}if(flag)printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。

求解FOLLOW集的方法

求解FOLLOW集的方法

求解FOLLOW集的方法刚刚学习FOLLOW集时总是容易忽略一些条件而造成错误,学会FOLLOW集的求解对于编译原理的学习很重要,一旦求错就容易造成分析SLR(1)分析表时出现错误。

1、对文法中的每个A属于V n,计算FOLLOW(A):(1)、对文法的开始符号S,将“$”加到FOLLOW(S)中;(2)、若A->aBb是一条规则,则把FIRST(b)中的非ε元素加到FOLLOW(B)中;(3)、若A->aB或A->aBb是一条规则且b=>ε,则把FOLLOW(A)加到FOLLOW(B)中;(4)、反复使用(2)、(3),直到每个非终结符的FOLLOW集不再增大为止。

看完规则,难免觉得有些许枯燥,下面我将列举一个较复杂的例子,可以使用到上述的全部规则。

eg: 设有文法G[A]:A→BCc | gDB B→bCDE |ε C→DaB | ca D→dD |ε E→gAf | c计算该文法的每一个非终结符的FIRST集和FOLLOW集。

解:(1)、FIRST集的求解:FIRST(A) = FIRST(BCc) ∪ FIRST(gDB)= FIRST(B) ∪ FIRST(C) ∪ {c} ∪ {g}= {b} ∪ FIRST(D) ∪ {a} ∪ {c,,g}= {a,b,c,d,g}同理:FIRST(B) = {b,ε} FIRST(C) = {a,c,d}FIRST(D) = {d,ε} FIRST(E) = {g,c}(2)、接下来求解FOLLOW集:a、由于A是文法的开始符号,所以$属于FOLLOW(A),由E→gAf | c l利用规则(2)可知f属于FOLLOW(A),所以FOLLOW(A)={f,$}b、由A→BCc利用规则(2)把FIRST(C)中的非ε元素加到FOLLOW(B)中,利用规则(3)把FOLLOW(A)加到FOLLOW(B)中;所以a,c,d,f,$属于FOLLOW(B).此外,由A→gDB ,C→DaB利用规则(3)把FOLLOW(A),FOLLOW(C)加到FOLLOW(B)中,由于还没求FOLLOW(C),暂不求FOLLOW(B).c、由A→BCc利用规则(2)把FIRST(c)加入FOLLOW(C),则c属于FOLLOW(C), 由B→bCDE利用规则(2)将FIRST(D)中的非ε元素加入FOLLOW(C),则d属于FOLLOW(C),当FIRST(D)的元素为ε时,紧跟随在C后面的是E,所以FIRST(E)的非ε元素也应计入FOLLOW(C)中,则g也属于FOLLOW(C),所以FOLLOW(C)={c,d,g}由此可求得FOLLOW(B)={a,c,d,f,g,$}d、由A→gDB 利用规则(2)把FIRST(B)中的非ε元素加到FOLLOW(D)中,则b属于FOLLOW(D)。

哈工程编译原理实验报告 语法分析

哈工程编译原理实验报告 语法分析
n = 0;
/*初始化数组*/
while(n < MaxVnNum)
{
Vn[n++] = '\0';
}
n = 0;
while(('#' != ch) && (n < MaxVnNum))
{
if(' ' != ch && '\n' != ch && -1 == IndexCh(ch))
{
Vn[n++] = ch;
{
printf("\n是否继续进行句型分析?(y / n):");
todo = getchar();
while('y' != todo && 'n' != todo)
{
printf("\n(y / n)? ");
todo = getchar();
}
if('y' == todo)
{
int i;
InitStack();
void First(int U);
void AddFirst(int U, int nCh); /*加入first集*/
bool HaveEmpty(int nVn);
void Follow(int V);/*计算follow集*/
void AddFollow(int V, int nCh, int kind);
当一个文法中存在ε产生式时,例如,存在A→ε,只有知道哪些符号可以合法地出现在非终结符A之后,才能知道是否选择A→ε产生式。这些合法地出现在非终结符A之后的符号组成的集合被称为FOLLOW集合。下面我们给出文法的FOLLOW集的定义。

编译原理:FIRST(x)FOLLOW(x)SELECT(x)的计算

编译原理:FIRST(x)FOLLOW(x)SELECT(x)的计算

编译原理:FIRST(x)FOLLOW(x)SELECT(x)的计算⽬录已知⽂法G[S]:S→MH|aH→LSo|εK→dML|εL→eHfM→K|bLM判断G是否是LL(1)⽂法。

First计算First集合的定义就是某个⾮终结符表达式可以推导出来的第⼀个字符可以是什么⽐如表达式S --> abb,它的First(S)={a}First(S)={a}+First(M)+First(H)+{ε}={a,b,d,e,ε}# S表达式存在单个的终结符a,添加{a}# S表达式以M开头,添加First(M)# 根据后⾯的表达式判断,M可以推出K,K可以推出空,所以M可以为空,此时S以H开头,添加First(H)# 由于H也可以推出空,所以S最终也会指向空,添加空集First(M)={b}+First(K)+{ε}={b,d,ε}# M表达式以终结符b开头,添加{b}# M表达式可以推导出单个的K表达式,所以添加First(K)# K有可能推导出空集,即M可以推导出空,所以添加空集First(K)={d}+{ε}={d,ε}# K可以以终结符d开头,添加{d}# K可以推导出空,添加空集First(H)=First(L)+{ε}={e,ε}# H可以推导出以L开头的表达式,所以添加First(L)# H可以推导出空,所以添加空集First(L)={e}# L只能推导出⼀个表达式,并且开头是终结符,所以添加{e}## 最后将已知的表达式代⼊到未知的表达式当中去,即可求出全部First集合Follow计算Follow表⽰某个⾮终结符后⾯可以跟着什么样的字符Follow集不存在空集为表达式编号1: S→MH|a2: H→LSo|ε3: K→dML|ε4: L→eHf5: M→K|bLMFollow(S)={$}+{o}={o,$}# 在表达式1中,S是⼀个⾮终结符,S是孤⽴的⼀个表达式,其Follow可以添加$,即添加{$}# 在表达式2中,S后⾯跟上了o,所以添加{o}Follow(H)=Follow(S)+{f}={f,o,$}# 在表达式1中,S后⾯跟了什么,MH后⾯就跟了什么,所以添加Follow(S)# 在表达式4中,H后⾯跟了f,所以添加{f}Follow(M)=First(H)+Follow(S)+First(L)={e,o,$}# 在表达式1中,M后⾯跟了H,所以添加First(H)# 在表达式2中可知,H可以推导出空,所以回到表达式1,S后⾯跟了什么,M后⾯就跟了什么,所以添加Follow(S)# 在表达式3中,M后⾯跟了⾮终结符L,所以添加First(L)# 在表达式5中,M后⾯跟了什么,bLM后⾯就跟什么,都是Follow(M),表达式不变Follow(L)=First(S)+Follow(K)+{o}+{$}+First(M)+Follow(M)={a,b,d,e,o,$}# 在表达式2中,L后⾯跟了⾮终结符S,所以添加First(S)# 在表达式2中,First(S)可以推出空,所以此时L后⾯跟着o,添加{o}# 在表达式3中,K后⾯跟了什么,dML后⾯就跟了什么,所以添加Follow(K)# 在表达式4中,L属于单⼀元素,所以添加$# 在表达式5中,L后⾯跟上了⾮终结符M,所以添加First(M)# 在表达式5中,从上得知,First(M)可以推导出空,所以此时M后⾯跟着什么,L后⾯就要跟着什么,所以添加Follow(M) Follow(K)={$}+Follow(M)={e,o,$}# 在表达式3中,K是单⼀字符,添加{$}# 在表达式5中,M后⾯跟着什么,K后⾯就跟着什么,所以添加Follow(M)注意:在书写Follow集中要时刻检查First集是否可以为空.Select计算分割表达式,如果⾮空则是First集,是空则为Follow集Select(S→MH)=First(M)+First(H)+Follow(S)={b,d,e,o,$}# S以M开头,加⼊First(M)# First(M)可以为空,加⼊First(H)# M和H都可以为空,加⼊Follow(S)Select(S→a)={a}# S只能推导出a,加⼊{a}Select(H→LSo)=First(L)={e}# H以L开头,并且First(L)不可以为空,即加⼊First(L)Select(H→ε)=Follow(H)={f,o,$}# H推导出空,加⼊Follow(H)Select(K→dML)={d}# K以终结符d开头,加⼊{d}Select(K→ε)=Follow(K)={e,o,$}# K可以为空,加⼊Follow(K)Select(L→eHf)={e}# L以终结符e开头,加⼊{e}Select(M→K)=First(K)+Follow(M)={d,e,o,$}# M可以推出K,加⼊First(K)# First(K)可以为空,即M可以加⼊Follow(M)Select(M→bLM)={b}# M可以推出以终结符b开头,加⼊{b}判断是否是LL(1)⽂法LL(1)⽂法就是同⼀⾮终结符推出来的Select集合相交为空,现在开始逐⼀判断Select(S→MH)∩Select(S→a)Select(H→LSo)∩Select(H→ε)Select(K→dML)∩Select(K→ε)# L只有⼀个表达式,省略LSelect(M→K)∩Select(M→bLM)易知,上述表达式都为空,所以这个表达式是LL(1)⽂法预测分析表的书写先列出First集和Follow集的表格First FollowS{a,d,b,e, ε}{$,o}H{e,ε}{f,o,$}K{d,ε}{e,o,$}L{e}{a,b,d,e,o,$}M{b,d,ε}{e,o,$}然后将⾮终结符、终结符作为横纵⾏,填⼊表达式。

LL1语法分析,first集,follow集,分析表Java实现

LL1语法分析,first集,follow集,分析表Java实现

import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.sql.*;import java.util.Vector;public class LL1 extends JFrame implements ActionListener { /****/private static final long serialVersionUID = 1L;JTextField tf1;JTextField tf2;JLabel l;JButton b0;JPanel p1, p2, p3;JTextArea t1, t2, t3;JButton b1, b2, b3;JLabel l0, l1, l2, l3, l4;JTable table;Statement sta;Connection conn;ResultSet rs;DefaultTableModel dtm;String Vn[] = null;Vector<String> P = null;int firstComplete[] = null;// 存储已判断过first的数据char first[][] = null;// 存储最后first结果int followComplete[] = null;// 存储已判断过follow的数据char follow[][] = null;// 存储最后follow结果char select[][] = null;// 存储最后select结果int LL = 0;// 标记是否为LL(1)String vt_tou[] = null;// 储存VtObject shuju[][] = null;// 存储表达式数据char yn_null[] = null;// 存储能否推出空LL1() {setLocation(100, 0);setSize(700, 780);tf1 = new JTextField(13);tf2 = new JTextField(13);l = new JLabel(">>");l0 = new JLabel("输入字符串:");l1 = new JLabel("输入的文法为:");l2 = new JLabel(" ");l3 = new JLabel("分析的结果:");l4 = new JLabel("预测分析表:");// p1=new JPanel();p2 = new JPanel();p3 = new JPanel();t1 = new JTextArea(24, 20);t2 = new JTextArea(1, 30);t3 = new JTextArea(24, 40);b0 = new JButton("确定(S为开始)");b1 = new JButton(" 判断文法 ");b2 = new JButton("输入");b3 = new JButton("清空");table = new JTable();JScrollPane jp1 = new JScrollPane(t1);JScrollPane jp2 = new JScrollPane(t2);JScrollPane jp3 = new JScrollPane(t3);p2.add(tf1);p2.add(l);p2.add(tf2);p2.add(b0);p2.add(b1);p2.add(l0);p2.add(l2);p2.add(jp2);p2.add(b2);p2.add(b3);p2.add(l1);p2.add(l3);p2.add(jp1);p2.add(jp3);p3.add(l4);p3.add(new JScrollPane(table));add(p2, "Center");add(p3, "South");b0.addActionListener(this);b1.addActionListener(this);b2.addActionListener(this);b3.addActionListener(this);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);table.setPreferredScrollableViewportSize(new Dimension(660, 200));setVisible(true);}////////////////////界面设计public void actionPerformed(ActionEvent e) {if (e.getSource() == b0) {String a = tf1.getText();String b = tf2.getText();t1.append(a + '→' + b + '\n');}if (e.getSource() == b1) {t3.setText("");int Vnnum = 0, k;Vn = new String[100];P = new Vector<String>();String s[] = t1.getText().split("\n");for (int i = 0; i < s.length; i++) {if (s.length < 2) {t3.setText("文法输入有误,请重新输入");// 判断长度是否符合return;}if (s[i].charAt(0) <= 'Z' && s[i].charAt(0) >= 'A'&& s[i].charAt(1) == '→') {for (k = 0; k < Vnnum; k++) {if (Vn[k].equals(s[i].substring(0, 1))) {break;}}if (Vnnum == 0 || k >= Vnnum) {Vn[Vnnum] = s[i].substring(0, 1);// 存入Vn数据Vnnum++;}P.add(s[i]);} else {t3.setText("文法输入有误,请重新输入");return;}}yn_null = new char[100];first = new char[Vnnum][100];int flag = 0;String firstVn[] = null;firstComplete = new int[Vnnum];for (int i = 0; Vn[i] != null; i++) // 依次求 FIRST**{flag = 0;firstVn = new String[20];if ((flag = add_First(first[i], Vn[i], firstVn, flag)) == -1) return;firstComplete[i] = 1;}t3.append("first集:" + "\n"); // 显示FIRST**for (int i = 0; Vn[i] != null; i++) {t3.append("first(" + Vn[i] + ")={ ");for (int j = 0; first[i][j] != '\0'; j++) {t3.append(first[i][j] + " , ");}t3.append("}" + "\n");}follow = new char[Vnnum][100];String followVn[] = null;followComplete = new int[Vnnum];for (int i = 0; Vn[i] != null; i++) // 求FOLLOW**{flag = 0;followVn = new String[20];if(i==0){}else if ((flag = tianjiaFollow(follow[i], Vn[i], followVn, flag)) == -1)return;followComplete[i] = 1;}t3.append("follow集:" + "\n"); // 显示FOLLOW**for (int i = 0; Vn[i] != null; i++) {t3.append("follow(" + Vn[i] + ")={ ");for (int j = 0; follow[i][j] != '\0'; j++) {t3.append(follow[i][j] + " , ");}t3.append("}" + "\n");}select = new char[P.size()][100];for (int i = 0; i < P.size(); i++) // 求SELECT**{flag = 0;tianjiaSelect(select[i], (String) P.elementAt(i), flag);}t3.append("select集:" + "\n"); // 显示SELECT**for (int i = 0; i < P.size(); i++) {t3.append("select(" + (String) P.elementAt(i) + ")={ ");for (int j = 0; select[i][j] != '\0'; j++) {t3.append(select[i][j] + " , ");}t3.append("}" + "\n");}for (int i = 0; Vn[i] != null; i++)// 判断select交集是否为空{int biaozhi = 0;char save[] = new char[100];for (int j = 0; j < P.size(); j++) {String t = (String) P.elementAt(j);if (t.substring(0, 1).equals(Vn[i])) {for (k = 0; select[j][k] != '\0'; k++) {if (puanduanChar(save, select[j][k])) {save[biaozhi] = select[j][k];biaozhi++;} else// 当有交集时,不为LL(1)文法{t3.append("不是LL(1)文法!!" + "\n");return;}}}}}char Vt[] = new char[100];int biaozhi = 0;for (int i = 0; i < P.size(); i++) {String t = (String) P.elementAt(i);for (int j = 2; j < t.length(); j++)// 提取表达式右侧的终结符存入Vt{if (t.charAt(j) > 'Z' || t.charAt(j) < 'A') {if (puanduanChar(Vt, t.charAt(j))) {Vt[biaozhi] = t.charAt(j);biaozhi++;}}}}if (puanduanChar(Vt, '#'))// 若可推出空集,则将#加入Vt。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理实验报告 实验名称 计算first集合和follow集合 实验时间 院系 计算机科学与技术 班级 软件工程1班 学号 姓名 1. 实验目的 输入:任意的上下文无关文法。 输出:所输入的上下文无关文法一切非终结符的first集合和follow集合。 2. 实验原理 设文法G[S]=(VN,VT,P,S),则首字符集为:

FIRST(α)={a|α*aβ,a∈VT,α,β∈VG}。 若α*ε,ε∈FIRST(α)。

由定义可以看出,FIRST(α)是指符号串α能够推导出的所有符号串中处于串首的终结符号组成的集合。所以FIRST集也称为首符号集。 设α=G1G2…Gn,FIRST(α)可按下列方法求得: 令FIRST(α)=Φ,i=1; (1) 若Gi∈VT,则Gi∈FIRST(α); (2) 若Gi∈VN; ①若εFIRST(Gi),则FIRST(Gi)∈FIRST(α); ②若ε∈FIRST(Gi),则FIRST(Gi)-{ε}∈FIRST(α); (3) i=i+1,重复(1)、(2),直到Gi∈VT,(i=2,3,…,n)或Gi

∈VN且若εFIRST(Gi)或i>n为止。

当一个文法中存在ε产生式时,例如,存在A→ε,只有知道哪些符号可以合法地出现在非终结符A之后,才能知道是否选择A→ε产生式。这些合法地出现在非终结符A之后的符号组成的集合被称为FOLLOW集合。下面我们给出文法的FOLLOW集的定义。 设文法G[S]=(VN,VT,P,S),则 FOLLOW(A)={a|S…Aa…,a∈VT}。

若S*…A,#∈FOLLOW(A)。

由定义可以看出,FOLLOW(A)是指在文法G[S]的所有句型中,紧跟在非终结符A后的终结符号的集合。 FOLLOW集可按下列方法求得: (1) 对于文法G[S]的开始符号S,有#∈FOLLOW(S); (2) 若文法G[S]中有形如B→GAP的规则,其中G,P∈VG,则FIRST(P)-{ε}∈FOLLOW(A); (3) 若文法G[S]中有形如B→GA的规则,或形如B→GAP的规则且ε∈FIRST(P),其中G,P∈VG,则FOLLOW(B)∈FOLLOW(A); 3.实验内容 计算first集合和follow集合 4.实验心得

通过上机实验我对文法符号的FIRST集和FOLLOW集有了更深刻的理解,已经熟练的掌握了求解的思想和方法,同时也锻炼了自己的动手解决问题的能力,对编程能力也有所提高。 5.实验代码与结果 #include #include #include usingnamespacestd; #defineMAGS50 intNONE[MAGS]={0}; stringstrings;//产生式 stringVn;//非终结符 stringVt;//终结符 stringfirst[MAGS];//用于存放每个终结符的first集 stringFirst[MAGS];//用于存放每个非终结符的first集 stringFollow[MAGS];//用于存放每个非终结符的follow集 intN;//产生式个数 structSTR { stringleft; stringright; }; //求VN和VT voidVNVT(STRGp) { inti,j; for(i=0;i{ for(j=0;j<(int)p[i].left.length();j++) { if((p[i].left[j]>='A'&&p[i].left[j]<='Z')) { if(Vn.find(p[i].left[j])>100) Vn+=p[i].left[j]; } else { if(Vt.find(p[i].left[j])>100) Vt+=p[i].left[j]; } } for(j=0;j<(int)p[i].right.length();j++) { if(!(p[i].right[j]>='A'&&p[i].right[j]<='Z')) { if(Vt.find(p[i].right[j])>100) Vt+=p[i].right[j]; } else { if(Vn.find(p[i].right[j])>100) Vn+=p[i].right[j]; } } } } voidgetlr(STRGp,inti) { intj; for(j=0;j{ if(strings[j]=='-'&&strings[j+1]=='>') { p[i].left=strings.substr(0,j); p[i].right=strings.substr(j+2,strings.length()-j); } } } //对每个文法符号求first集 stringLetter_First(STRGp,charch) { intt; if(!(Vt.find(ch)>100)) { first[Vt.find(ch)]="ch"; returnfirst[Vt.find(ch)-1]; } if(!(Vn.find(ch)>100)) { for(inti=0;i{ if(p[i].left[0]==ch) { if(!(Vt.find(p[i].right[0])>100)) { if(First[Vn.find(ch)].find(p[i].right[0])>100) { First[Vn.find(ch)]+=p[i].right[0]; } } if(p[i].right[0]=='G') { if(First[Vn.find(ch)].find('G')>100) { First[Vn.find(ch)]+='G'; } } if(!(Vn.find(p[i].right[0])>100)) { if(p[i].right.length()==1) { stringff; ff=Letter_First(p,p[i].right[0]); for(inti_i=0;i_i{ if(First[Vn.find(ch)].find(ff[i_i])>100) { First[Vn.find(ch)]+=ff[i_i]; } } } else { for(intj=0;j{ stringTT; TT=Letter_First(p,p[i].right[j]); if(!(TT.find('G')>100)&&(j+1){ sort(TT.begin(),TT.end()); stringtt; for(intt=1;t{ tt+=TT[t]; } TT=tt; tt=""; for(t=0;t{ if(First[Vn.find(ch)].find(TT[t])>100) { First[Vn.find(ch)]+=TT[t]; } } } else { for(t=0;t{ if(First[Vn.find(ch)].find(TT[t])>100) { First[Vn.find(ch)]+=TT[t]; } } break; } } }

} } } returnFirst[Vn.find(ch)]; } } //求每个非终结符的Follow集 stringLetter_Follow(STRGp,charch) { intt,k; NONE[Vn.find(ch)]++; if(NONE[Vn.find(ch)]==2) { NONE[Vn.find(ch)]=0; returnFollow[Vn.find(ch)]; } for(inti=0;i{ for(intj=0;j{ if(p[i].right[j]==ch) { if(j+1==p[i].right.length()) { stringgg; gg=Letter_Follow(p,p[i].left[0]); NONE[Vn.find(p[i].left[0])]=0; for(intk=0;k{ if(Follow[Vn.find(ch)].find(gg[k])>100) { Follow[Vn.find(ch)]+=gg[k]; } } } else { stringFF; for(intjj=j+1;jj{ stringTT; TT=Letter_First(p,p[i].right[jj]); if(!(TT.find('G')>100)&&(jj+1){ sort(TT.begin(),TT.end()); stringtt; for(intt=1;t{ tt+=TT[t]; } TT=tt; tt=""; for(t=0;t{ if(FF.find(TT[t])>100&&TT[t]!='G') { FF+=TT[t]; } } } else { for(t=0;t{ if(FF.find(TT[t])>100) { FF+=TT[t]; } } break; } }

相关文档
最新文档