java实现正则表达式到NFA的转换

我用java实现了一个正则表达式到NFA的转换程序,以下是我的代码

package com.siwanghu.regextoNFA;

public class Node {
    private int id;
    private static int ID=0;
    
    public Node(){
    	this.id=ID++;
    }

	public int getId() {
		return id;
	}

	public static void reset(){
		ID=0;
	}

	@Override
	public String toString() {
		return id+"";
	}
    
}
package com.siwanghu.regextoNFA;

public class Edge {
	private Node begin;
	private Node end;
	private String label;
	private Edge edge;

	public Edge() {
		super();
	}

	public Edge(Node begin, Node end) {
		super();
		this.begin = begin;
		this.end = end;
	}

	public Edge(Node begin, Node end, String label) {
		super();
		this.begin = begin;
		this.end = end;
		this.label = label;
	}

	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public Edge getEdge() {
		return edge;
	}

	public void setEdge(Edge edge) {
		this.edge = edge;
	}

	public Node getBegin() {
		return begin;
	}

	public void setBegin(Node begin) {
		this.begin = begin;
	}

	public Node getEnd() {
		return end;
	}

	public void setEnd(Node end) {
		this.end = end;
	}

	@Override
	public String toString() {
		return "Edge [begin=" + begin + ", end=" + end + ", label=" + label
				+ "]";
	}

}

package com.siwanghu.regextoNFA;

import java.util.ArrayList;
import java.util.List;

public class Graph {
	private List<Edge> edges;
	private Node start;
	private Node end;

	public Graph() {
		edges = new ArrayList<Edge>();
	}

	public List<Edge> getEdges() {
		return edges;
	}

	public Node getStart() {
		return start;
	}

	public void setStart(Node start) {
		this.start = start;
	}

	public Node getEnd() {
		return end;
	}

	public void setEnd(Node end) {
		this.end = end;
	}

	public void reset() {
		Node.reset();
	}

	public void Star(Object obj) {
		if (obj.getClass().getName().equals(Graph.class.getName())) {
			addStar((Graph) obj);
			return;
		}
		if (obj.getClass().getName().equals(Character.class.getName())) {
			addStar((Character) obj);
			return;
		} else {
			throw new RuntimeException("You have an error in your Regex syntax");
		}
	}

	public void Union(Object obj1, Object obj2) {
		if (obj1.getClass().getName().equals(Character.class.getName())) {
			if (obj2.getClass().getName().equals(Graph.class.getName())) {
				addUnion((Character) obj1, (Graph) obj2);
				return;
			}
			if (obj2.getClass().getName().equals(Character.class.getName())) {
				addUnion((Character) obj1, (Character) obj2);
				return;
			}
		}
		if (obj1.getClass().getName().equals(Graph.class.getName())) {
			if (obj2.getClass().getName().equals(Graph.class.getName())) {
				addUnion((Graph) obj1, (Graph) obj2);
				return;
			}
			if (obj2.getClass().getName().equals(Character.class.getName())) {
				addUnion((Graph) obj1, (Character) obj2);
				return;
			}
		} else {
			throw new RuntimeException("You have an error in your Regex syntax");
		}
	}

	public void Concat(Object obj1, Object obj2) {
		if (obj1.getClass().getName().equals(Character.class.getName())) {
			if (obj2.getClass().getName().equals(Graph.class.getName())) {
				addConcat((Character) obj1, (Graph) obj2);
				return;
			}
			if (obj2.getClass().getName().equals(Character.class.getName())) {
				addConcat((Character) obj1, (Character) obj2);
				return;
			}
		}
		if (obj1.getClass().getName().equals(Graph.class.getName())) {
			if (obj2.getClass().getName().equals(Graph.class.getName())) {
				addConcat((Graph) obj1, (Graph) obj2);
				return;
			}
			if (obj2.getClass().getName().equals(Character.class.getName())) {
				addConcat((Graph) obj1, (Character) obj2);
				return;
			}
		} else {
			throw new RuntimeException("You have an error in your Regex syntax");
		}
	}

