精华内容
下载资源
问答
  • 输入任意的上下文无关文法,输出所输入的上下文无关文法一切非终结符的first集合和follow集合 输入任意的上下文无关文法,输出所输入的上下文无关文法一切非终结符的first集合和follow集合
  • 代码链接:https://pan.baidu.com/s/1VNdrSMXaKu3HI0UQ_TInUQ 提取码:b1qz 使用教程 解压后打开文件夹,直接用Dev c++运行LL1,如图: 即可实现。 一分钱都不要啊, 比那些要C币的都好,点个赞呗亲们!!! ...

    DEV C++ 项目实现 不会建项目的看这个——>如何创建项目


    代码链接:https://pan.baidu.com/s/1VNdrSMXaKu3HI0UQ_TInUQ

    提取码:b1qz


    使用教程

    解压后打开文件夹,直接用Dev c++运行LL1,如图:
    在这里插入图片描述

    即可实现。


    一分钱都不要呀, 比需要C币下载的资源都好,点个赞呗!

    展开全文
  • 给定文法,构造FIRST集FOLLOW集的构造的C代码和我个人的实验报告
  • 编译原理------C++实现求First集和Follow集

    千次阅读 多人点赞 2019-12-06 20:39:54
    First集算法描述 1.若X->a…,则将终结符a放入First(X)中 2.若X->ε,则将ε放入First(X)中 3.若有X->Y1Y2Y3…Yk,则 (1)把First(Y1)去掉 ε后加入First(X) (2)如果First(Y1)包含ε,则...

    First集算法描述

    1.若X->a…,则将终结符a放入First(X)中
    2.若X->ε,则将ε放入First(X)中
    3.若有X->Y1Y2Y3…Yk,则
    (1)把First(Y1)去掉 ε后加入First(X)
    (2)如果First(Y1)包含ε,则把First(Y2)也加入到First(X)中,以此类推,直到某一个非终结符Yn的First集中不包含ε
    (3)如果First(Yk)中包含ε,即Y1~Yn都有ε产生式,就把ε加入到First(X)中

    Follow集算法描述

    1.对于文法开始符号S,把$加入到Follow(S)中
    2.若有A->aBC,则将First(C)中除了ε之外的元素加入到Follow(B)(此处a可以为空)
    3.若有A->aB或者A->aBC且ε属于first(C),则将Follow(A)加入到follow(B)中(此处a可以为空)
    4.若有A->Bc,则直接将c加入follow(B)中
    follow集中不含有空串ε

    代码

    代码说明

    1.原产生式存于文件中
    2.终结符只能用一个小写字母表示
    3.产生式内不可以有空格
    4.ε用#代替
    5.代码没有实现消除左递归和二义性,所以产生式必须为消除左递归和二义性的
    6.暂时看来代码没什么问题(可以准确求出first集和follow集),有问题请指正。

    #include<iostream>
    #include<string>
    #include<set>
    #include<map>
    #include <Windows.h>
    #include <fstream>
    
    using namespace std;
    
    /*
    所有非终结符均为单个字符,#代表空串
    E->TE'
    E'->+TE'|#
    T->FT'
    T'->*FT'|#
    F->(E)|i
    */
    
    class FF {
    public:
    	string fileName = "productions.txt";
    	set<string> productions;//产生式集合
    	map<string, set<string>> split_productions;//分解后的产生式集合
    	set<string> Vt;//终结符集合
    	set<string> Vn;//非终结符集合
    	map<string, set<string>> first;//First集
    	map<string, set<string>> follow;//Follow集
    
    	void init();//从文件读取产生式
    	void splitProductions();//分解产生式
    	void findVtAndVn();//获得终结符和非终结符
    	bool isVn(string s);
    	bool isVt(string s);
    	set<string> getOneFirst(string s);//获得单个非终结符first集
    	void getFirst();//获得所有非终结符first集
    	void getFollow();//获得所有非终结符follow集
    	void SSS();//求folloe集的步骤3
    };
    
    void FF::init() {
    	string line;
    	ifstream in(fileName);
    	if (in) {
    		//文法开始符号的follow集中放入$
    		getline(in, line);
    		productions.insert(line);
    		follow[line.substr(0, 1)].insert("$");
    		cout << line << endl;
    		while (getline(in, line)) {
    			productions.insert(line);
    			cout << line << endl;
    		}
    	}
    }
    void FF::splitProductions() {
    	int position = 0;
    	for (set<string>::iterator it = productions.begin(); it != productions.end(); it++) {
    		string temp = *it;
    		for (int i = 0; i < temp.length(); i++) {
    			position = temp.find("->");
    			string s = temp.substr(0, position);
    			string ss = temp.substr(position + 2);
    			set<string>sss;
    			string t;
    			for (int j = 0; j < ss.length(); j++) {
    				if (ss[j] == '|') {
    					sss.insert(t);
    					t = "";
    				}
    				else
    				{
    					t.append(ss.substr(j,1));
    				}
    				
    			}
    			sss.insert(t);
    			split_productions.insert(pair<string, set<string>>(s, sss));
    		}
    	}
    	for (map<string, set<string>>::iterator it = split_productions.begin(); it != split_productions.end(); it++) {
    		cout << it->first << "    ";
    		for (set<string>::iterator ii = it->second.begin(); ii != it->second.end(); ii++) {
    			cout << *ii << "    ";
    		}
    		cout << endl;
    	}
    
    
    }
    void FF::findVtAndVn() {
    	for (set<string>::iterator it = productions.begin(); it != productions.end(); it++) {
    		string temp = *it;
    		for (int i = 0; i < temp.length(); i++) {
    			if (temp[i] == '-' || temp[i] == '>' || temp[i] == '|')
    				continue;
    			//是大写字母
    			if (temp[i] >= 'A' && temp[i] <= 'Z') {
    				//后面带'
    				if (temp[i + 1] == '\'') {
    					Vn.insert(temp.substr(i, 2));
    					i++;
    				}
    				else {
    					Vn.insert(temp.substr(i, 1));
    				}
    			}
    			//是终结符
    			else
    			{
    				Vt.insert(temp.substr(i, 1));
    			}
    		}
    	}
    
    	cout << "非终结符" << endl;
    	for (set<string>::iterator it = Vn.begin(); it != Vn.end(); it++) {
    		cout << *it << endl;
    	}
    
    	cout << "终结符" << endl;
    	for (set<string>::iterator it = Vt.begin(); it != Vt.end(); it++) {
    		cout << *it << endl;
    	}
    }
    bool FF::isVn(string s) {
    	if (Vn.find(s) != Vn.end()) {
    		return true;
    	}
    	return false;
    }
    bool FF::isVt(string s) {
    	if (Vt.find(s) != Vt.end()) {
    		return true;
    	}
    	return false;
    }
    set<string> FF::getOneFirst(string s) {
    	if (split_productions.count(s)>0) {
    		set<string>temp = split_productions[s];
    		for (set<string>::iterator it = temp.begin(); it != temp.end(); it++) {
    			string stemp = *it;
    			if (stemp == "#") {
    				first[s].insert("#");
    			}
    			else {
    				int flagAll = 0;//所有的非终结符的first集都有#;
    				for (int i = 0; i < stemp.length(); i++) {
    					int flag = 0;//当前的非终结符的first集有#;
    					if (stemp[i+1] == '\'') {//带'的非终结符
    						set<string>t1 = getOneFirst(stemp.substr(i, 2));
    						for (set<string>::iterator ii = t1.begin(); ii !=  t1.end(); ii++) {
    							if (*ii == "#") {//此时空串不可插入
    								flag = 1;
    							}
    							else {
    								first[s].insert(*ii);
    							}
    						}
    						i++;
    					}
    					else if(isVn(stemp.substr(i,1)))//单个非终结符
    					{
    						set<string>t2 = getOneFirst(stemp.substr(i, 1));
    						for (set<string>::iterator ii = t2.begin(); ii != t2.end(); ii++) {
    							if (*ii == "#") {//此时空串不可插入
    								flag = 1;
    							}
    							else {
    								first[s].insert(*ii);
    							}
    						}
    					}
    					else {//终结符
    						first[s].insert(stemp.substr(i, 1));
    					}
    					if (i == stemp.length() - 1 && flag==1) {
    						flagAll = 1;
    					}
    					if (flag == 0)
    						break;
    
    				}
    				if (flagAll == 1) {
    					first[s].insert("#");
    				}
    			}
    		}
    	}
    	return first[s];
    }
    void FF::getFirst() {
    	for (map<string, set<string>>::iterator it = split_productions.begin(); it != split_productions.end(); it++) {
    		getOneFirst(it->first);
    	}
    	cout << "First集" << endl;
    	for (map<string, set<string>>::iterator it = first.begin(); it != first.end(); it++) {
    		cout << it->first << "  :  "  ;
    		for (set<string>::iterator ii = it->second.begin(); ii != it->second.end(); ii++)
    		{
    			cout << *ii << "    ";
    		}
    		cout << endl;
    	}
    
    }
    void FF::getFollow() {
    	for (map<string, set<string>>::iterator it = split_productions.begin(); it != split_productions.end(); it++) {
    		string left = it->first;
    		set<string>right = it->second;
    		for (set<string>::iterator ii = right.begin(); ii != right.end(); ii++) {
    			string temp = *ii;
    			
    			for (int i = 0; i < temp.length(); i++) {
    				if (isVt(temp.substr(i, 1))) {//终结符
    					continue;
    				}
    				else if (i+1<temp.length()&&temp[i + 1] == '\'') {//带有’的非终结符
    					if (isVt(temp.substr(i + 2, 1))) {//非终结符后面是终结符
    						follow[temp.substr(i, 2)].insert(temp.substr(i + 2, 1));
    						i++;
    					}
    					else {//非终结符后面是非终结符s
    						//把后面非终结符的first集ff加入follow集中
    						string s;
    						if (i+3<temp.length()&& temp[i + 3] == '\'') {
    							s = temp.substr(i + 2, 2);
    						}
    						else {
    							s = temp.substr(i + 2, 1);
    						}
    						set<string> ff = first[s];
    						for (set<string>::iterator nn = ff.begin(); nn != ff.end(); nn++) {
    							if (*nn != "#")
    								follow[temp.substr(i, 2)].insert(*nn);
    						}
    					}
    				}
    				else {//不带’的非终结符
    					
    					if (i+1<temp.length() && isVt(temp.substr(i + 1, 1))) {//非终结符后面是终结符
    						follow[temp.substr(i, 1)].insert(temp.substr(i + 1, 1));
    						i++;
    					}
    					else {//非终结符后面是非终结符s
    						//把后面非终结符的first集ff加入follow集中
    						string s;
    						if (i+2<temp.length() && temp[i + 2] == '\'') {
    							s = temp.substr(i + 1, 2);
    						}
    						else {
    							s = temp.substr(i + 1, 1);
    						}
    						set<string> ff = first[s];
    						for (set<string>::iterator nn = ff.begin(); nn != ff.end(); nn++) {
    							if (*nn != "#")
    								follow[temp.substr(i, 1)].insert(*nn);
    						}
    					}
    				}
    			}
    		}
    	}
    	//这一个需要多进行几次,因为follow是不断增长的
    	SSS();
    	SSS();
    
    	cout << "Follow集" << endl;
    	for (map<string, set<string>>::iterator it = follow.begin(); it != follow.end(); it++) {
    		cout << it->first << "  :  ";
    		for (set<string>::iterator ii = it->second.begin(); ii != it->second.end(); ii++)
    		{
    			cout << *ii << "    ";
    		}
    		cout << endl;
    	}
    }
    void FF::SSS() {
    	for (map<string, set<string>>::iterator it = split_productions.begin(); it != split_productions.end(); it++) {
    		string left = it->first;
    		set<string>right = it->second;
    		for (set<string>::iterator ii = right.begin(); ii != right.end(); ii++) {
    			string temp = *ii;
    			for (int j = temp.length() - 1; j > 0; j--) {
    				string now;
    				if (temp[j] == '\'') {
    					now = temp.substr(j - 1, 2);
    					j--;
    				}
    				else now = temp.substr(j, 1);
    				if (isVt(now)) {//产生式最后是终结符
    					break;
    				}
    				else {//产生式最后是非终结符
    					set<string>aa = follow[left];
    					for (set<string>::iterator pp = aa.begin(); pp != aa.end(); pp++) {
    						follow[now].insert(*pp);
    					}
    				}
    				if (first[now].find("#") == first[now].end())
    					break;
    			}
    		}
    	}
    }
    int main() {
    	FF ff;
    	ff.init();
    	ff.splitProductions();
    	ff.findVtAndVn();
    	ff.getFirst();
    	ff.getFollow();
    }
    展开全文
  • ( 编译原理JAVA求First集Follow集
  • 编译原理用C语言求first集sellect集follow集,最后,判断给出的文法是否是LL(1)文
  • 编译原理:求First集和Follow集

    千次阅读 2018-10-25 22:16:04
    #输入文法求First集和Follow集 #要求大写字母表示非终结符,小写字母表示终结符 #最后一个产生式以$结尾或者输入$表示输入结束 #默认第一个产生式的→左边为起始符号 def inputGrammer(): #接收文法输入的函数 ...

    代码

    #输入文法求First集和Follow集
    #要求大写字母表示非终结符,小写字母表示终结符
    #最后一个产生式以$结尾或者输入$表示输入结束
    #默认第一个产生式的→左边为起始符号
    def inputGrammer():  #接收文法输入的函数
        grammer=[]#声明一个文法列表,用来保存该文法的各个产生式
        print('箭头请用符号→')
        print('空串请用符号ε')
        print('____________________________')
        while(True):
            production=input()
            if(production=='$'):
                break;
            elif (production[-1:] == '$'):  # 如果是最后一个产生式,把$去掉加入到文法中,并跳出循环
                grammer.append(production[:-1])
                break;
            else:
                grammer.append(production)
        return grammer
    #print('____________________________')
    def cut(grammer):#把包含选择运算符的产生式,分为两个,如把 F→(E)|id 分成 F→(E) 和 F→id ,这样之后会比较方便
        grammer1 = []
        for i in range(len(grammer)):
            s=grammer[i]
            if '|' in s:
                while True:
                    index = s.find('|')
                    grammer1.append(s[:index])
                    index2 = s.find('→')
                    s1=s[:index2 + 1] + s[index + 1:]
                    if '|' not in s1:
                        grammer1.append(s1)
                        break
                    else:
                        s=s1
            else:
                grammer1.append(grammer[i])
        return grammer1
    #print('____________________________')
    First={}#该文法的First集,以字典形式存储
    Follow={}#该文法的Follow集,以字典形式存储
    def initializeFirstAndFollow(grammer):#找到文法中的非终结符VN,并为其各自建立First集和Follow集
        VN=[]
        for i in range(len(grammer)):
            s=grammer[i]
            for j in range(len(s)):
                if(s[j]>='A' and s[j]<='Z'):
                    if(j<len(s)-1 and s[j+1]=='\''):
                        vn=s[j]+'\''
                        if vn not in VN:
                            VN.append(vn)
                    else:
                        vn = s[j] + ''
                        if vn not in VN:
                            VN.append(vn)
        global First
        global Follow
        for i in range(len(VN)):
            First[VN[i]]=[]
            Follow[VN[i]]=[]
        Follow[VN[0]].append('$')
    # print('____________________________')
    def findFirstVN(s):#找到字符串中的第一个非终结符
        length=len(s)
        for i in range(length):
            if s[i]>='A' and s[i]<='Z':
                if(i<length-1):
                    if(s[i+1]=='\''):
                        return s[i:i+2]
                    else:
                        return s[i]
                else:
                    return s[i]
        return '$'#表示该字符串中没有非终结符
    #print('____________________________')
    def findNextVN(s):#找到字符串中的第二个非终结符
        #判断一下FirstVN的位置,与len(s)比较
        length=len(s)
        vn=findFirstVN(s)
        index=s.find(vn)
        length1=len(vn)
        return findFirstVN(s[index+length1:])
    #print('____________________________')
    def findLastVN(s):#找到字符串中的最后一个非终结符
        length=len(s)
        index=0
        if s[length-1:]<'A' or s[length-1:]>'Z':
            if s[length-1:]!='\'':
                return findFirstVN(s)
        for i in range(length):
            if s[i]>='A' and s[i]<='Z':
                index=i
        if index==length-1:
            return s[index]
        else:
            if s[index+1]=='\'':
                return s[index:index+2]
            else:
                return s[index]
    #print('____________________________')
    def lookVT(grammer):#扫描文法中的每一个产生式,如果产生式右边第一个符号是终结符,则把它加到产生式左边非终结符的First集中去
        global First
        for i in range(len(grammer)):
            s = grammer[i]
            index = s.find('→')
            left = s[:index]
            right= s[index + 1:]
            if right[0]<'A' or right[0]>'Z':
                if right[0]=='i' and 'id' not in First[left]:
                    First[left].append('id')
                else:
                    if right[0] not in First[left]:
                        First[left].append(right[0])
    #print('____________________________')
    def FFirst(grammer):
        '''
            扫描文法中的每一个产生式,对于产生式右边第一个符号不是非终结符的情况,
           把右边非终结符First集中的元素加入到左边非终结符的First集中去
          如果右边非终结符的First集中包含空串ε,则应找到该非终结符之后的一个非终结符
         把这个非终结符First集中的元素加入到左边非终结符的First集中去,此次类推
         '''
        for i in range(len(grammer)):
            s = grammer[i]
            index = s.find('→')
            right = s[index + 1:]
            if right[0]<'A' or right[0]>'Z':
                continue
            vn1 = findFirstVN(s)
            vn2 = findNextVN(s)
            flag=1
            while flag==1 and '$'!=vn2:
                for ss in First[vn2]:
                    if ss not in First[vn1]:
                        First[vn1].append(ss)
                if 'ε' in First[vn2]:
                    flag=1
                    index=s.find(vn2)
                    vn2=findLastVN(s[index:])
                else:
                    flag=0
    #print('____________________________')
    def handleFirst(grammer):#求First集的函数
        lookVT(grammer)
        FFirst(grammer)
        FFirst(grammer)
    #print('____________________________')
    def scanVT(s):#扫描文法中的每一个产生式,如果箭头→右边有终结符的话,找到在它之前紧挨着它的一个非终结符,把该终结符加入到该非终结符的Follow集中去
        #print(s,"In scanVT")
        global Follow
        s1=s
        index=s1.find('→')
        s1=s1[index+1:]
        for i in range(len(s1)):
            if s1[i]<'A' or s1[i]>'Z':
                if s1[i]!='\'':
                    if i>0 and s1[i-1]=='\'':
                        vn=s1[i-2:i]
                    elif i>0:
                        vn=s1[i-1]
                    else:
                        vn='$'
                    if len(s1)==1 or s1=='id':
                        vn='$'
                    if vn!='$':
                        if s1[i] =='i' or s1[i]=='d':
                            if 'id' not in Follow[vn]:
                                Follow[vn].append('id')
                        else:
                            if s1[i] not in Follow[vn]:
                                Follow[vn].append(s1[i])
        vn1=findFirstVN(s1)
        vn2=findNextVN(s1)#产生式右边只有两个非终结符??
        if vn1!='$' and vn2!='$' and vn1+vn2 in s1:
            for si in First[vn2]:
                if si not in Follow[vn1] and si!='ε':
                    Follow[vn1].append(si)
        #print("FOllOW")
        #print(Follow)
        #print("End of FOLLOW")
    
    #print('____________________________')
    def FFollow(grammer):
        '''
              扫描文法的每一个产生式,把第一个非终结符的Follow集去除空串ε加入到最后一个非终结符的Follow集中去
             如果最后一个非终结符的First集中有空串ε,
            则把第一个非终结符的Follow集去除空串ε加入到倒数第二个非终结符的FOllow集中去,依次类推
        '''
        for i in range(len(grammer)):
            s = grammer[i]
            vn1 = findFirstVN(s)
            vn2 = findLastVN(s)
            flag=1
            while flag==1 and vn1!=vn2:
                for ss in Follow[vn1]:
                    if ss not in Follow[vn2]:
                        Follow[vn2].append(ss)
                if 'ε' in First[vn2]:
                    flag=1
                    index=s.find(vn2)
                    vn2=findLastVN(s[:index])
                else:
                    flag=0
    #print('____________________________')
    def handleFollow(grammer):#求Follow集的函数
        global Follow
        for i in range(len(grammer)):
            s=grammer[i]
            scanVT(s)
        FFollow(grammer)
    #print('____________________________')
    def showFirst():#显示First集
        global First
        for i in First.keys():
            print('First(',i,')= ',end="{ ")
            for j in First[i]:
                if j!=First[i][-1]:
                    print(j,end=", ")
                else:
                    print(j, end="")
            print("} ")
    #print('____________________________')
    def showFollow():#显示Follow集
        for i in Follow.keys():
            print('Follow(',i,')= ',end="{ ")
            for j in Follow[i]:
                if j!=Follow[i][-1]:
                    print(j,end=", ")
                else:
                    print(j,end="")
            print("} ")
    
    #print('____________________________')
    if __name__ == '__main__':
        print('____________________________')
        g=inputGrammer()#接收文法输入
        grammer=cut(g)#对产生式作处理
        initializeFirstAndFollow(grammer)#初始化First集和Follow集
        print('____________________________')
        handleFirst(grammer)#求First集
        showFirst()#显示First集
        print('____________________________')
        handleFollow(grammer)#求Follow集
        showFollow()#显示Follow集
        print('____________________________')
    

    输入

    在这里插入图片描述

    输出

    在这里插入图片描述

    检查

    • 和课本55、56页的结果对比,发现是一致的
    展开全文
  • 编译原理 求first集follow集 c++ 题目: 输入任意的上下文无关文法,输出所输入的上下文无关文法一切非终结符的first集合follow集合
  • 编译原理求FIRST集FOLLOW集和SELECT集

    万次阅读 多人点赞 2019-07-02 15:29:50
    觉得解释比较不错。 所有大写字母代表非终结符,小写字母代表终结符,省略号代表未知数目(可能为0)的不确定类型的文法符号。 First集合: First集合顾名思义就是一个文法符号串所...求First集合可分如下几...

    转自:https://liuyanzhao.com/8279.html

    觉得解释比较不错。

    所有大写字母代表非终结符,小写字母代表终结符,省略号代表未知数目(可能为0)的不确定类型的文法符号。

    First集合:

    First集合顾名思义就是求一个文法符号串所可能推导出的符号串的第一个终结符的集合

    First(X)就是求X所有推导出的符号串的第一个符号的集合。

    求First集合可分如下几种情况:

    1、单个符号的First集合:单个终结符的First集合就是它自己。

    2、单个非终结符的First集合:

    A-->a… 产生式右部以终结符开头,根据定义,这种情况下显然可以看出a属于First(A)。

    A-->B… 产生式右部以非终结符开头,根据定义,既然可以把A替换成B……,也可以看出First(B)属于First(A)。这是一个递归的推导。

     

    3、多个符号形成的符号串的First结合:

    符号串ABC…,并且A不能推导出空串ε,显然根据定义First(ABC…)=First(A)

     

    符号串ABC…,并且A可能推导出空串ε,当A不是空串的时候,显然First(A)属于First(ABC…),但当A是空串的时候,ABC…就成了BC…,此时根据B是否能推出空串来决定是否将First(B)加入First (ABC…)。这是一个递归的推导,综上所述,符号串中的第一个不能推出空串的符 号前面所有符号的First集合减去空串ε都属于First(ABC…),第一个不能推出空串的 符号的First集合也属于First(ABC…)。也就是假设A、B都可以推出空串,C不能推 出空串,First(ABC…)=First(A)-ε∪First(B)-ε∪First(C)。

     

    注意:First集合中的符号一定是终结符,终结符也包括空串ε。

    A–>…UP… 要求的Follow集合的非终结符后跟非终结符

     

    Follow集合:

    Follow集合也是顾名思义的,就是文法符号后面可能跟随的终结符的集合(不包括空 串ε)

    Follow(X)就是求X后面可能跟随的符号集合。

    求Follow集合可分如下几种情况:

    终结符的Follow集合没有定义,只有非终结符才会有Follow集合。

     

     

    A–>…Ua… 要求的Follow集合的非终结符后跟终结符

    根据定义,显然a属于Follow(U)。这种情况下,Follow(U)和A没有任何关系,产 生式左边是什么无所谓。

     

    A–>…UP… 要求的Follow集合的非终结符后跟非终结符

    根据定义,显然P的第一个符号属于Follow(U),也就是First(P)属于Follow(U)。

     

    A–>…UP并且ε属于First(P) 要求的Follow集合的非终结符后跟非结尾的终结符, 并且结尾非终结符的First集合包含空串。

    这是上一种情况的一种特例,除了要按上一种情况处理,First(P)属于Follow(U) 以外还要进行分析;因为当P推导为空串时,空串不能出现在Follow集合中,所以U 后面跟随的应该是P后面的东西,可P已经是结束的符号,此时U后面显然就是A后 面跟随的东西了。所以在这种情况下Follow(A)也属于Follow(U)。

     

    A–>…U 要求的Follow集合的非终结符在产生式结尾

    这时候又要递归推导,U是A的结尾,所以U后面跟随的东西也就是A后面跟随的东 西。所以Follow(A)属于Follow(U)。

     

    注意:Follow集合中的符号一定是终结符,并且不能包括空串ε,而且定义开始符号 的Follow集合初始为{#(句子括号)}。

     

    Select集合:

    Select集合就是产生式左部的可能的推导结果的起始符号。

    Select(A–>B)就是求这个产生式中A可能推导出起始符号集合(不包含空串ε)。

    求Select集合可分如下几种情况:

    A–>X (X为任意文法符号串,不限于非终结符或单个符号),并且X不能推导出空串 ε

    根据定义,显然A推出的符号串起始就是X的起始,也就是First(X).

    Select(A–>X)= First(X)

    A–>X (X为任意文法符号串,不限于非终结符或单个符号),并且X能推导出空串ε

    根据定义,显然First(X)属于Select(A–>X),此外,当X推导为空串时,显然A 也推导为空串,那么此时推导出的符号串就会是A后面的符号的推导结果。也就是 Follow(A),所以,此时Follow(A)也属于Select(A–>X)。

    注意:Select集合中不包括空串ε,但有可能会包含#(句子括号)。

     

    举个例子:

    S→AB

    S→bC

    A→ε

    A→b

    B→ε

    B→aD

    C→AD

    C→b

    D→aS

    D→c

    求他的first,follow,select

    先求First集

    • First(S) =(First(A)-{ε})∪(First (B)-{ε}) ∪{ε}∪{b} ={a,b,ε}

    因为A的first有ε,B的first有ε,S->AB,所以是First(A)-{ε})∪(First (B)-{ε}) ∪{ε},然后S->bC,所以再加一个b,就是First(A)-{ε})∪(First (B)-{ε}) ∪{ε}∪{b},

    • First (A)={b, ε}

    没什么好解释的

    • First (B)={a, ε}

    ε不用解释,就是B->ε,所以有他,a就是因为B->aD,第一个非终结符是a所以有a,那要不要加上D的first呢,就是a和c,答案是不用,就只要aD里面的a就可以

    • First (C)={a,b,c}

    C->AD这一句,AD都是非终结符,所以要找A和D的first集,D的是a,c,A的是b,ε,因为不是AD同时都能推出ε所以C的first是A和D的first的并集减去ε,还要加上b,因为有C->b这一句

    • First (D)={a,c}

    D->c不用解释,D->aS这一句,不用加上S的first!!!

     

    First (AB)={a,b,ε}

    First (bB)={b}

    First (ε)={ε}

    First (b)={b}

    First (aD)={a}

    First (AD)={a,b,c}

    First (aS)={a}

    First (c)={c}

    AB同时能够推出ε,所以first(AB)就是A和B的first的并集减去ε再并上ε

    bB的first就是b,不用加上B的first

    ε的就是ε,b就是b,c就是c,只有一个终结符ε没什么好说的

    一个终结符和一个非终结符的,就要那个终结符就可以,不用管后面那个非终结符,

    两个非终结符的要看是不是他们两个同时能推出ε,能就有ε,要是有一个不能推出ε,那first集就没有ε

    AB有ε是因为AB都能推出ε,AD没有是因为A能D不能推出ε

    以上first集就求完了,是不是很简单,我搞了一上午。。。

     

    接下来求follow集

    从开始符号S开始推倒,开始符号的follow里面一定要有#,

    所以开始符号的S的follow集要有#,

    follow是找->后面的,比如找S的follow,就要看谁的->后面有S,D->aS里面有S,然后在看D->aS的S后面有没有别的符号,没有就加上D的follow集,如果有,就加上后面那个字母的first集里面除了ε以外的符号,在看这个字母能不能推出ε,如果能,就再加上->左边的那个字母的follow

    看A的follow,首先找所有->后面有A的,找到了S->AB,C->AD,先看S->AB,A后面有B,所以要加上B的first集里面除了ε的其他符号,再看B能不能在有限的步骤里推出ε,有B->ε这句,所以能,就要再加上->左边的S的follow集,所以目前的A的follow集里面有a,和follow(S),再看C->AD这一句,A后面有D,所以要加上D的first集里面除了ε的其他的,再看B能不能在有限的步骤里推出ε,D不能,所以不用加->左边的C的follow,所以A的follow就是a,follow(S),a,c,但是如果有重复的,就只要一个,所以最终就是a,c,follow(S),这个follow(S)到后面还要算出来的,不能就这样写

    看B的follow,找所有->后面有B的,找到了S->AB,看B后面有字母吗?没有,就加上->左边的S的follow,所以follow(B)=follow(S)

    看C的follow,找所有->后面有C的,找到了S-bC,看C后面有字母吗?没有,就加上->左边的S的follow集,所以follow(C)=follow(S)

    看D的follow,找所有->后面有D的,找到了B->aD。C->AD,这两句D后面都没有字母,所以加上->左边的B和C的follow,所以follow(D)=follow(B)并上follow(C)

    最终要把以上的follow都求出来,看

    follow(S)=#+follow(D),

    follow(D)=follow(B)+follow(C),

    所以follow(S)=#+follow(B)+follow(C),

    follow(B)=follow(S),

    follow(C)=follow(S)

    所以follow(S)=#+follow(S)+follow(S),

    所以follow(S)就是#,

    follow(B),follow(C),follow(D)也都是#,

    所以follow(A)就是ac,#,求完了,以上所有的+代表求并集

     

    再看select怎么求

    对于A->a,

    如果a≠>ε,那么select(A->a)=first(a),

    如果a=*>,那么select(A->a)就是first(a)-ε+follow(A)

    看select(S->AB),AB都能推出ε,所以select(S->AB)=first(AB)-ε+follow(S)所以结果是a,b,#

    看select(S->bC),bC不能推出ε,所以是first(bC),结果是b

    看select(A->ε),A能推出ε所以是first(ε)-ε+follow(A)结果a,c,#

    看select(A->b),这里的A是推出b不是ε所以是first(b),结果是b

    看select(B->ε),B能推出ε,所以是first(ε)-ε+follow(B),结果是#

    看select(B->aD),这里B不能推出ε,所以是first(aD),结果是a

    看select(C->AD),这里D不能推出ε,所以算AD不能推出ε,就是first(AD),结果是a,b,c

    看select(C->b),C推不出看ε,所以是first(b),结果是b

    看select(D->aS),这里不能推出ε,所以是first(aS),结果是a

    看select(D->c),这里D不能推出ε,所以是first(c),结果是c

    LL(1)文法

    是自顶向下分析,从左到右扫描输入串,最左推导,只需向右看一个符号就可以决定如何推倒

    LL(1)文法满足条件:左部相同的产生式的select集的交集为空,并且产生式的右部不能同时推导出ε,那么这个文法是LL(1)文法,否则不是

    上面的文法select(C->AD)和select(C->b)的交集是b不是空,select(S->AB)和select(S->bC)的交集也是b不是空,所以这不是一个LL(1)文法

    展开全文
  • 如何求First集Follow集(超详细)

    千次阅读 多人点赞 2020-12-23 18:16:37
    如何求First集Follow集 已知文法如下,求First集Follow集 G[E]:E→TE′E′→+TE′∣εT→FT′T′→∗FT′∣εF→(E)∣i G[E]: E{\rightarrow} TE' \\ {\quad\quad\quad\quad\quad}E'{\rightarrow}+TE'|\var...
  • 编译原理的FIRST集和FOLLOW集~~有兴趣的可以看一下,有漏了一个条件,不过注明出来了~~
  • 编译原理 求解first集和follow集步骤(附例子)

    万次阅读 多人点赞 2020-03-14 21:07:41
    First集 定义:对于任意文法符号串α ,FIRST(α)是可从α推导得到的串的首符号的集合 如果αε,则ε也在FIRST(α)中( 即α可空) FIRST(α)={t|α-->tβ, t∈T}U{ε|α-->ε} 做法:首先明确FIRST...
  • 计算first集和follow集

    2012-06-04 19:53:51
    编译实验中一文法的first集和follow集
  • 编译原理FIRST集和FOLLOW集

    千次阅读 多人点赞 2019-06-18 17:16:41
    编译原理FIRST集和FOLLOW集法 由于最近要期末考试了,所以要从头到尾复习(预习)一遍了。陈意云老师写的课本比较抽象,看不太懂,最后又找了中科大的编译原理课,可能听的时候太困了没有集中精力,又跑去看了...
  • java 求First集和Follow集

    千次阅读 2014-05-10 09:50:45
    import java.util.ArrayList; import java.util.Scanner; import java.util.StringTokenizer;... * 1、一行只能输入一个句子,且不能拖延到第二行,... * 2、推导符号,只能是→->中一种,每行语句中必须有推导符
  • 编译原理FIRST集和FOLLOW集法以及构建LL(1)分析表

    万次阅读 多人点赞 2019-07-01 10:57:57
    文章目录FIRST集FOLLOW集的计算生成预期分析表算法例题 FIRST集FIRST集是一个文法符号串所可能推导出的符号串的第一个终结符的集合 对于文法G的任一符号串α\alphaα = x1x2…xnx_{1}x_{2} \ldots x_{n...
  • 文法first集和follow集的计算源代码
  • 对文法中的非终结符,求first集和follow集
  • C++实现first集follow集

    2020-12-03 22:36:07
    C++实现first集follow集 “@”代替字符“ε”,“i”代替字符“id” #include<iostream> #include<vector> #include<string> #include<fstream> using namespace std; struct exp{ char ...
  • 复习 | First集和Follow集

    千次阅读 2020-12-22 17:53:56
    这篇文章记录First集和Follow集法。
  • 如何计算FIRST集和FOLLOW集

    千次阅读 2020-02-14 15:33:22
    编译原理之计算FIRST集合和FOLLOW集合 原创 ...
  • FIRST集和FOLLOW集的计算

    千次阅读 2019-04-26 17:05:58
    文章目录`FIRST`集的计算计算`FIRST(x)`具体算法计算`$X_21,X_2,X_3,...,X_n$`的`FIRST`集FOLLOW集的计算算法 FIRST集的计算 计算FIRST(x) FIRST(X):可以从X中推导出的所有串首终结符构成的结合。 若$X\Rightarrow...
  • 一、FIRST集 FIRST(A)为A的开始符或者首符号集。 1、定义: 设G=(VT,VN,S,P)是上下文无关文法 ,FIRST(α)={a|α能推导出aβ,a∈VT,α,β∈V*} 特别的,若α能推导出ε,则规定ε∈FIRST(α). 2、根据定义求解...
  • FIRST 的定义 简单的说 FIRST 就是一个文法符号串的开始符号集合 设 G=(VT,VN,S,P)是上下文无关文法,...例题 4.3: FIRST 题目: 给定文法 G[S]: (1)S -> Af (2)S -> Be (3)A -> a
  • FIRST集和FOLLOW集FIRST集步骤FOLLOW集步骤 FIRST集 步骤 若X->a…,则将终结符a加入FIRST(X)中; 若X->e ,则将终结符e加入FIRST(X)中(e表示空集); 若 X->BC…D,则将First(B)所有元素(除了空集...
  • 博文链接:https://zpchen.iteye.com/blog/208947
  • Python求first 和follow

    千次阅读 2019-10-20 16:45:32
    FIRST = {} FOLLOW = {} sentences = [ 'E->TG', 'G->+TG', 'G->-TG', 'G->ε', 'T->FS', 'S->*FS', 'S->/FS', ...#初始化 first 和follow集合字典的键值对中的 值 为空 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,419
精华内容 3,367
关键字:

求first集和follow集代码