LL(1)分析器,借鉴了别人的代码
LL(1)部分
/* (1)E->TG
* (2)G->+TG|-TG
* (4)G->@
* (5)T->FS
* (6)S->*FS|/FS
* (8)S->@
* (9)F->(E)
* (10)F->i
* */
package e1902;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.*;
public class e1902 {
static char vn[] ;
//创建非终结符数组
static char vt[] ;
//终结符,并加入了#方便follow集时查找,@代表空
boolean first[][] = new boolean [vn.length][vt.length+1];
//所有非终结符first集的集合,每行最后一个元素用来判断是否求过first集
boolean follow[][] = new boolean [vn.length][vt.length+1];
//所有非终结符follow集的集合,每行最后一个元素用来判断是否求过follow集
String analyse[][] = new String [vn.length][vt.length-1];
//创建预测分析表
static String verbs[] ;
//文法
static window windows;
static String rowdata[][] = new String[50][5];//添加到窗口表格里的数组
static final String path ="D://Eclipse/e1902.txt";
e1902(String verbs[],char vn[],char vt[]) {
first_final(vn,vt,verbs);//求first集
follow_final(vn,vt,verbs);//求follow集
create(verbs,vn,vt);//建分析表
}//class e1902的构造方法
public static void main(String args[]) throws Exception{
int i ,j ,k=0,flag=0;
char c;
char temp2[] = {'0','0','0','0','0','0','0','0','0','0'};
ArrayList<String> list = new ArrayList<String>();
File file = new File(path);
BufferedReader br = new BufferedReader(new FileReader(file));
String temp;
while((temp = br.readLine())!= null){
list.add(temp);
}
br.close();//关闭文件
verbs = new String[list.size()];
for( i =0;i < list.size();i++){
verbs[i] = list.get(i);
}
for(i = 0 ;i<verbs.length;i++){
c = verbs[i].charAt(0);
for(j=0;j<10;j++){
if(c == temp2[j]){
flag = 1;
break;
}
}
if(flag == 0){
temp2[k] = c;
k++;
}
flag = 0;
}
k=0;
for(i=0;i<10;i++){
if(temp2[i] != '0'){
k++;
}
}
vn = new char[k];
for(i= 0;i<k;i++){
vn[i] = temp2[i];
}
k=0;
flag = 0;
char temp3[] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
for(i=0;i<verbs.length;i++){
for(j=3;j<verbs[i].length();j++){
if( verbs[i].charAt(j) != '|' && (verbs[i].charAt(j)<'A' || verbs[i].charAt(j)>'Z') && verbs[i].charAt(j) != '@' ){
temp3[k] = verbs[i].charAt(j);
k++;
}
}
}
int len = 0;
char temp4[] = {'0','0','0','0','0','0','0','0','0','0'};
for(i=0;i<k;i++){
c = temp3[i];
flag = 0;
for(j=0;j<10;j++){
if( c == temp4[j]){
flag = 1;
break;
}
}
if(flag == 0){
temp4[len]=c;
len++;
}
}
k=0;
for(i=0;i<10;i++){
if(temp4[i] != '0'){
k++;
}
}
vt = new char[k+2];
for(i= 0;i<k;i++){
vt[i] = temp4[i];
}
vt[k] = '#';
vt[k+1] = '@';
window windows = new window(rowdata,vn,vt,verbs);
if(isleft(verbs,vn,vt) == true){
windows.textshow.append("文法包含左递归,ERROR!");
return;
}
e1902 e = new e1902(verbs,vn,vt);
for(i = 0;i<vn.length;i++){
temp = " FIRST("+vn[i]+")={ ";
for(j= 0 ;j<vt.length;j++){
if(e.first[i][j] == true){
if(vt[j] == '@'){
temp = temp + 'ε' + " ";
}
else{
temp = temp + vt[j] + " ";
}
}
}
temp = temp + "}\n";
windows.textshow.append(temp);
}//向窗口输出FIRST集
for(i = 0;i<vn.length;i++){
temp = " FOLLOW("+vn[i]+")={ ";
for(j= 0 ;j<vt.length;j++){
if(e.follow[i][j] == true){
temp = temp + vt[j] + " ";
}
}
temp = temp + "}\n";
windows.textshow.append(temp);
}//向窗口输出FOLLOW集
temp = "analyze table:\n";
windows.textshow.append(temp);
temp = "\n";
windows.textshow.append(temp);
temp = " ";
windows.textshow.append(temp);
for(i = 0;i<vt.length-1;i++){
temp = vt[i]+" ";
windows.textshow.append(temp);
}//输出表头
temp = "\n";
windows.textshow.append(temp);
for(i = 0; i< vn.length;i++){
temp = "\n";
windows.textshow.append(temp);
temp = " " + vn[i] + " ";
for(j = 0; j < vt.length -1; j++){
if(e.analyse[i][j] != null){
temp = temp + vn[i] + "->" + e.analyse[i][j] +" ";
}
else{
temp = temp + " ";
}
}
temp = temp + "\n";
windows.textshow.append(temp);
}
}
static boolean isleft(String verbs[],char vn[],char vt[]){
int i,j,k;
for(i =0;i < verbs.length;i++){
j=3;
k = indexofor(3,verbs[i]);
if(k == -1){
k = verbs[i].length();
}
while(j < verbs[i].length()){
if(verbs[i].charAt(0) == verbs[i].charAt(j)){
return true;//直接左递归
}
j = k+1;
k = indexofor(j,verbs[i]);
if(k == -1){
k = verbs[i].length();
}
}
}
int m,p;
char u ;
String temp;
for(i=0;i<verbs.length;i++){
j = 3;
u = verbs[i].charAt(0);
k = indexofor(3,verbs[i]);
if(k == -1 ){
k = verbs[i].length();
}
while(j < verbs[i].length()){
if(vn(verbs[i].charAt(j),vn) != -1){
//右侧第一个字符是非终结符
temp = verbs[vn(verbs[i].charAt(j),vn)];
m=3;
p = indexofor(3,temp);
if(p == -1 ){
p = temp.length();
}
while(m < temp.length()){
if(u == temp.charAt(m)){
//含有间接左递归
return true;
}
m = p+1;
p = indexofor(m,temp);
if(p == -1 ){
p = temp.length();
}
}
}
j = k+1;
k = indexofor(j,verbs[i]);
if(k == -1 ){
k = verbs[i].length();
}
}
}
return false;
}
//判断是否含有左递归,若含有左递归,直接终止程序,报错
int indexofx(char c, String s){
int i;
for(i = 3;i<s.length();i++){
if(s.charAt(i) == c){
return i;//返回C的位置
}
}
return -1;//没有c返回-1
}
//对于String类的求字符位置
static int indexofx(char c, char s[]){
int i;
for(i = 3;i<s.length;i++){
if(s[i] == c){
return i;
}
}
return -1;//没有c返回-1
}
//对于char[]类的求字符位置
static int indexofor (int i,String s){
for(i=i+1;i<s.length();i++){
if(s.charAt(i) == '|'){
return i;
}
}
return -1;//-1表示没有‘|’
}
//indexofor函数返回产生式右边‘|’的位置
static int vn(char a,char c[]){
int i ;
for(i=0;i<c.length;i++){
if(c[i] == a){
return i;
}
}
return -1;//-1表示a不是非终结符
}
// vn 函数返回a在非终结符数组中的位置
static int vt(char a, char c[] ){
int i ;
for(i=0;i<c.length;i++){
if(c[i] == a){
return i;
}
}
return -1;//-1表示a不是终结符
}
// vt 函数返回a在终结符数组中的位置
void fir(String s,int i , char vn[],char vt[],String verbs[]){
int c = vn(s.charAt(0),vn);
//c是这一条产生式左侧的非终结符,c为非终结符数组中的位置,同时也是first[][]中行数
int k;
if(vt(s.charAt(i),vt) != -1){
first[c][vt(s.charAt(i),vt)] = true;//写入first集
}//右侧第一个字符是终结符,直接写入first集
else{
//当前判断的字符式是非终结符
if(first[vn(s.charAt(i),vn)][vt.length] == false){
first(s.charAt(i),vn,vt,verbs);//i是非终结符,并且还未求first集,先求出first集
}
for(k=0;k<vt.length;k++){
if(first[vn(s.charAt(i),vn)][k] == true && vt[k] != '@'){
first[c][k] = true;//把i的first集中除了空串的终结符给c的first集
}
}
if(first[vn(s.charAt(i),vn)][vt('@',vt)] == true){
//此时i的first集中有空串
if(i == s.length() - 1){
//i是产生式最后一位
first[c][vt('@',vt)] = true;
return;//这条产生式结束。准备扫描下一条
//规则四:A->BCD......,BCD...的first集中都含有空,则把空写入c的first集中
}
if( s.charAt(i+1) != '|'){
//规则四:A->BCD......,将BCD...的first集-@写入c的first集中
i++;//指向后一个字符
fir(s,i,vn,vt,verbs);//迭代将产生式中所有连续非终结符的first集都求出来
}
else{
//i+1是 | ,这条产生式暂时结束,同上一个if,每个first集都有@,写入@
first[c][vt('@',vt)] = true;
}
}
}
}
//求某一条产生式的first集,此时并不是某一个非终结符的first集,因为有的非终结符有多条产生式
void first(char c,char vn[],char vt[],String verbs[]){
int i,j;
String s;
for(i=0;i< verbs.length;i++){
s = verbs[i];
if( c == s.charAt(0)){
//找到c的产生式
j=3;
if(s.charAt(0) != s.charAt(j)){
fir(s,j,vn,vt,verbs);//求关于这条产生式的first集
}
while( indexofor(j,s) != -1 && j < s.length()){
//判断这条产生式有没有‘|’
j = indexofor(j,s);//定位到下一条‘|’
j++;
if(s.charAt(0) != s.charAt(j)){
fir(s,j,vn,vt,verbs);//求关于这条产生式的first集
}
}
}
}
first[vn(c,vn)][vt.length] = true;//标记已经求过这个非终结符的first集
}
//求某一个非终结符的first集
void first_final(char vn[],char vt[],String verbs[]){
int i;
for(i=0;i<vn.length;i++){
if(!first[i][vt.length] ){
//当这个非终结符的first集还没求,求first集
first(vn[i],vn,vt,verbs);
}
}
}
//求所有非终结符的first集
void fol(String s,int j,char vn[],char vt[],String verbs[]){
int i;
if(j == s.length()-1 ||(j < s.length()&& s.charAt(j+1) == '|')){
if(s.charAt(0) != s.charAt(j)){
if(follow[vn(s.charAt(0),vn)][vt.length] == false){
//如果左边非终结符的follow集还没求,先求左边
follow(s.charAt(0),vn,vt,verbs);
}
for(i=0;i<vt.length;i++){
if(follow[vn(s.charAt(0),vn)][i] == true){
//把左侧非终结符的follow集给i
follow[vn(s.charAt(j),vn)][i] = true;
}
}
}
}
if(j<s.length()-1 && s.charAt(j+1) != '|'){
//i右侧还有字符
if(vt(s.charAt(j+1),vt) != -1){
//右侧字符是终结符
if(vt[vt(s.charAt(j+1),vt)] != '@'){
//同时右侧字符不是空,将右侧字符写入i的follow集中
follow[vn(s.charAt(j),vn)][vt(s.charAt(j+1),vt)] = true;
}
}
else{
//右侧字符是非终结符
for(i=0;i<vt.length;i++){
if(first[vn(s.charAt(j+1),vn)][i] == true && vt[i] != '@'){
//把右侧字符的first集-@给i的follow集
follow[vn(s.charAt(j),vn)][i] = true;
}
}
if(s.charAt(0) == s.charAt(j)){
return;
}
boolean flag = true;//右侧非终结符的first集中有@时为true
for(i=j+1;i<s.length();i++){
if(vt(s.charAt(i),vt) != -1){
//右侧字符有终结符
flag = false;
break;
}
if(s.charAt(i) == '|'){
break;//遇到‘|’跳出
}
if(first[vn(s.charAt(i),vn)][vt('@',vt)] == false){
flag = false;
}
}
if(flag){
//当前字符的右侧字符的first集里有@
if(follow[vn(s.charAt(0),vn)][vt.length] == false){
//左侧非终结符的follow集还未求
follow(s.charAt(0),vn,vt,verbs);
}
else{
for(i=0;i<vt.length;i++){
if(follow[vn(s.charAt(0),vn)][i] == true){
follow[vn(s.charAt(j),vn)][i] = true;
//把左侧字符的follow集给右侧字符
}
}
}
}
}
}
}
//求某一行产生式的follow集
void follow(char c,char vn[],char vt[],String verbs[]){
if(c == 'E'){
follow[vn('E',vn)][vt('#',vt)] = true;
//开始符号E的follow集中有#
}
int i,j;
String s;
for(i=0;i<verbs.length;i++){
s = verbs[i];
for(j=3;j<s.length();j++){
if(c == s.charAt(j)){
fol(s,j,vn,vt,verbs);//此条产生式右侧有c
}
}
}
follow[vn(c,vn)][vt.length] = true;//标记此非终结符的follow集已经求过
}
//求某一个非终结符的follow集
void follow_final(char vn[],char vt[],String verbs[]){
int i;
for(i=0;i<vn.length;i++){
if(follow[i][vt.length] == false){
follow(vn[i],vn,vt,verbs);//当这个非终结符的follow集还没求,求follow集
}
}
}
//求所有非终结符的follow集
void ana(int j ,int i , String s ,int m,char vn[],char vt[],String verbs[]){
char u = verbs[i].charAt(0);//u为此条产生式左边字符
int k;
if(vt(verbs[i].charAt(j),vt) != -1){
//j是终结符
if(verbs[i].charAt(j) != '@'){
//且不是@
analyse[vn(u,vn)][vt(verbs[i].charAt(j),vt)] = s;//写入s
}
else{
//是@
for(k=0;k<vt.length-1;k++){
if(follow[vn(u,vn)][k] == true){
analyse[vn(u,vn)][k] = s;
//是@就代表左侧first集有@,就要把左侧的follow集加到表中
}
}
}
}
else{
//i是非终结符
for(k=0;k<vt.length-1;k++){
//为了避免写入@
if(first[vn(verbs[i].charAt(j),vn)][k] == true){
//右侧是非终结符,他的first集就是左侧的first集,写进表里
analyse[vn(u,vn)][k] = s;
}
}
if(first[vn(verbs[i].charAt(j),vn)][vt('@',vt)] == true){
//右侧的first集里有@,就是左侧first集有@,左侧follow集写进表里
if(j == m-1){
//i为|前的最后一个字符或产生是最后一个字符
//此时已到最后一个,可以判断每个字符的first集中都有@
//即:左侧字符的first集 中有@
for(k=0;k<vt.length-1;k++){
if(follow[vn(u,vn)][k] == true){
//左侧follow集
analyse[vn(u,vn)][k] = s;
}
}
}
else{
j++;
ana(j,i,s,m,vn,vt,verbs);
//规则四,此时扫描判断右侧每个非终结符的first集中都有@
}
}
}
}
//将某一个产生式填入表中
void create(String verbs[],char vn[],char vt[]){
int i,j,k;
String s;
for(i=0;i<verbs.length;i++){
j=3;
while(j<verbs[i].length()){
k=indexofor(j,verbs[i]);
//k是|
if(k == -1){
k = verbs[i].length();
}
s = verbs[i].substring(j,k);//s是一个没有‘|’的产生式
ana(j,i,s,k,vn,vt,verbs);
j=k+1;
}
}
}
//生成预测分析表
void words(String s,char vn[],char vt[]){
String rule = new String();
String action = new String();
String m = new String();
Stack<Character> temp = new Stack<Character>();//分析栈
temp.setSize(20);//初始化大小
temp.push(new Character('#'));//初始化将#入栈
temp.push(new Character('E'));//将开始符号入栈
rule = " ";
action = "初始化";
char u,v;
char str[] ;
String test ;
int i=0,j,k=-1,n;
while(i<s.length()){
n=0;
k++;
str= new char[10];
for(j=0;j<10;j++){
str[j]=' ';
}
rowdata[k][0]=""+k;
for(j=0;j<temp.size();j++){
if(temp.get(j)!= null){
str[n] = temp.get(j);
n++;
}
}
test = new String(str);
rowdata[k][1]=""+test;
rowdata[k][2]=s.substring(i);
rowdata[k][3]=rule;
rowdata[k][4]=action;
u = s.charAt(i);
v=temp.pop();
action="pop"+v;
if(vn(v,vn) != -1){
//栈顶元素为非终结符时
if(analyse[vn(v,vn)][vt(u,vt)] != null ){
//分析表中有产生式
m = analyse[vn(v,vn)][vt(u,vt)];
rule = v+"->"+m;
if(!m.equals("@") ){
//产生式不是@
action=action+",push(";
for(j=m.length()-1;j>-1;j--){
//倒序入栈
action = action + m.charAt(j);
temp.push(new Character(m.charAt(j)));
}
action = action + ")";
continue;
}
else if(m.equals("i")){
action = action+"popF";
temp.push(m.charAt(0));
continue;
}
else{
//产生式是@
rule = v +"->ε";
continue;
}
}
else{
//表内没有产生式
rule = " ";
action = "error1!";
rowdata[k+1][0]=" ";
rowdata[k+1][1]=" ";
rowdata[k+1][2]=" ";
rowdata[k+1][3]=" ";
rowdata[k+1][4]=action;
return;//出错返回
}
}
else{
//栈顶元素是终结符
rule = "";
if(v == u){
//匹配
if(v == '#'){
//结束,成功
action = "accept!";
rowdata[k+1][0]=" ";
rowdata[k+1][1]=" ";
rowdata[k+1][2]=" ";
rowdata[k+1][3]=" ";
rowdata[k+1][4]=action;
return;
}
else{
i++;
action = "pop,getnext(I)";
continue;
}
}
else{
//不匹配
action = "error2!";
rowdata[k+1][0]=" ";
rowdata[k+1][1]=" ";
rowdata[k+1][2]=" ";
rowdata[k+1][3]=" ";
rowdata[k+1][4]=action;
return ;//出错返回
}
}
}
}
}
窗口部分和LR没什么区别