	public void addStar(Graph graph) {
		Node begNode = new Node();
		Node endNode = new Node();
		Edge edge1 = new Edge(endNode, begNode, "epsilon");
		Edge edge2 = new Edge(begNode, graph.getStart(), "epsilon");
		Edge edge3 = new Edge(graph.getEnd(), endNode, "epsilon");
		for (int i = 0; i < graph.getEdges().size(); i++) {
			this.edges.add(graph.getEdges().get(i));
		}
		this.edges.add(edge1);
		this.edges.add(edge2);
		this.edges.add(edge3);
		this.start = begNode;
		this.end = endNode;
	}

	public void addStar(Character character) {
		Node nodeCenter = new Node();
		Node nodebeg = new Node();
		Node nodeend = new Node();
		Edge edgeLink = new Edge(nodeCenter, nodeCenter, character.toString());
		Edge edgeEpsilonBeg = new Edge(nodebeg, nodeCenter, "epsilon");
		Edge edgeepsilonEnd = new Edge(nodeCenter, nodeend, "epsilon");
		this.edges.add(edgeLink);
		this.edges.add(edgeEpsilonBeg);
		this.edges.add(edgeepsilonEnd);
		this.start = nodebeg;
		this.end = nodeend;
	}

	public void addUnion(Character character, Graph graph) {
		Node begNode = new Node();
		Node endNode = new Node();
		Edge edge1 = new Edge(begNode, graph.getStart(), "epsilon");
		Edge edge2 = new Edge(graph.getEnd(), endNode, "epsilon");
		Edge edge3 = new Edge(begNode, endNode, character.toString());
		for (int i = 0; i < graph.getEdges().size(); i++) {
			this.edges.add(graph.getEdges().get(i));
		}
		this.edges.add(edge1);
		this.edges.add(edge2);
		this.edges.add(edge3);
		this.start = begNode;
		this.end = endNode;
	}

	public void addUnion(Graph graph, Character character) {
		Node begNode = new Node();
		Node endNode = new Node();
		Edge edge1 = new Edge(begNode, graph.getStart(), "epsilon");
		Edge edge2 = new Edge(graph.getEnd(), endNode, "epsilon");
		Edge edge3 = new Edge(begNode, endNode, character.toString());
		for (int i = 0; i < graph.getEdges().size(); i++) {
			this.edges.add(graph.getEdges().get(i));
		}
		this.edges.add(edge1);
		this.edges.add(edge2);
		this.edges.add(edge3);
		this.start = begNode;
		this.end = endNode;
	}

	public void addUnion(Graph graph1, Graph graph2) {
		Node begNode = new Node();
		Node endNode = new Node();
		Edge edge1 = new Edge(begNode, graph1.getStart(), "epsilon");
		Edge edge2 = new Edge(begNode, graph2.getStart(), "epsilon");
		Edge edge3 = new Edge(graph1.getEnd(), endNode, "epsilon");
		Edge edge4 = new Edge(graph2.getEnd(), endNode, "epsilon");
		this.start = begNode;
		this.end = endNode;
		for (int i = 0; i < graph1.getEdges().size(); i++) {
			this.edges.add(graph1.getEdges().get(i));
		}
		for (int i = 0; i < graph2.getEdges().size(); i++) {
			this.edges.add(graph2.getEdges().get(i));
		}
		this.edges.add(edge1);
		this.edges.add(edge2);
		this.edges.add(edge3);
		this.edges.add(edge4);
	}

	public void addUnion(Character characterOne, Character characterTwo) {
		Node nodebeg = new Node();
		Node nodeend = new Node();
		Edge edgeOne = new Edge(nodebeg, nodeend, characterOne.toString());
		Edge edgeTwo = new Edge(nodebeg, nodeend, characterTwo.toString());
		edges.add(edgeOne);
		edges.add(edgeTwo);
		start = nodebeg;
		end = nodeend;
	}

