先看例子:
设有文法:
E -> TE’
E’->+E|ε
T->FT’
T’->T|ε
F->PF’
F’->F’|ε
P->(E)|a|b|^
关于First,Follow集合以及预测分析表的求法
首先看了书和网上的资料,第一眼就是看不懂,接下来让我以白话的形式来分享一下
First和Follow集合
First集合的求法:
看一下例子我们应该能直接明白了:
首先看表达式E->TE’, 它的First(E)就是First(T),没懂?,不要紧,我在举个例子,这次我们看表达式 P->(E)|a|b|^, 它的First(.P)就是{(,a,b,^}(这里用.P代表下P啊),咱们再来最后一个例子,看表达式T’->T| ε, 它的First(T’)就是{FIrst(T),ε}.
我相信很多人都已经发现规律了,First的求法就是将后面式子的第一位加进去(如果有多种情况,则需要都取一下式子的第一位,如上面的First(.p)),如果是非终结符就把这个非终结符的First集合加进去,如果是终结符,直接加入终结符就行.
Follow集合的求法
首先要将#加入文法开头的Follow集合中,此题中E是文法集合,所以要将#加入Follow(E)中。
其次,设有表达式a->bcd
1.如果First(d)包含ε,那么就将Follow(a)的元素加入Follow(.c)中.d可以不存在.即a->bc,此时也要将Follow(a)的元素加入Follow(.c)中
2.将First(d)中除ε外的元素加入Follow(.c)中
预测分析表
这个我建议去看一下这个博客的末尾处,我就是看了这个一下就懂了,切记:如果看不懂定义,结合表看就懂了
https://blog.youkuaiyun.com/qq_41731283/article/details/106448620
递归下降分析程序
总体来说这个程序并不难,首先要知道我们的目的,我们的目的是输入一个字符串,然后判断能不能从E推出这个表达式,直接看代码,我相信各位一看就能懂.
package LeeCode;
import java.util.Scanner;
public class DiGuiRecursiveAnalysis {
static String word;//输入的字符串
static int index = 0;//用来记录目前准备匹配的字符的位置
public void error() {//如果匹配错误,输出不合法的,然后终止程序,不再进行匹配
System.out.println("不合法的!");
System.exit(0);
}
//E->TE'
public void E() {
System.out.println("E->TE'");
T();
E1();
}
//E'->+E|null
public void E1() {
if (word.charAt(index) == '+') {
index++;
System.out.println("E'->+E");
E();
} else {
System.out.println("E'->ε");
}
}
// T->FT'
private void T() {
System.out.println("T->FT'");
F();
T1();
}
// T'->T|null
private void T1() {
/*
这里的if我要说一下,为什么条件是这些呢,因为我们First(T')中的元素是这些加上ε.然而我们要执行T1->ε这步最后得到的就是ε元素,反正执行T1->T这步最后可以得到该if中的元素,所以如果想执行T1->T这步,则需要匹配是不是这些元素
*/
if (word.charAt(index) == '('||word.charAt(index) == 'a'||word.charAt(index) == 'b'||word.charAt(index) == '&') {
System.out.println("T'->T");
T();
} else{
System.out.println("T'->ε");
}
}
// F->PF'
private void F() {
System.out.println("F->PF'");
P();
F1();
}
//F'->*F'|null
private void F1() {
if (word.charAt(index) == '*') {
index++;
System.out.println("F'->*F'");
F1();
} else {
System.out.println("F'->ε");
}
}
//P->(E)|a|b|&
private void P() {
if (word.charAt(index) == '(') {
index++;
E();
if (word.charAt(index) == ')') {
index++;
System.out.println("P->(E)");
} else {
error();
}
} else if (word.charAt(index) == 'a') {
index++;
System.out.println("P->a");
}else if (word.charAt(index) == 'b') {
index++;
System.out.println("P->b");
}else if (word.charAt(index) == '&') {
index++;
System.out.println("P->&");
} else {
error();
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入字符串(以#结尾)");
word = input.nextLine();
if (word.charAt(word.length()-1)!='#'){
System.out.println("输入的不符合要求,要以#结尾!");
System.exit(0);
}
DiGuiRecursiveAnalysis parse = new DiGuiRecursiveAnalysis();
parse.E();
System.out.println("分析成功");//因为我程序如果判断出错误就终止了,所如果没有终止的话就代表成功了.直接输出即可.
}
}
运行截图:
1.
2.
如有错误请指出,一起学习,一起进步!