aboutsummaryrefslogtreecommitdiff
path: root/lib/ndfa.rb
blob: 2e610cf1177ba34833a0880294df9d23725f548a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
module VFSM
	class NDFA
		attr_reader :currentnodes

		def initialize(machineDefinition)
			inedges = false
			nodes = []
			@currentnodes = []

			lineno = 0
			File.foreach(machineDefinition) do |line|
				lineno += 1
				linearray = line.chomp.split
				unless inedges then
					if linearray == [] then
						#do nothing
					elsif linearray[0].downcase == "comment:" then
						#do nothing
					elsif linearray[0].downcase == "nodes:" then
						#do nothing
						#ignore line for backwards compatability
					elsif linearray[0].downcase == "start:" then
						tempsnode = nodes.select do |node|
							node.id == linearray[1]
						end
						if tempsnode.length == 0 then
							startnode = Node.new linearray[1]
							nodes.push startnode
							@currentnodes.push startnode
						else
							@currentnodes.push tempsnode[0]
						end
					elsif linearray[0].downcase == "accept:" then
						linearray[1..-1].each do |node|
							anodes = nodes.select do |inode|
								node == inode.id
							end
							if anodes.length == 0 then
								mynode = Node.new node, true
								nodes.push mynode
							else
								anodes[0].accepting!
							end
						end
					elsif linearray[0].downcase == "edges:" then
						inedges = true
					else
						puts "Syntax error at line #{lineno}"
						puts line
						exit
					end
				else
					if linearray[0].downcase == "end:" then
						inedges = false
					else
						fnode = nil
						tnode = nil
						fnodes = nodes.select do |node|
							node.id == linearray[0]
						end
						if fnodes.length == 0 then
							fnode = Node.new linearray[0]
							nodes.push fnode
						else
							fnode = fnodes[0]
						end
						tnodes = nodes.select do |node|
							node.id == linearray[2]
						end
						if tnodes.length == 0 then
							tnode = Node.new linearray[2]
							nodes.push tnode
						else
							tnode = tnodes[0]
						end
						if linearray[1].downcase == "epsilon:" or linearray[1].downcase == "lambda:" then
							fnode.pushedge :lambda, tnode
						else
							fnode.pushedge linearray[1], tnode
						end
					end
				end
			end
			NDFA.recurse @currentnodes
			NDFA.printnodes @currentnodes
		end

		def handleinput(inputString)
			inputString.chomp.split.each do |input|
				nextnodes = []
				@currentnodes.each do |node|
					nextnode = node.goto input
					unless nextnode == :reject
						nextnode.each do |x|
							nextnodes.push x
						end
					end
				end

				NDFA.recurse nextnodes

				print " --#{input}--> "

				NDFA.printnodes nextnodes

				if nextnodes == [] then
					puts
					puts "Invalid input, REJECTED"
					exit
				else
					@currentnodes = nextnodes
				end
			end
		end

		class << self
			def printnodes nodes
				print "{ "
				(0..(nodes.length - 1)).each do |x|
					if nodes[x].accepting? then
						print "((#{nodes[x].id}))"
					else
						print "(#{nodes[x].id})"
					end
					print ", " unless x == (nodes.length - 1)
				end
				print " }"
			end

			def recurse nodeslist
				begin
					oldlist = nodeslist.dup
					oldlist.each do |node|
						tmp = node.goto :lambda
						unless tmp == :reject then
							tmp.each do |x|
								nodeslist.push x
							end
						end
					end
					nodeslist.uniq!
				end while oldlist != nodeslist
			end
		end
	end
end