	public void addConcat(Character character, Graph graph) {
		Node begNode = new Node();
		Edge edge = new Edge(begNode, graph.getStart(), character.toString());
		for (int i = 0; i < graph.getEdges().size(); i++) {
			this.edges.add(graph.getEdges().get(i));
		}
		this.edges.add(edge);
		this.start = begNode;
		this.end = graph.getEnd();
	}

	public void addConcat(Graph graph, Character character) {
		Node endNode = new Node();
		Edge edge = new Edge(graph.getEnd(), endNode, character.toString());
		for (int i = 0; i < graph.getEdges().size(); i++) {
			this.edges.add(graph.getEdges().get(i));
		}
		this.edges.add(edge);
		this.start = graph.getStart();
		this.end = endNode;
	}

	public void addConcat(Graph graph1, Graph graph2) {
		Edge edge = new Edge(graph1.getEnd(), graph2.getStart(), "epsilon");
		this.start = graph1.getStart();
		this.end = graph2.getEnd();
		for (int i = 0; i < graph1.getEdges().size(); i++) {
			this.edges.add(graph1.getEdges().get(i));
		}
		for (int i = 0; i < graph2.getEdges().size(); i++) {
			this.edges.add(graph2.getEdges().get(i));
		}
		this.edges.add(edge);
	}

	public void addConcat(Character characterOne, Character characterTwo) {
		Node begNode = new Node();
		Node midNode = new Node();
		Node endNode = new Node();
		Edge edge1 = new Edge(begNode, midNode, characterOne.toString());
		Edge edge2 = new Edge(midNode, endNode, characterTwo.toString());
		this.start = begNode;
		this.end = endNode;
		this.edges.add(edge1);
		this.edges.add(edge2);
	}

	@Override
	public String toString() {
		String printString = "Start=" + this.start + "  End=" + this.end + "\n";
		for (int i = 0; i < edges.size(); i++) {
			printString += edges.get(i) + "\n";
		}
		return printString;
	}
}
package com.siwanghu.regextoNFA;

import java.util.Stack;

public class Regex {
	private String regex = "";
	private Stack operatorStack;
	private Stack operandStack;
	private int[][] priority = {
			{ 1, 1, 1, -1, 1, 1 }, // *&|()#
			{ -1, 1, 1, -1, 1, 1 }, { -1, -1, 1, -1, 1, 1 },
			{ -1, -1, -1, -1, 0, 2 }, { 1, 1, 1, 1, 1, 1 },
			{ -1, -1, -1, -1, -1, -1 } };

	public Regex() {
		regex = "";
		operatorStack = new Stack();
		operandStack = new Stack();
	}

	public Regex(String _regex) {
		regex = "";
		operatorStack = new Stack();
		operandStack = new Stack();
		prepareString(_regex);
	}

