aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Lasseter <nathan.je.lasseter@googlemail.com>2013-03-24 13:05:46 +0000
committerNathan Lasseter <nathan.je.lasseter@googlemail.com>2013-03-24 13:05:46 +0000
commit5e179bfadb1d73779f69737dea611c43c6d48587 (patch)
tree5cd56f08b7d08c2066b9eed08f1dd1ee8fe13d6c
parent771cdb55c4a30be16ddafebc9b43f087765f9876 (diff)
Parser for syntax v2, more examples, formatted output to (()) accepting nodes
-rw-r--r--README6
-rw-r--r--examples/mfcs.vfsm15
-rw-r--r--examples/mfcs2.vfsm19
-rw-r--r--vfsm.rb68
4 files changed, 82 insertions, 26 deletions
diff --git a/README b/README
index 6ec4d1f..6478a54 100644
--- a/README
+++ b/README
@@ -3,18 +3,18 @@ If an emulation of a machine is a virtual machine, then this is VFSM: the Virtua
Usage is: ruby vfsm.rb <machine description file> <input>
A Machine description must have:
- * A Nodes: line, followed by space separated node ids
* A Start: line, followed by the starting node id
* An Accept: line, followed by space separated node ids which may accept
* An Edges: line, followed by edge definition lines and an End: line
-There may be any number of Comment: lines which are unsurprisingly ignored.
-
An edge definition line must have:
* The source node
* The input to accept
* The destination node
+There may be any number of Comment: lines which are unsurprisingly ignored.
+In the VFSM v2 syntax, you do not need a nodes line, the node ids are inferred from the start:, accept:, and edges:-end: lines. Nodes: lines are ignored for backwards compatability.
+
The input is a string of space separated input tokens.
See the examples.
diff --git a/examples/mfcs.vfsm b/examples/mfcs.vfsm
new file mode 100644
index 0000000..2320199
--- /dev/null
+++ b/examples/mfcs.vfsm
@@ -0,0 +1,15 @@
+comment: MFCS Problems for Lecture 1
+comment: Question 5a
+comment: VFSM syntax version 2
+comment: Any 00 in the string must be followed by a 1.
+comment: eg. "1 0 1" "0 0 1 0 0 1 1 0 1"
+
+start: s0
+accept: s0 s1
+edges:
+ s0 0 s1
+ s1 0 s2
+ s1 1 s0
+ s2 1 s0
+ s0 1 s0
+end:
diff --git a/examples/mfcs2.vfsm b/examples/mfcs2.vfsm
new file mode 100644
index 0000000..2e70532
--- /dev/null
+++ b/examples/mfcs2.vfsm
@@ -0,0 +1,19 @@
+comment: MFCS Problems for Lecture 1
+comment: VFSM Syntax v2
+comment: Input over the alphabet {0, 1}
+comment: The leftmost and rightmost input must differ
+
+start: start
+accept: h0 h1
+edges:
+ start 1 q0
+ q0 1 q0
+ q0 0 h0
+ h0 1 q0
+ h0 0 h0
+ start 0 q1
+ q1 0 q1
+ q1 1 h1
+ h1 1 h1
+ h1 0 q1
+end:
diff --git a/vfsm.rb b/vfsm.rb
index dbec072..efbf949 100644
--- a/vfsm.rb
+++ b/vfsm.rb
@@ -1,7 +1,7 @@
class Node
- def initialize id
+ def initialize id, accepting = false
@id = id
- @accepting = false
+ @accepting = accepting
@edges = []
end
@@ -62,29 +62,29 @@ File.foreach(ARGV[0]) do |line|
elsif linearray[0].downcase == "comment:" then
#do nothing
elsif linearray[0].downcase == "nodes:" then
- linearray[1..-1].each do |node|
- extnode = nodes.select do |inode|
- inode.id == node
- end
- if extnode.length > 0 then
- puts "Duplicate node id in declaration at line #{lineno}"
- puts line
- exit
- else
- nodes.push(Node.new node)
- end
- end
+ #do nothing
+ #ignore line for backwards compatability
elsif linearray[0].downcase == "start:" then
tempsnode = nodes.select do |node|
node.id == linearray[1]
end
- currentnode = tempsnode[0]
- elsif linearray[0].downcase == "accept:" then
- anodes = nodes.select do |inode|
- linearray[1..-1].include? inode.id
+ if tempsnode.length == 0 then
+ currentnode = Node.new linearray[1]
+ nodes.push currentnode
+ else
+ currentnode = tempsnode[0]
end
- anodes.each do |inode|
- inode.accepting!
+ 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
@@ -97,19 +97,37 @@ File.foreach(ARGV[0]) do |line|
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
- fnodes[0].pushedge linearray[1], tnodes[0]
+ if tnodes.length == 0 then
+ tnode = Node.new linearray[2]
+ nodes.push tnode
+ else
+ tnode = tnodes[0]
+ end
+ fnode.pushedge linearray[1], tnode
end
end
end
ARGV[1].chomp.split.each do |input|
- print "(#{currentnode.id}) --#{input}--> "
+ if currentnode.accepting? then
+ print "((#{currentnode.id})) --#{input}--> "
+ else
+ print "(#{currentnode.id}) --#{input}--> "
+ end
nextnode = currentnode.goto input
if nextnode == :reject then
puts
@@ -120,7 +138,11 @@ ARGV[1].chomp.split.each do |input|
end
end
-puts "(#{currentnode.id})"
+if currentnode.accepting? then
+ puts "((#{currentnode.id}))"
+else
+ puts "(#{currentnode.id})"
+end
if currentnode.accepting? then
puts "Valid input, ACCEPTED"