编译原理 词法分析 Java代码实现

词法分析代码步骤

借助GraphViz

生成NFA,DFA,miniDFA等借助GraphViz工具
环境配置详情参见https://blog.csdn.net/qq_18208435/article/details/70464654

生成逆波兰表达式

对正则表达式添加操作符

如a(a|b)*b应该改为a·(a|b)*·b

给定输入字符串st,添加操作符,代码如下:

//假定字符串输入为小写字母。
for(int i = 0; i < st.length(); i++) {
	if(i-1>=0) {
        char t0 = st.charAt(i-1);
		char t1 = st.charAt(i);
        if((t0 >= 'a' && t0 <= 'z') && (t1 >= 'a' && t1 <= 'z')) {//ab->a·b
            st.insert(i, "·");
        }
        else if(t0 == ')' && (t1 >= 'a' && t1 <= 'z')) {//)a->)·a
            st.insert(i, "·");
        }
        else if((t0 >= 'a' && t0 <= 'z') && t1=='(') {//a(->a·(
            st.insert(i, "·");
        }
        else if(t0 == '*' && (t1 >= 'a' && t1 <= 'z')) {//*a->*·a
            st.insert(i,"·");
        }
        else if(t0 == '*' && t1 == '('){//*(->*·(
            st.insert(i,"·");
        }
    }
}

生成逆波兰表达式