	public Graph transformNFA() {
		if (regex.length() == 0)
			return null;
		else {
			int i = 0;
			operatorStack.push(‘#‘);
			char[] _regex = (regex + "#").toCharArray();
			while (_regex[i] != ‘#‘
					|| (Character) (operatorStack.peek()) != ‘#‘) {
				if (!isOperator(_regex[i])) {
					operandStack.push((Character)_regex[i]);
					i++;
				} else {
					int value=priorityOperator((Character)(operatorStack.peek()), _regex[i]);
					switch (value) {
					case 1:
						Character character=(Character)operatorStack.pop();
						switch (character) {
						case ‘*‘:
							Object obj=operandStack.pop();
							Graph graph1=new Graph();
							graph1.Star(obj);
							operandStack.push(graph1);
							break;
						case ‘&‘:
							Object obj2=operandStack.pop();
							Object obj1=operandStack.pop();
							Graph graph2=new Graph();
							graph2.Concat(obj1, obj2);
							operandStack.push(graph2);
							break;
						case ‘|‘:
							Object obj4=operandStack.pop();
							Object obj3=operandStack.pop();
							Graph graph3=new Graph();
							graph3.Union(obj3, obj4);
							operandStack.push(graph3);
							break;
						default:
							break;
						}
						break;
					case 0:
						operatorStack.pop();
						i++;
						break;
					case -1:
						operatorStack.push(_regex[i]);
						i++;
						break;
					default:
						break;
					}
				}
			}
			return (Graph) operandStack.pop();
		}
	}

	public void reset(){
		Node.reset();
		operandStack.clear();
		operatorStack.clear();
	}

	public String getRegex() {
		return regex;
	}

	public void setRegex(String _regex) {
		prepareString(_regex);
	}

	private boolean isOperator(Character character) {
		String operatorString = "*&|()#";
		if (operatorString.contains(character.toString())) {
			return true;
		} else {
			return false;
		}
	}

	private int priorityOperator(Character character1, Character character2) {
		String priorityString = "*&|()#";
		return this.priority[priorityString.indexOf(character1.toString())][priorityString
				.indexOf(character2.toString())];
	}

	private void prepareString(String _regex) {
		char[] regexs = _regex.replaceAll(" ", "").toCharArray();
		for (int i = 0; i < regexs.length; i++) {
			if (i == 0)
				regex += regexs[i];
			else {
				if (regexs[i] == ‘|‘ || regexs[i] == ‘*‘ || regexs[i] == ‘)‘) {
					regex += regexs[i];
				} else {
					if (regexs[i - 1] == ‘(‘ || regexs[i - 1] == ‘|‘)
						regex += regexs[i];
					else
						regex += ("&" + regexs[i]);
				}
			}
		}
	}

}
package com.siwanghu.regextoNFA;

public class Test {
	public static void main(String[] args) {
		try {
			String regexString1 = "a*";
			Regex regex1 = new Regex(regexString1);
			System.out.println(regex1.getRegex());
			System.out.println(regex1.transformNFA());
			regex1.reset();

			String regexString2 = "ab";
			Regex regex2 = new Regex(regexString2);
			System.out.println(regex2.getRegex());
			System.out.println(regex2.transformNFA());
			regex2.reset();

			String regexString3 = "a|b";
			Regex regex3 = new Regex(regexString3);
			System.out.println(regex3.getRegex());
			System.out.println(regex3.transformNFA());
			regex3.reset();

			String regexString4 = "(a|b)*";
			Regex regex4 = new Regex(regexString4);
			System.out.println(regex4.getRegex());
			System.out.println(regex4.transformNFA());
			regex4.reset();

			String regexString5 = "1(0|1)*101";
			Regex regex5 = new Regex(regexString5);
			System.out.println(regex5.getRegex());
			System.out.println(regex5.transformNFA());
			regex5.reset();

			String regexString6 = "0*10*10*10*";
			Regex regex6 = new Regex(regexString6);
			System.out.println(regex6.getRegex());
			System.out.println(regex6.transformNFA());
			regex6.reset();

			String regexString7 = "1(1010*|1(010)*1)*0";
			Regex regex7 = new Regex(regexString7);
			System.out.println(regex7.getRegex());
			System.out.println(regex7.transformNFA());
			regex6.reset();

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}
时间: 2024-10-07 23:15:33

java实现正则表达式到NFA的转换的相关文章

1000行代码徒手写正则表达式引擎【1】--JAVA中正则表达式的使用

简介: 本文是系列博客的第一篇,主要讲解和分析正则表达式规则以及JAVA中原生正则表达式引擎的使用.在后续的文章中会涉及基于NFA的正则表达式引擎内部的工作原理,并在此基础上用1000行左右的JAVA代码,实现一个支持常用功能的正则表达式引擎.它支持贪婪匹配和懒惰匹配:支持零宽度字符(如"\b", "\B"):支持常用字符集(如"\d", "\s"等):支持自定义字符集("[a-f]","[^b-

从正则表达式构造ε-NFA

来自 vczh ? 1:字符集 ? ? 字符集是正则表达式最基本的元素,因此反映到状态图上,字符集也会是构成状态图的基本元素.对于字符集C,如果有一个规则只接受C的话,这个规则对应的状态图将会被构造成以下形式: ? ? ? ? 这个状态图的初始状态是Start,结束状态是End.Start状态读入字符集C跳转到End状态,不接受其他字符集. ? ? 2:串联 ? ? 如果我们使用A⊙B表示规则A和规则B的串联,我们可以很容易的知道串联这个操作具有结合性,也就是说(A⊙B)⊙C=A⊙(B⊙C).因

从正则表达式到 NFA 到 DFA 到最简 DFA (二)

从正则表达式到 NFA 到 DFA 到最简 DFA (二) NFA $ \rightarrow $ DFA (子集构造法) 这里我们用一个例子来解释. 如上图所示,这是上一篇文章中的正则表达式化成的 NFA,这里拿来接着用. 我们首先看开始状态 n0.n0 在接收了一个字符 a 之后可以转换到 n1,这个时候我们要看 n1 是否存在 $ \varepsilon $ 转移.若存在,则递归的将所有能 $ \varepsilon $ 转移的状态添加到一个集合里(包括 n1).然后再看我们所创造的这个集

编译原理-第三章 词法分析-3.7 从正则表达式到自动机-从正则表达式构造NFA

基于MYT算法从正则表达式构造NFA 基本思想: 性质: 对于加括号的正则式(s),使用N(s)本身作为它的NFA 一.构造识别ε和字母表中一个符号的NFA 1.特点 仅一个接受状态,它没有向外的转换 2.示例 二.构造识别主算符为选择正则式的NFA 1.特点 仅一个接受状态,它没有向外的转换 2.示例 三.构造识别主算符为连接正则式的NFA 1.特点 仅一个接受状态,它没有向外的转换 2.示例 四.构造识别主算符为闭包正则式的NFA 1.特点 仅一个接受状态,它没有向外的转换 2.示例 五.例

java常用正则表达式

java常用正则表达式 1.^\d+$ //匹配非负整数(正整数 + 0) 2.^[0-9]*[1-9][0-9]*$ //匹配正整数 3.^((-\d+) ?(0+))$ //匹配非正整数(负整数 + 0) 4.^-[0-9]*[1-9][0-9]*$ //匹配负整数 5.^-?\d+$ //匹配整数 6.^\d+(\.\d+)?$ //匹配非负浮点数(正浮点数 + 0) 7.^(([0-9]+\.[0-9]*[1-9][0-9]*) ?([0-9]*[1-9][0-9]*\.[0-9]+)

Java中用正则表达式找出数字

Java中用正则表达式找出数字 1.题目    String str = "fjd789klsd908434jk#$$%%^38488545",从中找出78990843438488545,请找到解决办法 2.实现源码 /** * */ package com.you.model; /** * @author YouHaidong * */ public class FindNumber { /** * 字符串str */ public static String str = "

Java线程:线程状态的转换

Java线程:线程状态的转换 一.线程状态 线程的状态转换是线程控制的基础.线程状态总的可分为五大状态:分别是生.死.可运行.运行.等待/阻塞.用一个图来描述如下: 1.新状态:线程对象已经创建,还没有在其上调用start()方法. 2.可运行状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态.当start()方法调用时,线程首先进入可运行状态.在线程运行之后或者从阻塞.等待或睡眠状态回来后,也返回到可运行状态. 3.运行状态:线程调度程序从可运行池中选择一个线程作为当前

Java中数据类型及其之间的转换

Java中数据类型及其之间的转换 基本的数据类型 基本类型有以下四种: 1)int长度数据类型有:byte(8bits).short(16bits).int(32bits).long(64bits). 2)float长度数据类型有:单精度(32bits float).双精度(64bits double),JAVA中将小数默认为double类型,若要定义float需在数据后面用f声明: 3)boolean类型变量的取值有:ture.false 4)char数据类型有:unicode字符,16位 对

利用JAXB实现java实体类和xml互相转换

1.应用场景 在使用WebService实现数据上传下载,数据查询时,可以利用JAXB实现java实体类和xml互相转换 2.Demo 2.1 student.java 实体类,包含list(set同理).map.Teacher.Date 类型的属性 package jaxb; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAccess