设计上下文无关文法的变换算法实验目的 编程实现上下文无关文法的变换算法,用于消除文法中的ε产生式、单产生式、以及无用符号。
import java.util.*;
public class CFG {
//以#为空
class Transfer {
String beg;
List<String> to;
Transfer(){
beg =new String();
to =new ArrayList<>();
}
}
List<String> nonterminal=new ArrayList<>();//非终结符的集合
List<String> terminal=new ArrayList<>();//终结符的集合
List<String> allterminal=new ArrayList<>();
List<String> conversion=new ArrayList<>();//有空转换的字符
String Begin =new String();
void AddS1(){
Transfer transfer=cfg.get(Begin);
Transfer trans=new Transfer();
trans.beg="S1";
for(String s1:transfer.to){
trans.to.add(s1);
}
cfg.put("S1",trans);
nonterminal.add("S1");
allterminal.add("S1");
}
HashMap<String, Transfer> cfg=new HashMap<>();
void InputProduction(){
Scanner sc=new Scanner(System.in);
System.out.println("请输入有多少个非终结符,第一个为起始符");
int i,num=sc.nextInt();
for (i = 0; i < num; i++) {
System.out.println("请输入非终结符符号");
String name= sc.next();
nonterminal.add(name);
if(!allterminal.contains(name)){
allterminal.add(name);
}
Transfer transfer = new Transfer();
transfer.beg =name;
System.out.println("请输入生成式个数");
int num1=sc.nextInt();
System.out.println("请输入生成式,以#为空");
for (int j = 0; j < num1; j++) {
String get= sc.next();
if(get.equals("#")){
conversion.add(name);
}
char[] gets=get.toCharArray();
for (char c:gets){
String str=new String(new char[]{c});
if(!allterminal.contains(str)){
allterminal.add(str);
}
}
transfer.to.add(get);
}
cfg.put(name,transfer);
if(i==0){
Begin=name;
if(transfer.to.contains("#")){
AddS1();
}
}
}
terminal.addAll(allterminal);
terminal.removeAll(nonterminal);
// System.out.println(terminal);
// System.out.println(nonterminal);
// System.out.println(allterminal);
}
void OutputProduction(){
System.out.println("非终结符有:"+nonterminal);
System.out.println("终结符有:"+terminal);
for (Transfer t: cfg.values()) {
for (String str:t.to) {
System.out.println(t.beg +"->"+str);
}
}
}
void RemoveEpsilon(){
boolean flag=true;
while (flag){
List<String> newconversion=new ArrayList<>();
flag=false;
for (int i = 0; i < conversion.size(); i++) {
Transfer trans=cfg.get(conversion.get(i));
if(trans.to.contains("#")){
trans.to.remove("#");//删去直接置空的符号
for(Transfer tra:cfg.values()){//在其他式子中删去置空的非终结符
List<String> toadd=new ArrayList<>();
if(!conversion.contains(tra.beg)&&tra.to.contains(trans.beg)&&!tra.to.contains("#")){
toadd.add("#");
if(!tra.beg.equals("S1")){
flag = true;
newconversion.add(tra.beg);
}
}
for (String str:tra.to){
if (str.contains(conversion.get(i))){
Recursion(conversion.get(i),str,0,toadd);
}
}
for (String add:toadd) {
if(!tra.to.contains(add)){
tra.to.add(add);
}
}
}
}
}
conversion.addAll(newconversion);
}
}
void Recursion(String target, String ori, int index, List<String> toadd) {
if (index == -1) {
return;
}
index = ori.indexOf(target, index);
if (index != -1) {
String nstr;
if (index == 0) {
nstr = ori.substring(1);
} else {
nstr = ori.substring(0, index) + ori.substring(index + 1);
}
Recursion(target, ori, index+1, toadd);
if (!toadd.contains(nstr)&&!nstr.equals("")) {
toadd.add(nstr);
}
Recursion(target, nstr, index, toadd);
}
}
void EliminateUnitProduction(){
boolean flag=true;
while (flag){
flag=false;
for(Transfer tra:cfg.values()){//移除单生成式
List<String> strs = new ArrayList<>();
for (String str: tra.to) {
if(nonterminal.contains(str)){
flag=true;
strs.add(str);
}
}
for (String ss:strs) {
tra.to.remove(ss);
Transfer t=cfg.get(ss);
List<String> anewss=new ArrayList<>();
for (String gets:t.to) {
if(!tra.to.contains(gets)){
anewss.add(gets);
}
}
tra.to.addAll(anewss);
}
}
}
}
void EliminateUselessSymbols(){
List<String> toEnd=terminal;
boolean keep=true;
while (keep){
keep=false;
for(Transfer tra:cfg.values()){//找到可以终结的字符
for (String str: tra.to){
char[] chars=str.toCharArray();
boolean flag=true;
for (char ch:chars) {
if(!toEnd.contains(String.valueOf(ch))){
flag=false;
}
}
if(flag&&!toEnd.contains(tra.beg)){
toEnd.add(tra.beg);
keep=true;
break;
}
}
}
}
//可以终结的非终结符
List<String> nontoend=new ArrayList<>();
for(String ss:nonterminal){
if(toEnd.contains(ss)){
nontoend.add(ss);
}
}
//不可以终结的非终结符
List<String> cannot=new ArrayList<>();
cannot.addAll(nonterminal);
cannot.addAll(toEnd);
cannot.removeAll(toEnd);
allterminal.removeAll(cannot);
nonterminal=nontoend;
terminal.removeAll(nonterminal);
for (String s:cannot) {//删去不可终结的非终结符
cfg.remove(s);
}
for (Transfer tr: cfg.values()) {
List<String> todel=new ArrayList<>();
for (String st: tr.to){
for (String sj:cannot) {
if(st.contains(sj)){
todel.add(st);
break;
}
}
}
tr.to.removeAll(todel);
}
}
public static void main(String[] args) {
CFG cfg=new CFG();
cfg.InputProduction();
cfg.RemoveEpsilon();
cfg.EliminateUnitProduction();
cfg.EliminateUselessSymbols();
cfg.OutputProduction();
}
}