码迷,mamicode.com
首页 > 编程语言 > 详细

编译原理:正规式转变成NFA算法

时间:2015-04-13 01:35:40      阅读:1945      评论:0      收藏:0      [点我收藏+]

标签:

import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

class Edge{
    private int u, v;
    private char key;
    public Edge(int u, int v, char key) {
        super();
        this.u = u;
        this.v = v;
        this.key = key;
    }
    @Override
    public String toString() {
        return u + "->" + v + " " + key;
    }
}

class NFA{
    private String formal_ceremony;//正规式字符串
    private int cnt_node=1;//记录节点的个数
    private Map<Integer, Integer> endNode = new TreeMap<Integer, Integer>();//每一个开始节点对应的终端节点
    ArrayList<Edge> nodeAl = new ArrayList<Edge>();
    public NFA(String formal_ceremony) {
        super();
        this.formal_ceremony = formal_ceremony;
    }
    
    public boolean    kernel_way(int fa, int ld, int rd, boolean isClosure){//fa表示区间的开始点,正规式的区间[ld, rd], isClosure表示这段区间查是否存在闭包 
        if(ld < 0 || rd >= formal_ceremony.length()){
            System.out.println("正规式不正确---发生数组越界!");
            return false;
        }
        int pre_node = fa;
        int inBracket = 0;//判断‘|‘是否在括弧内
        for(int i=ld; i<=rd; ++i){
            if(formal_ceremony.charAt(i)==‘(‘) ++inBracket;
            else if(formal_ceremony.charAt(i)==‘)‘) --inBracket;
            else if(formal_ceremony.charAt(i)==‘|‘ && 0==inBracket){
                if(!kernel_way(fa, ld, i-1, isClosure)) return false;
                if(!kernel_way(fa, i+1, rd, isClosure)) return false;
                return true;
            }
        }
        for(int i=ld; i<=rd; ++i){
            if(formal_ceremony.charAt(i)==‘(‘){//又是一个子区间
                //寻找和 该 ‘(‘相匹配的‘)‘
                int cntLeftBracket = 0;//统计遍历过程中‘(‘出现的次数,遇到‘)‘减去1
                int posRightBracket = -1;//记录相匹配的‘)‘的位置
                int posLeftBracket = i;
                for(int j=i+1; j<=rd; ++j){
                    if(formal_ceremony.charAt(j)==‘(‘)
                        ++cntLeftBracket;
                    else if(formal_ceremony.charAt(j)==‘)‘){
                        if(cntLeftBracket == 0){
                            posRightBracket = j;
                            break;
                        }
                        --cntLeftBracket;
                    }
                }
                if(posRightBracket == -1){//出错
                    System.out.println("正规式出错----括弧不匹配!");
                    return false;
                }
                int nodeFather = 0;//括弧内正则式的开始节点
                if(posRightBracket+1 <= rd && formal_ceremony.charAt(posRightBracket+1)==‘*‘){
                    i = posRightBracket+1;//过滤掉"()*"
                    nodeAl.add(new Edge(pre_node, ++cnt_node, ‘$‘));//表示这一条边为空
                    pre_node = cnt_node;
                    nodeFather = cnt_node;
                    nodeAl.add(new Edge(pre_node, ++cnt_node, ‘$‘));//表示这一条边为空
                    pre_node = cnt_node;
                    //处理()*括弧内的正规式
                    if(!kernel_way(nodeFather, posLeftBracket+1, posRightBracket-1, true)) return false;
                } else {
                    nodeFather = pre_node;
                    if(!kernel_way(nodeFather, posLeftBracket+1, posRightBracket-1, false))//对于"(101)", 看成101
                        return false;
                    i = posRightBracket;
                }
                
            } else {//单个字符
                if(formal_ceremony.charAt(i)==‘)‘) continue;
                if(i+1 <= rd && formal_ceremony.charAt(i+1)==‘*‘){
                    nodeAl.add(new Edge(pre_node, ++cnt_node, ‘$‘));//表示这一条边为空
                    pre_node = cnt_node;
                    nodeAl.add(new Edge(pre_node, pre_node, formal_ceremony.charAt(i)));//自身到自身一条边
                    if(i+1==rd  && isClosure)
                        nodeAl.add(new Edge(pre_node, fa, ‘$‘));//表示这一条边为空并且是连接到父亲节点
                    else{
                        if(endNode.containsKey(fa))
                            nodeAl.add(new Edge(pre_node, endNode.get(fa), ‘$‘));
                        else{
                            nodeAl.add(new Edge(pre_node, ++cnt_node, ‘$‘));//表示这一条边为空
                            if(i==rd) endNode.put(fa, cnt_node);//记录非闭包状态下 第一个节点对应的最后一个节点
                        }
                    }
                    pre_node = cnt_node;
                    ++i;//过滤*
                } else {
                    if(i==rd && isClosure){//是闭包的情况
                        nodeAl.add(new Edge(pre_node, fa, formal_ceremony.charAt(i)));
                    } else{
                        if(endNode.containsKey(fa))
                            nodeAl.add(new Edge(pre_node, endNode.get(fa), formal_ceremony.charAt(i)));
                        else{
                            nodeAl.add(new Edge(pre_node, ++cnt_node, formal_ceremony.charAt(i)));
                            if(i==rd) endNode.put(fa, cnt_node);//记录非闭包状态下 第一个节点对应的最后一个节点
                        }
                    }
                    pre_node = cnt_node;
                }
            }
        }
        return true;
    }
    
    public void outputNFA(){
        for(Edge e : nodeAl)
            System.out.println(e);
    }
}

/*
 * 将正规式转换成NFA
 * */
public class ToNFA {
    
    public static void main(String[] args){
//        String formal_ceremony = "1(1010*|1(010)*1)*0";
//        String formal_ceremony = "1(0|1)*101";
//        String formal_ceremony = "0*1*(010)0*1*";
//        String formal_ceremony = "(0|1|2)*";
//        String formal_ceremony = "0|1";
//        String formal_ceremony = "0|1|2|3";
//        String formal_ceremony = "(0|1|6)|(2|3)|(4|5)";
//        String formal_ceremony = "(0|1)*|(2|3)*";
        String formal_ceremony = "((10)|(01)*|(0|1))";
        NFA nfa = new NFA(formal_ceremony);
        if(nfa.kernel_way(1, 0, formal_ceremony.length()-1, false))
            nfa.outputNFA();
    }
}

 

编译原理:正规式转变成NFA算法

标签:

原文地址:http://www.cnblogs.com/hujunzheng/p/4421132.html

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!