对给定文法,采用JAVA语言实现求其项目集族。
算法设计:
* 1.遍历项目集,首先取出第i个项目集
* 2.遍历第i个项目集,取出所有点点后的字符加入缓存中
* 3.创建新的项目集
* 4.循环取出缓存中的字符(表示可读入状态),
* 如若当前状态集中有当前取出的缓存字符,则创建一个新的项目(点点后移),并在新的项目集中加入此项目(创建以此项目)
* 5.如果items中无此项目,则加入
* @param G
代码实现如下:
private void createFamily(Grammar G) { //够造项目集
/**
* 保存非终结符与终结符
*/
List<String> non_terminal = G.getNon_terminals();
List<String> terminal = G.getTerminals();
List<Follow> follows = G.getFollows();
//在终结符里添加结束字符
terminal.add("#");
int number = 1;
for (int i = 0; i < itemsets.size(); i++) {// itemsets.size是动态的,会随着程序的执行而变化
List<String> caching = new ArrayList<String>();// 缓存
ItemSet iitemset = itemsets.get(i);// 用iitemset表示第i个项目集
/* 遍历一遍第i个项目集,将所有出现在点后面的字符添加到缓存中 */
for (int j = 0; j < iitemset.items.size(); j++) {
Item jitem = iitemset.items.get(j);// 用jitem表示第j个项目
if (jitem.getPoint() >= jitem.getRightParts().size()) { //如S->CS·
// 如果·后面没有东西,就跳过这个项目的判断。
continue;
}
if (!caching.contains(jitem.rightParts.get(jitem.getPoint()))) {
// 如果·后面有东西,将这个东西添加到caching缓存中。
caching.add(jitem.rightParts.get(jitem.getPoint()));
}
}
//caching保留的是本次循环项目集i后,i所有项的点点后面的字符
/* 遍历缓存,表示逐个读入状态 */
for (int j = 0; j < caching.size(); j++) {
String jcache = caching.get(j);// jcache表示第j个可以读入的状态
ItemSet newITS = new ItemSet();
for (int k = 0; k < iitemset.items.size(); k++) {
List<String> rightpart = iitemset.items.get(k).rightParts;
int point = iitemset.items.get(k).point;
if (point < rightpart.size()) {
if (rightpart.get(point).equals(jcache)) {
// 如果点后面是有东西的,并且项目集中某个项目的point后的字符和 缓存中的第k个字符相同。也就是E->·E-T读入字符E
//把当前jcache引出的均加入
Item item = new Item(iitemset.items.get(k));// 创建一个新的项目
newITS.initItemSet(item, G);// 把新创建的项目加入到新的项目集中
}
}
}
/* 如果新的状态集不存在于项目集规范族中,就将其添加到项目集规范族中 */
int l = 0;
for (l = 0; l < itemsets.size(); l++) {
if(newITS.EqualsItems(itemsets.get(l),newITS)){
break;
}
//if(itemsets.get(l).contains(newITS)){
// break;
//}
}
if (l >= itemsets.size()) {
newITS.number = number;
itemsets.add(newITS);
number++;
if(terminal.contains(jcache)){
//如果为终结符移机
}
}
}
}
}