采用调度场算法

  • 顺序扫描表达式,如果当前字符是字母(优先级为0的符号) ,则直接输出;如果当前字符为运算符或者括号(优先级不为 0的符号),则判断:
    • 若当前运算符为’(’ ,直接入栈;
    • 若为’)’ ,出栈并顺序输出运算符直到遇到第一个’(’ ,遇到的第一个 '('出栈但不输出;
    • 若为其它,比较运算符栈栈顶元素与当前元素的优先级:
      • 如果栈顶元素是’(’,当前元素直接入栈
      • 如果栈顶元素优先级>=当前元素优先级,出栈并顺序输出运算符直到 栈顶元素优先级<当前元素优先级,然后当前元素入栈
      • 如果栈顶元素优先级<当前元素优先级,当前元素直接入栈
  • 重复上述操作直至表达式扫描完毕
  • 顺序出栈并输出运算符直到栈元素为空

代码实现:

StringBuilder ans = new StringBuilder();
//char[] Table= {'*','·','|'};
Map<Character,Integer> map = new HashMap<Character,Integer>();//数字表示优先级
map.put('|', 1);
map.put('·', 2);
map.put('*', 3);
Stack<Character> stack = new Stack<>();
for(int i = 0; i < st.length(); i++) {
    char t = st.charAt(i);
    if(t >= 'a' && t <= 'z') {
        ans.append(t);
    }
    else if(t == '(' || stack.empty()) {
        stack.push(t);
    }
    else if(t == ')') {
        char top = stack.pop();
        while(top!='(') {
            ans.append(top);
            top = stack.pop();
        }
    }
    else {
        char top = stack.pop();
        if(top == '(') {
            stack.push(top);
            stack.push(t);
        }
        else {
            if(map.get(top) >= map.get(t)){
                while(map.get(top) >= map.get(t)) {
                    ans.append(top);
                    if(!stack.empty()) {
                        top = stack.pop();
                        if(top == '(') {
                            stack.push(top);
                            stack.push(t);
                            break;
                        }
                    }
                    else {
                        stack.push(t);
                        break;
                    }
                }
            }
            else {
                stack.push(top);
                stack.push(t);
            }
        }
    }
}
while(!stack.empty()) {
    ans.append(stack.pop());
}

生成NFA

采用存储边的思想,利用如下数据结构将每一条边存储:

public class Part{
    public int s;//存储一条边的start
    public int e;//存储一条边的end
    public char op;//存储一条边上的op
    public Part(int s,int e,char op) {
        this.s = s;
        this.e = e;
        this.op = op;
    }
}

通过处理逆波兰表达式得到最终的NFA,处理流程如下:

对你逆波兰表达式扫描

  • 如果当前字符为字母,则增加一条新的边Part(num,num+1,op),并将该部分两端的节点(num,num+1)入栈

  • 如果当前字符为’ · ',则从Stack中取出两条边,p1,p2。增加三条边:

    new Part(p1.e,p2.s,'ε')
    new Part(num,p1.s,'ε')
    new Part(p2.e,++num,'ε')
    

    并将该部分两端的节点(num-1,num)入栈

  • 如果当前字符为’ | ',则从Stack中取出两条边,p1,p2。增加四条边:

    v.add(new Part(num,p1.s,'ε'));
    v.add(new Part(num,p2.s,'ε'));
    ++num;
    v.add(new Part(p1.e,num,'ε'));		
    v.add(new Part(p2.e,num,'ε'));
    

    并将改部分两端的节点(num-1,num)入栈

  • 如果当前字符为’ * ',则从Stack中取出一条边,p。增加四条边:

    v.add(new Part(p.e,p.s,'ε'));
    v.add(new Part(num,p.s,'ε'));
    ++num;
    v.add(new Part(num-1,num,'ε'));
    v.add(new Part(p.e,num,'ε'));
    

    并将该部分两端的节点(num-1,num)入栈

注:完成后stack中栈底的边p,p.s为整个NFA的start,p.e为整个NFA的end(终态)。

while(!stack.isEmpty()) {
    p = stack.pop();
}
start = p.s;
end = p.e;

生成DFA

这部分比较思路上比较简单,主要是做一下几个方面的工作

  • 求ε闭包(状态合并)

  • 状态合并后标记终态(含NFA终态节点的DFA节点都是终态,可能不止一个)

    注:含NFA初态节点的DFA节点为初态,只有一个

  • 将合并后的节点重新编号,重新将DFA的边记录

代码实现思路为:

  1. 求NFA start节点的epsilon闭包
  2. 求闭包内节点通过不同操作符到达的节点的epsilon闭包,如果该节点是一个新的节点,则重复2操作直至没有新的节点产生

以下为关键代码实现:

//求start节点的epsilon闭包
public void GetIEpsilon(TreeSet<Integer> s,int start){
    vis[start] = 1;
    s.add(start);
    for (Part part : v) {
        if (part.s == start && part.op == 'ε') {
            //s.add(v.get(i).e);
            if (vis[part.e] == 0)
                GetIEpsilon(s, part.e);
        }
    }
}
//求经过op操作符为a所到达的点的epsilon闭包,存入一个TreeSet
public void GetI(TreeSet<Integer> s,int start,char a){
    for (Part part : v) {
        if (part.s == start && part.op == a) {
            s.add(part.e);
            Arrays.fill(vis, 0);
            GetIEpsilon(s, part.e);
        }
    }
}

//将含NFA的start和end节点标记出来,PointSet[i]为DFA的节点,集合内容为NFA的节点编号。
public void GetSE(){
    System.out.println("start:"+ TurnNFA.start);
    System.out.println("end:"+ TurnNFA.end);
    for(int i = 0; i < setNum; i++){
        if(pointSet[i].contains(TurnNFA.start)){
            start.add(i+1);//只有一个
        }
        if(pointSet[i].contains(TurnNFA.end)){
            end.add(i+1);
        }
    }
    Iterator<Integer> itS = start.iterator();
    Iterator<Integer> itE = end.iterator();
    while(itS.hasNext()){
        System.out.print(itS.next()+" ");
    }
    System.out.println();
    while(itE.hasNext()){
        System.out.print(itE.next()+" ");
    }
    System.out.println();
}
//求DFA的状态
while(visNum < setNum){
    itOp = opSet.iterator();
    while(itOp.hasNext()) {
        itSet = pointSet[visNum].iterator();
        char opNow = itOp.next();
        while (itSet.hasNext()) {
            GetI(pointSet[setNum],itSet.next(),opNow);
        }
        if(pointSet[setNum].size()!=0){
            int flag = 0;
            int pointSame=0;
            for(int i = 0; i < setNum; i++){
                if(pointSet[i].equals(pointSet[setNum])){
                    pointSame = i;
                    flag = 1;
                    break;
                }
            }
            if(flag == 0){//没有相同的集合元素
                edgeDFA.add(new Part(visNum+1,setNum+1,opNow));
                setNum++;
                pointSet[setNum] = new TreeSet<>();
            }
            else{//有集合相同的元素
                edgeDFA.add(new Part(visNum+1,pointSame+1,opNow));
                pointSet[setNum].clear();
            }
        }
    }
    visNum++;
}

生成miniDFA

这部分的实现思路没什么复杂的地方,关键在于找到相同的状态,合并。

关键代码

//state[x][y]二维数组表示x通过操作符‘a’+y到达的状态
//group[i]表示DFA的状态i对应的区号
while(true){
    for (Part part : edge) {
        state[part.s][part.op - 'a'] = groupId[part.e];
    }
    int Num = 1;
    for(int i = 1; i <= setNum; i++){
        int flag = 0;
        for(int j = 1; j < i; j++){
            if(cmp(state[j],state[i]) && groupId[i] == groupId[j]){
                flag = 1;
                newGroupId[i]=newGroupId[j];
                break;
            }
        }
        if(flag == 0) {
            newGroupId[i] = Num;
            Num++;
        }
    }
    if(cmp(groupId,newGroupId))//旧区号和新区号相同,跳出。
        break;
    else{
        groupId = Arrays.copyOf(newGroupId,newGroupId.length);
    }
}

Code Origanization

代码组织结构

//GraphViz.java
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;


public class  GraphViz{
    private String runPath="";
    private String dotPath="";
    private String runOrder="";
    private String dotCodeFile="dotcode.txt";
    private String resultGif="dotGif";
    private StringBuilder graph = new StringBuilder();

    Runtime runtime=Runtime.getRuntime();

    public void run() {
        File file=new File(runPath);
        file.mkdirs();
        writeGraphToFile(graph.toString(), runPath);
        creatOrder();
        try {
            runtime.exec(runOrder);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void creatOrder(){
        runOrder+=dotPath+" ";
        runOrder+=runPath;
        runOrder+="\\"+dotCodeFile+" ";
        runOrder+="-T png ";
        runOrder+="-o ";
        runOrder+=runPath;
        runOrder+="\\"+resultGif+".png";
        System.out.println(runOrder);
    }

    public void writeGraphToFile(String dotcode, String filename) {
        try {
            File file = new File(filename+"\\"+dotCodeFile);
            if(!file.exists()){
                file.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(dotcode.getBytes());
            fos.close();
        } catch (java.io.IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public GraphViz(String runPath,String dotPath) {
        this.runPath=runPath;
        this.dotPath=dotPath;
    }

    public void add(String line) {
        graph.append("\t"+line+"\n");
    }

    public void addln(String line,String factor) {
        graph.append("\t"+line + "[label=\""+factor+"\"]"+"\n");
    }

    public void addln() {
        graph.append('\n');
    }

    public void start_graph() {
        graph.append("digraph G {\n") ;
    }

    public void end_graph() {
        graph.append("}") ;
    }
} 
//ReversePolish.java
import java.util.*;

public class ReversePolish {
	public StringBuilder s;

	public ReversePolish(StringBuilder st)
	{
		for(int i = 0; i < st.length(); i++) {
			if(i-1>=0) {
				char t0 = st.charAt(i-1);
				char t1 = st.charAt(i);
				if((t0 >= 'a' && t0 <= 'z') && (t1 >= 'a' && t1 <= 'z')) {//ab
					st.insert(i, "·");
				}
				else if(t0 == ')' && (t1 >= 'a' && t1 <= 'z')) {
					st.insert(i, "·");
				}
				else if((t0 >= 'a' && t0 <= 'z') && t1=='(') {
					st.insert(i, "·");
				}
				else if(t0 == '*' && (t1 >= 'a' && t1 <= 'z')) {
					st.insert(i,"·");
				}
				else if(t0 == '*' && t1 == '('){
					st.insert(i,"·");
				}
			}
		}
		System.out.println(st);
		StringBuilder ans = new StringBuilder();
		//char[] Table= {'*','·','|'};
		Map<Character,Integer> map = new HashMap<Character,Integer>();
		map.put('|', 1);
		map.put('·', 2);
		map.put('*', 3);
		Stack<Character> stack = new Stack<>();
		for(int i = 0; i < st.length(); i++) {
			char t = st.charAt(i);
			if(t >= 'a' && t <= 'z') {
				ans.append(t);
			}
			else if(t == '(' || stack.empty()) {
				stack.push(t);
			}
			else if(t == ')') {
				char top = stack.pop();
				while(top!='(') {
					//System.out.println(top);
					//System.out.print(stack+"\n");
					ans.append(top);
					top = stack.pop();
				}
			}
			else {
				//System.out.println(t);
				char top = stack.pop();
				if(top == '(') {
					stack.push(top);
					stack.push(t);
				}
				//System.out.println(a+"----"+b);
				else {
					if(map.get(top) >= map.get(t)){
						while(map.get(top) >= map.get(t)) {
							ans.append(top);
							if(!stack.empty()) {
								top = stack.pop();
								if(top == '(') {
									stack.push(top);
									stack.push(t);
									break;
								}
							}
							else {
								stack.push(t);
								break;
							}
						}
					}
					else {
						stack.push(top);
						stack.push(t);
					}
				}
			}
			//System.out.print(stack+"\n");
			//System.out.print(ans+"\n");
		}
		while(!stack.empty()) {
			ans.append(stack.pop());
		}
		s = ans;
	}
	public static void main(String[] args) {
		StringBuilder s = new StringBuilder();
		s.append("((a*)*|(b|a))*cd*");
		//System.out.println(s);
		ReversePolish r = new ReversePolish(s);
		System.out.println(r.s);
	}
}

//Part.java
public class Part{
    public int s;
    public int e;
    public char op;
    public Part(int s,int e,char op) {
        this.s = s;
        this.e = e;
        this.op = op;
    }
}
//TurnNFA.java

import java.util.*;
public class TurnNFA {
	public static ArrayList<Part> v;
	public static int start;
	public static int end;
	public TurnNFA(StringBuilder s) {
		v = new ArrayList<>(10000);
		ArrayDeque<Part> stack = new ArrayDeque<>();
		int num = 1;
		for(int i = 0; i < s.length(); i++) {
			char t = s.charAt(i);
			if(t >= 'a' && t <= 'z'){
				Part p = new Part(num,++num,t);
				stack.push(p);
				v.add(p);
				++num;
			}
			else if(t == '·'){
				Part p2 = stack.pop();
				Part p1 = stack.pop();
				v.add(new Part(p1.e,p2.s,'ε'));
				v.add(new Part(num,p1.s,'ε'));
				v.add(new Part(p2.e,++num,'ε'));
				stack.push(new Part(num-1,num, ' '));
				//stack.push(new Part(p1.s,p2.e,' '));
				++num;
			}
			else if(t == '|'){
				Part p2 = stack.pop();
				Part p1 = stack.pop();
				v.add(new Part(num,p1.s,'ε'));
				v.add(new Part(num,p2.s,'ε'));
				++num;
				v.add(new Part(p1.e,num,'ε'));
				v.add(new Part(p2.e,num,'ε'));
				stack.push(new Part(num-1,num,' '));
				++num;
			}
			else if(t == '*'){
				Part p = stack.pop();
				v.add(new Part(p.e,p.s,'ε'));
				v.add(new Part(num,p.s,'ε'));
				++num;
				v.add(new Part(num-1,num,'ε'));
				v.add(new Part(p.e,num,'ε'));
				stack.push(new Part(num-1,num,' '));
				++num;
			}
		}
		Part p = new Part(0,0,' ');
		while(!stack.isEmpty()) {
			p = stack.pop();
		}
		start = p.s;
		end = p.e;
		drawNFA();
	}
	public void drawNFA(){
		GraphViz gViz=new GraphViz(".\\src\\HomeWork1\\GraphNFA", "D:\\Grapgviz\\Graphviz\\bin\\dot.exe");
		gViz.start_graph();
		gViz.add("node [shape = doublecircle];"+end+";");
		gViz.add("node [shape = circle];");
		for (Part part : v) {
			gViz.addln(part.s + "->" + part.e, "" + part.op);
		}
		gViz.addln("start"+"->"+start," ");
		gViz.end_graph();
		try {
			gViz.run();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		StringBuilder s = new StringBuilder("a*ab·b·*·b·ba|*·");
		TurnNFA t = new TurnNFA(s);
	}
}
//TurnDFA.java
import java.util.*;
public class TurnDFA {
    public static TreeSet<Integer> start;
    public static TreeSet<Integer> end;//存储含有终态的节点
    public static ArrayList<Part> v;
    public static ArrayList<Part> edgeDFA;
    public static TreeSet<Character> opSet;
    public static TreeSet<Integer>[] pointSet;
    public static int setNum = 0;
    public static int[] vis;
    public TurnDFA(StringBuilder s){
        start = new TreeSet<>();
        end = new TreeSet<>();
        v = new ArrayList<>(10000);
        opSet = new TreeSet<>();
        edgeDFA = new ArrayList<>(10000);
        vis = new int[1000];
        Arrays.fill(vis,0);
        TurnNFA tn = new TurnNFA(s);
        TurnNFA.v.sort(new PartComparator());//按Part的start将边排序
        v = new ArrayList<>(TurnNFA.v);
        setNum = 0;//用于记录pointSet的数量
        int visNum = 0;//用于记录已经访问的pointSet的数量
        pointSet = new TreeSet[1000];
        pointSet[0] = new TreeSet<>();
        Arrays.fill(vis,0);//求Epsilon闭包前vis清零
        GetIEpsilon(pointSet[0], TurnNFA.start);//得到start的Epsilon闭包
        //start = 0;
        setNum++;
        pointSet[setNum] = new TreeSet<>();
        System.out.println(pointSet[0]);
        GetEdgeOp(opSet);
        System.out.println(opSet);
        Iterator<Integer> itSet;
        Iterator<Character> itOp;
        while(visNum < setNum){
            itOp = opSet.iterator();
            while(itOp.hasNext()) {
                itSet = pointSet[visNum].iterator();
                char opNow = itOp.next();
                while (itSet.hasNext()) {
                    GetI(pointSet[setNum],itSet.next(),opNow);
                }
                //System.out.println(opNow+" "+pointSet[setNum]);
                if(pointSet[setNum].size()!=0){
                    //edgeDFA.add(new Part(visNum+1,setNum+1,opNow));
                    int flag = 0;
                    int pointSame=0;
                    for(int i = 0; i < setNum; i++){
                        if(pointSet[i].equals(pointSet[setNum])){
                            pointSame = i;
                            flag = 1;
                            break;
                        }
                    }
                    if(flag == 0){//没有相同的集合元素
                        edgeDFA.add(new Part(visNum+1,setNum+1,opNow));
                        setNum++;
                        pointSet[setNum] = new TreeSet<>();
                    }
                    else{//有集合相同的元素
                        edgeDFA.add(new Part(visNum+1,pointSame+1,opNow));
                        pointSet[setNum].clear();
                    }
                }
            }
            visNum++;
        }
        for(int i = 0; i < setNum; i++){//测试处,输出DFA每一个PointSet,后期注释
            System.out.println(pointSet[i]);
        }
        for (Part part : edgeDFA) {//测试处,输出DFA的每一条边,后期注释
            System.out.println(part.s + " " + part.e + " " + part.op);
        }
        System.out.println(setNum);//测试处,输出DFA的个数
        GetSE();//
        drawGraph();
    }
    public void GetI(TreeSet<Integer> s,int start,char a){
        for (Part part : v) {
            if (part.s == start && part.op == a) {
                s.add(part.e);
                Arrays.fill(vis, 0);
                GetIEpsilon(s, part.e);
            }
        }
    }
    public void GetIEpsilon(TreeSet<Integer> s,int start){
        vis[start] = 1;
        s.add(start);
        for (Part part : v) {
            if (part.s == start && part.op == 'ε') {
                //s.add(v.get(i).e);
                if (vis[part.e] == 0)
                    GetIEpsilon(s, part.e);
            }
        }
    }
    public void GetEdgeOp(TreeSet<Character> s){
        for (Part part : v) {
            if (part.op != 'ε') {
                s.add(part.op);
            }
        }
    }
    public void GetSE(){//获取含有start的节点集合以及含有end的节点集合
        //TurnNFA tn = new TurnNFA(s);
        System.out.println("start:"+ TurnNFA.start);
        System.out.println("end:"+ TurnNFA.end);
        for(int i = 0; i < setNum; i++){
            if(pointSet[i].contains(TurnNFA.start)){
                start.add(i+1);//只有一个
            }
            if(pointSet[i].contains(TurnNFA.end)){
                end.add(i+1);
            }
        }
        Iterator<Integer> itS = start.iterator();
        Iterator<Integer> itE = end.iterator();
        while(itS.hasNext()){
            System.out.print(itS.next()+" ");
        }
        System.out.println();
        while(itE.hasNext()){
            System.out.print(itE.next()+" ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        StringBuilder s = new StringBuilder("a*ab·b·*·b·ba|*·");
        TurnDFA tn = new TurnDFA(s);
    }
    public void drawGraph(){
        GraphViz gViz=new GraphViz(".\\src\\HomeWork1\\GraphDFA", "D:\\Grapgviz\\Graphviz\\bin\\dot.exe");
        gViz.start_graph();
        gViz.add("node [shape = doublecircle];");
        for (Integer integer : end) {
            gViz.add(integer.toString());
        }
        gViz.add(";");
        gViz.add("node [shape = circle];");
        for (Part part : edgeDFA) {
            gViz.addln(part.s + "->" + part.e, "" + part.op);
        }
        Iterator<Integer> itStart = start.iterator();//只有一个
        gViz.addln("start"+"->"+itStart.next()," ");
        gViz.end_graph();
        try {
            gViz.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class PartComparator implements Comparator<Part>{
    public int compare(Part p1, Part p2){
        return p1.s - p2.s;
    }
}

//TurnMinDFA.java
import com.sun.source.tree.Tree;
import javax.swing.*;
import java.util.*;

public class TurnMinDFA {
    public static ArrayList<Part> edge;
    public static ArrayList<Part> minEdge;
    public static ArrayList<Character> opList;
    public static TreeSet<Integer> end;
    public static int setNum;
    public static int startPoint;
    public static TreeSet<Integer> endPoint;
    public TurnMinDFA(StringBuilder s){
        TurnDFA t = new TurnDFA(s);
        setNum = TurnDFA.setNum;
        opList = new ArrayList<>(26);//一共26个英文字母
        edge = new ArrayList<>(TurnDFA.edgeDFA);
        minEdge = new ArrayList<>();
        end = new TreeSet<>(TurnDFA.end);
        opList.addAll(TurnDFA.opSet);
        for (Character character : opList) {
            System.out.println(character);
        }
        Iterator<Integer> itEnd;
        System.out.println("setNum:"+setNum);
        ArrayList<Integer>[] State = new ArrayList[setNum+1];
        int[][] state = new int[setNum+1][];
        for(int i = 1; i <= setNum; i++){
            state[i] = new int[opList.size()];
            Arrays.fill(state[i],0);//0代表epsilon
        }
        int[] newGroupId = new int[setNum+1];
        int[] groupId = new int[setNum+1];
        Arrays.fill(newGroupId,0);
        for(int i = 1; i <= setNum; i++){//初始化
            if(end.contains(i)){
                groupId[i]=2;
            }
            else
                groupId[i]=1;
        }
        while(true){
            for (Part part : edge) {
                state[part.s][part.op - 'a'] = groupId[part.e];
            }
            int Num = 1;
            for(int i = 1; i <= setNum; i++){
                int flag = 0;
                for(int j = 1; j < i; j++){
                    if(cmp(state[j],state[i]) && groupId[i] == groupId[j]){
                        flag = 1;
                        newGroupId[i]=newGroupId[j];
                        break;
                    }
                }
                if(flag == 0) {
                    newGroupId[i] = Num;
                    Num++;
                }
            }
            if(cmp(groupId,newGroupId))
                break;
            else{
                groupId = Arrays.copyOf(newGroupId,newGroupId.length);
            }
        }
        startPoint = groupId[1];
        endPoint = new TreeSet<>();
        itEnd = end.iterator();
        while(itEnd.hasNext()){
            endPoint.add(groupId[(int)itEnd.next()]);
        }
        System.out.println(startPoint+" "+endPoint);

        //根据区号求存储miniDFA的边
        for(int i = 1; i <= setNum; i++){
            for(int j = 0; j < opList.size(); j++){
                if(state[i][j]!=0) {
                    int flag = 0;
                    for (Part part : minEdge) {
                        if (groupId[i] == part.s && state[i][j] == part.e && (char) ('a' + j) == part.op) {
                            flag = 1;
                            break;
                        }
                    }
                    if(flag == 0)
                        minEdge.add(new Part(groupId[i], state[i][j], (char) ('a' + j)));
                }
            }
        }
        for (Part part : minEdge) {
            System.out.println(part.s + " " + part.e + " " + part.op);
        }
        drawMinDFA(startPoint,endPoint);
    }
    public void drawMinDFA(int startPoint, TreeSet<Integer> endPoint){
        GraphViz gViz=new GraphViz(".\\src\\HomeWork1\\GraphMinDFA", "D:\\Grapgviz\\Graphviz\\bin\\dot.exe");
        gViz.start_graph();
        gViz.add("rankdir = LR");
        gViz.add("node [shape = doublecircle];");
        for(int i: endPoint){
            gViz.add(""+i);
        }
        gViz.add(";");
        gViz.add("node [shape = circle];");
        for(int i = 0; i < minEdge.size();i++)
        {
            System.out.println("Running"+i);
            gViz.addln(minEdge.get(i).s+"->"+minEdge.get(i).e,""+minEdge.get(i).op);
        }
        gViz.addln("start"+"->"+startPoint," ");
        gViz.end_graph();
        try {
            gViz.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public boolean cmp(int[] a, int[] b){
        int flag = 0;
        if(a.length == b.length){
            for(int i = 0; i < a.length; i++){
                if(a[i]!=b[i]){
                    flag = 1;
                    break;
                }
            }
            return flag == 0;
        }
        else{
            return false;
        }
    }
    public static void main(String[] args) {
        String s0 = JOptionPane.showInputDialog("请输入表达式:");
        StringBuilder s1 = new StringBuilder(s0);
        ReversePolish r = new ReversePolish(s1);
        //StringBuilder s = new StringBuilder("a*ab·b·*·b·ba|*·");
        TurnMinDFA t = new TurnMinDFA(r.s);
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值