Skip to content

Instantly share code, notes, and snippets.

@jarsen
Created May 18, 2009 07:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jarsen/113356 to your computer and use it in GitHub Desktop.
Save jarsen/113356 to your computer and use it in GitHub Desktop.
For a cs theory class. Will take a NFA-lambda machine and print out it's corresponding DFA
#!/usr/bin/env ruby -wKU
#nfa_converter.rb
# converts a given NFA-lambda to it's corresponding DFA and prints
# corresponding transition rules.
$: << File.expand_path(File.dirname(__FILE__))
require 'NFA'
ARGV.each do |fileName| # each argument passed through bash is a file to convert
puts "Constructing state machine for #{fileName}..."
nfa = NFA.new fileName
puts "Original NFA-Lambda:"
puts nfa
puts
puts "Corresponding DFA:"
puts nfa.to_DFA
end
require 'set'
class State
attr_accessor :name
def initialize(name)
@name = name
end
def to_s
name
end
end
class Transition
attr_accessor :state, :symbol, :next_state
def initialize state, symbol, next_state
@state, @symbol, @next_state = state, symbol, next_state
end
def lambda?
@symbol == "l"
end
def to_s
state + symbol + next_state
end
end
class NFA
attr_accessor :states, :alphabet, :transitions, :start, :finals
def initialize fileName
@states = Set.new # set up all of the arrays for keepings states and things
@alphabet = Set.new
@transitions = Set.new
@finals = Set.new
file = File.read(fileName).split("\n") #read in the file
@start = State.new file.shift #get the name of the start state
@states.add @start
#add line 2 - final states
file.shift.split(" ").each do |name|
state = State.new name
@states.add state
@finals.add state
end
#add line 4 - non-final states
file.shift.split(" ").each do |name|
@states.add State.new(name)
end
#the rest are transitions
file.each do |line|
state, symbol, next_state = line.split(/([a-z]*)/)
transitions.add Transition.new(state, symbol, next_state)
alphabet.add symbol
end
end
def to_DFA
q_prime = lambda_closure start.name # step 1
while true # step 2
continue = do #figure out if we have more to do
end
if continue do
y = t
else break
end
end
end
def t qi, symbol
closure = lambda_closure qi
results = Set.new closure
# find a transition where symbol and qj match, add to new closure
transitions.each do |transition|
if closure.include? transition.state and transition.symbol == symbol then
results.add transition.next_state
end
end
results
end
def lambda_closure qi
closure = Set.new [qi] # basis
transitions.each do |transition| # recursive step
closure.merge lambda_closure(transition.next_state) if transition.state == qi and transition.lambda?
end
closure
end
def to_s
str = start.name + "\n"
finals.each { |state| str << state.name + " " }
str << "\n"
(states - finals - [start]).each { |state| str << state.name + " " }
str << "\n"
transitions.each { |transition| str << transition.to_s + "\n"}
return str
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment