编译原理:java实现求first集

2022-10-21  本文已影响0人  树里的熊

求first集合的思路还是非常清晰的,按照书上的算法。
定义:first(A)={a| A ==>+ aβ }

代码说明:
first:Map<String,List<String>> key:Vn,Vt value:对应var的first集
terminals:Set<String>终结符集合
nonTerminals:Set<String>非终结符集合

实现思路:
直接看代码就好啦~
额外需要说的一点是!这里一定要注意深拷贝问题,因为哪怕是用putAll也并没有完全深拷贝,因为我的map的value是Set,仍然是引用,所以一定要自己手动new一个set,然后add进去。才真正实现了深拷贝。

public void generateFirstCollection() {
    //所有终结符的first集合就是自己
    for (String ter : terminals) {
      Set<String> set = new HashSet<>();
      set.add(ter);
      first.put(ter, set);
    }
    //非终结符注册,避免判断first.containsKey,更简洁
    for (String non : nonTerminals) {
      Set<String> set = new HashSet<>();
      first.put(non, set);
    }

    while (true) {
      //手动深拷贝
      Map<String, Set<String>> firstClone = new HashMap<>();
      for(Entry<String,Set<String>>entry:first.entrySet()){
        Set<String>set=new HashSet<>();
        for(String s:entry.getValue() ){
          set.add(s);
        }
        firstClone.put(entry.getKey(),set);
      }

     for (Production p : productions) {
        String rightHead = p.getRights().get(0);
        // * - 有产生式A ==> αβ if (α ∈ VT) then add α to first(A)
        if (terminals.contains(rightHead)) {
          Set<String> set = firstClone.get(p.getLeft());
          set.add(rightHead);
          firstClone.replace(p.getLeft(), set);
        }
        if (nonTerminals.contains(rightHead) && firstClone.containsKey(rightHead)) {
          Set<String> set = firstClone.get(p.getLeft());
          set.addAll(firstClone.get(rightHead));
          firstClone.replace(p.getLeft(), set);
        }
      }
      //判断有无改变
      if (isSameMap(first, firstClone)) {
        return;
      } else {
        first = firstClone;
      }
    }
  }
上一篇 下一篇

猜你喜欢

热点阅读