发布时间 : 星期四 文章编译原理实验报告3-LL(1)文法构造更新完毕开始阅读
}
}
}
gp->P[i - 1].insert(0, 1, ch_i); for (; h <= s; h++) { }
gp->P[m - 1] += \;
gp->P[i - 1].erase(gp->P[i - 1].size() - 1, 1);
if (flagpos[h]) { }
splitstr[h] += newWord;
gp->P[i - 1] = gp->P[i - 1] + splitstr[h] + \;
simplify(gp); //化简无用的产生式
提取左因子(包括辅助函数):
//对字符串数组排序
void str_sort(string *str, int num) { }
/*子函数,提取左因子*/
void remove_left_gene(struct grammar *gp) {
char ch, newWord;
for (rule_a = 0; rule_a < m; rule_a++) {
int bre = -1; int oldpo = 0; int num = 0, ps = 3; string str[30],restr[30];
//前者用于判断,需要保持原样,后者用于对有公
//分割替换后的产生式
//遍历所有产生式
//标记已对产生式进行过左因子的提取
int rule_a, i, j, k, l, matchnum,oldmatchnum, resize,size; int i, j;
for (i = 0; i < num; i++) { }
for (j = i + 1; j < num; j++) { }
if (str[i] > str[j])
str[i].swap(str[j]);
共左因子的候选进行提取,可变
while (ps != gp->P[rule_a].size() + 1) { }
str_sort(str, num); str_sort(restr, num);
//对所有候选按ASCII码进行排序,以便于简
str[num] = strsplit(gp->P[rule_a], ps); restr[num] = str[num]; ps = ps + str[num].size() + 1; num++;
化对公共左因子的判断,只需先对前面候选判断
int ca_i; string Pa = \;
Pa.insert(0, 1, gp->Vn[rule_a]);
for (ca_i = 0; ca_i < num; ca_i++) { //对排序后的候选进行重组并存入文法 }
gp->P[rule_a] = Pa; int ipo = 0;
ipo = 0; size = 0; resize = 0; oldmatchnum = 0; int i_s = str[i].size(); for (j = 0; j < i_s; j++) { }
/*有公共左因子的处理过程*/
if (matchnum != oldmatchnum || j == i_s) {
bre ++;
string match, repstr, can, newP; match = str[i].substr(0, j);
//获取公共左因子
matchnum = 0; ch = str[i][j]; int kf = num;
for (k = i + 1; k < num && k < kf; k++) { //对i之后的候选进行判断,是否有与i对应 }
if (j == 0) { } else { }
if (oldmatchnum != matchnum) break;
//判断是否有公共左因子是i的第一个字符的
if (str[k][j] == ch) { } else { }
break; matchnum++;
//有公共左因子
//对候选的逐个字符遍历
//标记除了本身,有几个候选有公共左因子
//辅助免除对已判断过有左因子的候选的遍历
//遍历候选
for (i = 0; i < num; i++,i += ipo) {
if (ca_i == num - 1) else
Pa += str[ca_i] + \; Pa += str[ca_i];
的公共左因子
情况,有则特别处理
if (matchnum == 0)
break;
else { oldmatchnum = matchnum; kf = i + 1 + oldmatchnum; }
}
}
}
}
newWord = GetWord(gp->Vn); gp->Vn[m] = newWord; m++; newP = \;
newP.insert(0, 1, newWord); repstr = match + newWord; int renum = num; if (bre > 0) { }
//得到新的非终结符
//将新非终结符存入文法
//得到要被替换的有公共左因子的所有候选
//若对同一产生式还存在另一个公共左因子(之前
提取过一次左因子),需进行特别处理
size = resize = 0; renum = 0; ps = 3;
while (ps != gp->P[rule_a].size() + 1) { }
//分割变化后
的产生式
restr[renum] = strsplit(gp->P[rule_a], ps); ps = ps + restr[renum].size() + 1; renum++;
/*将已经提取过左因子的以候选为单位的字符串重新组合成产生式(包括新产生for (l = 0; l <= i - oldpo + oldmatchnum; l++) { }
gp->P[rule_a].replace(resize + 3, size + oldmatchnum, repstr); //原产生式以替换的方if (i + 1 + oldmatchnum > num) { break; } else oldpo = ipo = oldmatchnum;
if (l >= i - oldpo) { } else { }
resize += restr[l].size(); resize++;
size += restr[l].size(); can = restr[l].substr(j); if (can == \)
can = \;
if (l == i - oldpo + oldmatchnum) newP += can; else newP = newP + can + \; gp->P[m - 1] = newP;
式)*/
式进行改变
4、 主程序代码;
#include
struct grammar { };
int m = 0, n = 0;
char GetBC(FILE* fpi) { }
/*
整型函数,读入一行产生式分析出文法成员,参数分别是输入文本的文件指针、文法
第几行的产生式
*/
结构体的指针
void scanP(FILE* fpi,struct grammar *gp) {
char ch; string str; if (feof(fpi))
//存入一条产生式 //到达文件尾则返回
//读入产生式左部的非终结符
//将非终结符存入结构体
return;
char ch; do {
ch = fgetc(fpi); } while (ch == ' '); return ch;
//子函数,用于读取一个非空格字符
//全局变量,分别表示最近存入结构体的非终结符与终
结符是字符数组的第几个位置
char Vn[20]; char Vt[20]; char S;
string P[20];
//使用结构体定义文法 //非终结符 //终结符 //开始符号
//产生式
ch = GetBC(fpi);
if (ch >= 'A' && ch <= 'Z') {
str += ch; gp->Vn[m] = ch; m++;
ch = GetBC(fpi); if (ch == '-') {
str += ch; ch = GetBC(fpi); if (ch == '>') {
str += ch; while (1) {
ch = GetBC(fpi); if (ch == '\\n' || ch == ';')
break;
//读入换行符