1、判断各非汇总结符是否可以推出空
(1)将各非终结符出示状态置为“未知”
(2)按顺序扫描各产生式右部。分为下面几种情况:
a、若遇到符号“ε”,检查左部非终结符状态,若不是“空”,将其置为“空”,继续扫描下一产生式;
b、若遇到终结符,检查左部非终结符状态,若为“未知”,将其置为“非空”,继续扫描下一产生式;
c、若遇到非终结符,检查该非终结符状态,若为“未知”,则跳过当前产生式,扫描下一产生式;若为“非空”,检查左部非终结符状态,若为“未知”,将其置为“非空”,继续扫描下一产生式;
若为“空”,继续扫描本产生式的下一符号;
d、若遇到“\0”,检查左部非终结符状态,若不是“空”,将其置为“空”,继续扫描下一产生式;
e、若上述a,b,c,d过程引起了非终结符状态的改变,则跳到(2)处继续循环,否则跳出循环,判断结束。
2、求非终结符的first集
扫描以要求first集的非终结符为左部的各产生式的右部,分为下面几种情况:
A、若遇到终结符,将该终结符加入左部非终结符的first集,继续扫描下一产生式;
B、若遇到符号“ε”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
C、若遇到非终结符,将该非终结符的 first集— {ε}加入左部非终结符的first集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;若不为空,则继续扫描下一产生式;
D、若遇到“\0”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
3、求某一非终结符的FOLLOW集
(1)在产生式右部找到该非终结符,扫面它后面的符号,分为下面几种情况:
A、若是终结符,则将该终结符加入该非终结符的folow集;
B、若是非终结符,将该非终结符的 first集— {ε}加入该非终结符的folow集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
C、若是“\0”,则将该产生式的左部非终结符的follow集加入它的follow集。
(2)在产生式的右部继续查找该非终结符,若找到,转(1)步。
4、求某产生式的select集
扫描产生式的右部,分为下面几种情况:
(1) 若是终结符,则将该终结符加入该产生式的select集;
(2) 若是“ε”,将左部非终结符的follow集加入该产生式的select集;
(3) 若是非终结符,将该非终结符的 first集— {ε}加入该产生式的select集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
(4) 若是“\0”,则将该产生式的左部非终结符的follow集加入该产生式的select集。
代码:import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.nio.charset.Charset;
import java.util.*;
public class LL1 {
public static int find(char v) {
/*if(v=='a'||v=='b'||v=='c'||v=='d'){
return 1;
}
else{
return 0;
}*/
if(v=='+'||v=='*'||v=='('||v==')'||v=='i'){
return 1;
}
else{
return 0;
}
}
public static String shutdown(){
//return "abc#";
return "i+*()#";
}
public static void start() {
System.out.println("LL(1)语法分析演示程序-----------------------------李欣");
System.out.println(" 1.输入LL(1)文法\n");
System.out.println(" 2.显示输入的LL(1)文法\n");
System.out.println(" 3.判定非终结符是否为空\n");
System.out.println(" 4.输出非终结符的First集\n");
System.out.println(" 5.输出非终结符的Follow集\n");
System.out.println(" 6.输出产生式的Sellect集\n\t");
System.out.println(" 7.分析过程演示\n\t");
System.out.println(" 请输入你想要做的操作:");
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
Scanner in = new Scanner(System.in);
start();
int choose=0;
String o = in.nextLine();
choose=Integer.parseInt(o);
while(choose!=1) {
System.out.println("输入错误请重新输入:");
o = in.nextLine();
choose=Integer.parseInt(o);
}
String []t = new String [50]; //字符串形式存入
int []s= new int [26]; // 存放左部起始符
int i=0;
int top;
int n;
int count=0; //
char []mov = new char[50];
System.out.println("请输入个数");
o = in.nextLine();
n = Integer.parseInt(o);
for(i=0;i<26;i++){
s[i]=5;
}
System.out.println("请输入文法");
i = 0;
while(i<n){
char ch;
t[i] = in.nextLine();
ch = t[i].charAt(0);
if(s[ch-'A']==5) {
s[ch-'A']=-1; //-1表示未知
mov[count]=ch;
count++;
}
i++;
}
/***********************************************************************************************/
// System.out.println();
// System.out.println("判断是为空:");
int len;
int j;
top = n;
for(i=0;i<top;i++){
len = t[i].length();
for(j=3;j<len;j++){
if(t[i].charAt(j)=='\0'){
s[t[i].charAt(0)-'A']=0;
break;
}
if(s[t[i].charAt(0)-'A']==0){
break;
}
/*a*/ if(t[i].charAt(j)=='@'){
s[t[i].charAt-'A']=0; //遇到符号ε表示空
break;
}
/*b*/ if(find(t[i].charAt(j))==1){ //遇到终结符,检查左部非终结符状态
if(s[t[i].charAt(0)-'A']==-1){
s[t[i].charAt(0)-'A']=1;
break;
}
}
/*c*/ if(find(t[i].charAt(j))==0){ //遇到非终结符,检查该非终结符状态
if(s[t[i].charAt(j)-'A']==-1){//若为"未知",则跳过当前产生式,扫描下一产生式
String vc = new String();
vc=t[i];
t[top]=vc;
top++;
break;
}
if(s[t[i].charAt(j)-'A']==1){ //若为"非空",检查左部非终结符状态,
if(s[t[i].charAt(0)-'A']==-1){
s[t[i].charAt(0)-'A']=1; //若为"未知",将其置为"非空",继续扫描下一产生式;
}
break;
}
if(s[t[i].charAt(j)-'A']==0){//若为"空",继续扫描本产生式的下一符号;
if(j+1==t[i].length()){
s[t[i].charAt(0)-'A']=0;
break;
}
}
}
}
}
/*for(i=0;i<26;i++){
if(s[i]==1){
char ch = (char) (i+'A');
System.out.println( ch+"为非空");
}
if(s[i]==0){
char ch = (char) (i+'A');
System.out.println( ch+"为空");
}
}*/
/****************************************************************************************/
//System.out.println();
//System.out.println("First集:");
Set []first = new HashSet[26];
top = n;
int []flag = new int [26];
for(i=0;i<26;i++) {
flag[i]=0;
}
for(i=0;i<top;i++) {
char ch = t[i].charAt(0);
if(flag[ch-'A']==0) {
flag[ch-'A']=1;
first[ch-'A'] = new HashSet();
}
for(j=3;j<=t[i].length();j++) {
if(j==t[i].length()){ //若遇到“\0”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
first[(int)ch-'A'].add('@');
break;
}
if(find(t[i].charAt(j))==1) { //若遇到终结符,将该终结符加入左部非终结符的first集,继续扫描下一产生式;
first[(int)ch-'A'].add(t[i].charAt(j));
break;
}
if(t[i].charAt(j)=='@') { //若遇到符号“ε”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
first[(int)ch-'A'].add('@');
break;
}
if(find(t[i].charAt(j))==0) { //若遇到非终结符,将该非终结符的 first集— {ε} 加入左部非终结符的first集
if(top<2*n) {
String vc = new String();
vc=t[i];
t[top]=vc;
top++;
}
if(first[(int)t[i].charAt(j)-'A']!=null) {
Iterator<Character> it = first[(int)t[i].charAt(j)-'A'].iterator(); //利用迭代器遍历
while(it.hasNext()) {
char chr = it.next();
if(chr!='@')
first[(int)ch-'A'].add(chr);
}
}
if(s[t[i].charAt(j)-'A']==0) { //然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
continue;
}
else { //若不为空,则继续扫描下一产生式;
break;
}
}
}
}
/*for(i=0;i<26;i++) {
if(s[i]!=5) {
System.out.println((char)(i+'A')+"的first集"+first[i].toString());
}
}*/
/*******************************************************************************************************************************/
//System.out.println();
//System.out.println("Follow集:");
Set []follow = new HashSet[26];
top = n;
for(i=0;i<26;i++) {
flag[i]=0;
}
int l;
for(i=0;i<count*n;i++) {
char ch = mov[i%count]; //ch为当前要检测的字符
// System.out.println("当前检测字符为"+ch);
if(flag[ch-'A']==0) {
flag[ch-'A']=1; //分配空间
follow[ch-'A'] = new HashSet();
}
follow[mov[0]-'A'].add('#');
for(j=0;j<top;j++) { //五个式子
// System.out.println(" 当前是第"+j+"个式子");
for(l=3;l<t[j].length();l++) { //每个式子从头到尾
if(t[j].charAt(l)==ch) {
// System.out.println(" 第"+j+"个式子的第"+(l-2)+"个字符匹配成功");
int q;
for(q=l+1;q<=t[j].length();q++) {
if(q==t[j].length()) { //若是“\0”,则将该产生式的左部非终结符的follow集加入它的follow集。
// System.out.println(" 进入1");
if(follow[(int)t[j].charAt(0)-'A']!=null) {
Iterator<Character> it = follow[(int)t[j].charAt(0)-'A'].iterator(); //利用迭代器遍历
while(it.hasNext()) {
char chr = it.next();
if(chr!='@')
follow[(int)ch-'A'].add(chr);
}
// System.out.println(" "+ch+"的follow集合为"+follow[(int)ch-'A']);
}
break;
}
if(find(t[j].charAt(q))==1) { //若是终结符,则将该终结符加入该非终结符的follow集;
// System.out.println(" 进入2");
follow[ch-'A'].add(t[j].charAt(q));
break;
}
if(find(t[j].charAt(q))==0) { //若是非终结符,将该非终结符的 first集— {ε} 加入该非终结符的follow集,
// System.out.println(" 进入3");
Iterator<Character> it = first[(int)t[j].charAt(q)-'A'].iterator(); //利用迭代器遍历
// System.out.println(" "+t[j].charAt(q));
while(it.hasNext()) {
char chr = it.next();
if(chr!='@')
follow[(int)ch-'A'].add(chr);
}
// System.out.println(" "+ch+"的follow集合为"+follow[(int)ch-'A']);
if(s[t[j].charAt(q)-'A']==0) { //然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
// System.out.println(" 进入3.5");
continue;
}
}
}
}
}
}
}
/*for(i=0;i<26;i++) {
if(s[i]!=5) {
System.out.println((char)(i+'A')+"的follow集"+follow[i].toString());
}
}*/
/***********************************************************************************************************************************************************************/
//System.out.println();
//System.out.println("Select集:");
Set []select = new HashSet[n];
top = n;
for(i=0;i<n;i++) {
select[i] = new HashSet();
}
for(i=0;i<n;i++) {
for(l=3;l<=t[i].length();l++) {
if(l==t[i].length()) {
Iterator<Character> it = follow[(int)t[i].charAt(0)-'A'].iterator(); //利用迭代器遍历
while(it.hasNext()) {
char chr = it.next();
select[i].add(chr);
}
break;
}
if(find(t[i].charAt(l))==1) { //若是终结符,则将该终结符加入该产生式的select集;
select[i].add(t[i].charAt(l));
break;
}
if(t[i].charAt(l)=='@') { //若是“ε”,将左部非终结符的follow集加入该产生式的select集
Iterator<Character> it = follow[(int)t[i].charAt(0)-'A'].iterator(); //利用迭代器遍历
while(it.hasNext()) {
char chr = it.next();
select[i].add(chr);
}
break;
}
if(find(t[i].charAt(l))==0) { //若是非终结符,将该非终结符的 first集— {ε} 加入该产生式的select集
Iterator<Character> it = first[(int)t[i].charAt(l)-'A'].iterator(); //利用迭代器遍历
while(it.hasNext()) {
char chr = it.next();
if(chr!='@')
select[i].add(chr);
}
if(s[t[i].charAt(l)-'A']==0) { //然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号
continue;
}
else {
break;
}
}
}
}
/*for(i=0;i<n;i++) {
System.out.println(t[i]+"的select集为"+select[i].toString());
}*/
/*********************************************************************************************************************/
//System.out.println();
//System.out.println("判断是否为LL(1)文法:");
int judge=0;
for(i=0;i<n;i++) {
for(j=i+1;j<n;j++) {
if(t[i].charAt(0)==t[j].charAt(0)) {
Set<Character> result = new HashSet<Character>();
result.clear();
result.addAll(select[i]);
result.retainAll(select[j]);
if(result.size()!=0) {
judge=1;
break;
}
}
}
/*if(judge==1) {
System.out.println("该文法不是LL(1)文法");
break;
}
else {
System.out.println("该文法是LL(1)文法");
}*/
}
/*********************************************************************************************************************/
//System.out.println();
//System.out.println("构建的预测分析表:");
int [][]graph=new int [26][20];
for(i=0;i<26;i++) {
for(j=0;j<20;j++) {
graph[i][j]=1024;
}
}
String end = shutdown();
for(i=0;i<n;i++) {
for(j=0;j<end.length();j++) {
if(select[i].contains(end.charAt(j))) {
graph[t[i].charAt(0)-'A'][j]=i;
}
}
}
/*for(i=0;i<end.length();i++) {
System.out.print(" "+end.charAt(i)+" ");
}
System.out.println();
for(i=0;i<count;i++) {
System.out.print(mov[i]);
for(j=0;j<end.length();j++) {
if(graph[mov[i]-'A'][j]!=1024) {
System.out.print(" "+t[graph[mov[i]-'A'][j]]);
}
else {
System.out.print(" "+"error");
}
}
System.out.println();
}*/
/*************************************************************************************************************************************/
/*************************************************************************************************************************************/
while(true){
start();
o = in.nextLine();
choose=Integer.parseInt(o);
while(choose>7) {
System.out.println("输入错误请重新输入:");
o = in.nextLine();
choose=Integer.parseInt(o);
}
if(choose==2) {
for(i=0;i<n;i++) {
System.out.println(t[i]);
}
}
if(choose==3) {
for(i=0;i<26;i++){
if(s[i]==1){
char ch = (char) (i+'A');
System.out.println( ch+"为非空");
}
if(s[i]==0){
char ch = (char) (i+'A');
System.out.println( ch+"为空");
}
}
}
if(choose==4) {
for(i=0;i<26;i++) {
if(s[i]!=5) {
System.out.println((char)(i+'A')+"的first集"+first[i].toString());
}
}
}
if(choose==5) {
for(i=0;i<26;i++) {
if(s[i]!=5) {
System.out.println((char)(i+'A')+"的follow集"+follow[i].toString());
}
}
}
if(choose==6) {
for(i=0;i<n;i++) {
System.out.println(t[i]+"的select集为"+select[i].toString());
}
System.out.println();
if(judge==1) {
System.out.println("该文法不是LL(1)文法");
}
else {
System.out.println("该文法是LL(1)文法");
}
System.out.println();
for(i=0;i<end.length();i++) {
System.out.print(" "+end.charAt(i)+" ");
}
System.out.println();
for(i=0;i<count;i++) {
System.out.print(mov[i]);
for(j=0;j<end.length();j++) {
if(graph[mov[i]-'A'][j]!=1024) {
System.out.print(" "+t[graph[mov[i]-'A'][j]]);
}
else {
System.out.print(" "+"error");
}
}
System.out.println();
}
}
if(choose==7) {
if(judge==1) {
System.out.println("该文法不是LL(1)文法!!不能进行LL(1)分析!!!");
}
else {
String str = new String();
System.out.println("请输入要分析的符号串(以#号结尾):");
str=in.nextLine();
Stack vc = new Stack();
vc.push('#');
vc.push(t[0].charAt(0));
System.out.println("步骤 "+"分析栈 "+"剩余串 "+"产生式或匹配");
//
i=0;
l=0;
int c=0;
String copy=new String();
copy=str;
StringBuffer way = new StringBuffer();
way.append(t[0].charAt(0));
while((char)vc.peek()!='#'||str.charAt(i)!='#') {
System.out.print(l+" "+vc.toString()+" "+str+" ");
if((char)vc.peek()==str.charAt(i)) {
System.out.println(str.charAt(i)+"匹配");
vc.pop();
str=str.substring(1);
c++;
}
else if(find((char)vc.peek())==0) {
j = graph[(char)vc.peek()-'A'][end.indexOf(str.charAt(i))];
if(j==1024) {
System.out.println("分析出错!!!!!!停止分析");
// System.out.println((char)vc.peek()+" "+str.charAt(i)+" "+i);
break;
}
else {
System.out.println(t[j]);
vc.pop();
if(t[j].charAt(3)!='@') {
for(int k=t[j].length()-1;k>=3;k--) {
vc.push(t[j].charAt(k));
}
}
//
way.append(" => ");
way.append(copy.substring(0,c));
int z;
for(z=vc.size()-1;z>0;z--) {
way.append(vc.get(z));
}
}
}
else {
System.out.println("分析出错!!!!!!");
break;
}
}
if((char)vc.peek()=='#'&&str.charAt(i)=='#') {
System.out.println(l+" "+vc.toString()+" "+str+" "+"接受");
System.out.println("最右推导"+way);
}
}
}
}
}
}


京公网安备 11010502036488号