aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNathan Lasseter <nathan@4574.co.uk>2014-03-29 16:23:06 +0000
committerNathan Lasseter <nathan@4574.co.uk>2014-03-29 16:23:06 +0000
commitd9fbb2c4900b008daa9c5e0302677f9d1674a473 (patch)
treece4a5ae23db310d064c379e0148dd621e845ca61 /lib
parent4b1a4a8e9dbe9ea46b596a4578f7e3d51b235a15 (diff)
Begun modularising
Diffstat (limited to 'lib')
-rw-r--r--lib/ndfa.rb146
-rw-r--r--lib/node.rb44
-rw-r--r--lib/vfsm.rb2
3 files changed, 192 insertions, 0 deletions
diff --git a/lib/ndfa.rb b/lib/ndfa.rb
new file mode 100644
index 0000000..2e610cf
--- /dev/null
+++ b/lib/ndfa.rb
@@ -0,0 +1,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
diff --git a/lib/node.rb b/lib/node.rb
new file mode 100644
index 0000000..5875e38
--- /dev/null
+++ b/lib/node.rb
@@ -0,0 +1,44 @@
+module VFSM
+ class Node
+ def initialize id, accepting = false
+ @id = id
+ @accepting = accepting
+ @edges = []
+ end
+
+ def id
+ return @id
+ end
+
+ def accepting! accepting=true
+ @accepting = accepting
+ end
+
+ def accepting?
+ return @accepting
+ end
+
+ def pushedge on, to
+ tempto = @edges.select do |edge|
+ edge[0] == on
+ end
+ @edges.push [on, to]
+ end
+
+ def goto on
+ to = @edges.select do |edge|
+ edge[0] == on
+ end
+
+ if to.length == 0 then
+ return :reject
+ else
+ ret = []
+ to.each do |x|
+ ret.push x[1]
+ end
+ return ret
+ end
+ end
+ end
+end
diff --git a/lib/vfsm.rb b/lib/vfsm.rb
new file mode 100644
index 0000000..6c5ff96
--- /dev/null
+++ b/lib/vfsm.rb
@@ -0,0 +1,2 @@
+require './lib/node'
+require './lib/ndfa'