Add NFA::Transition, start on DFA construction
This commit is contained in:
parent
8473df421a
commit
214ece7d90
@ -3,12 +3,53 @@ module Imbecile
|
|||||||
|
|
||||||
class DFA
|
class DFA
|
||||||
|
|
||||||
|
class State
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(nfas)
|
def initialize(nfas)
|
||||||
start_nfa = NFA.new
|
start_nfa = NFA.new
|
||||||
nfas.each do |nfa|
|
nfas.each do |nfa|
|
||||||
start_nfa.start_state.add_transition(nil, nfa.start_state)
|
start_nfa.start_state.add_transition(nil, nfa.start_state)
|
||||||
end
|
end
|
||||||
|
@states = {}
|
||||||
|
@to_process = Set.new
|
||||||
nil_transition_states = start_nfa.start_state.nil_transition_states
|
nil_transition_states = start_nfa.start_state.nil_transition_states
|
||||||
|
@states[nil_transition_states] = 0
|
||||||
|
process_nfa_state_set(nil_transition_states)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_nfa_state_set(nfa_state_set)
|
||||||
|
transitions = transitions_for(nfa_state_set)
|
||||||
|
while transitions.size > 0
|
||||||
|
subrange = CodePointRange.first_subrange(transitions.map(&:code_point_range))
|
||||||
|
dest_nfa_states = transitions.reduce(Set.new) do |result, transition|
|
||||||
|
if transition.code_point_range.include?(subrange)
|
||||||
|
result << transition.last
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
unless @states.include?(dest_nfa_states)
|
||||||
|
@to_process << dest_nfa_states
|
||||||
|
end
|
||||||
|
transitions.delete_if do |transition|
|
||||||
|
transition.code_point_range.last <= subrange.last
|
||||||
|
end
|
||||||
|
transitions.map! do |transition|
|
||||||
|
if transition.code_point_range.first <= subrange.last
|
||||||
|
Transition.new(CodePointRange.new(subrange.last + 1, transition.code_point_range.last), transition.destination)
|
||||||
|
else
|
||||||
|
transition
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def transitions_for(states)
|
||||||
|
states.reduce([]) do |result, state|
|
||||||
|
result + state.cp_transitions
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -5,6 +5,21 @@ module Imbecile
|
|||||||
|
|
||||||
class State
|
class State
|
||||||
|
|
||||||
|
class Transition
|
||||||
|
|
||||||
|
attr_reader :code_point_range
|
||||||
|
attr_reader :destination
|
||||||
|
|
||||||
|
def initialize(code_point_range, destination)
|
||||||
|
@code_point_range = code_point_range
|
||||||
|
end
|
||||||
|
|
||||||
|
def nil?
|
||||||
|
@code_point_range.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
attr_accessor :accepts
|
attr_accessor :accepts
|
||||||
attr_reader :transitions
|
attr_reader :transitions
|
||||||
|
|
||||||
@ -12,8 +27,8 @@ module Imbecile
|
|||||||
@transitions = []
|
@transitions = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_transition(code_point, destination_state)
|
def add_transition(code_point_range, destination)
|
||||||
@transitions << [code_point, destination_state]
|
@transitions << Transition.new(code_point_range, destination)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determine the set of states that can be reached by nil transitions.
|
# Determine the set of states that can be reached by nil transitions.
|
||||||
@ -24,10 +39,10 @@ module Imbecile
|
|||||||
def nil_transition_states
|
def nil_transition_states
|
||||||
states = Set[self]
|
states = Set[self]
|
||||||
analyze_state = lambda do |state|
|
analyze_state = lambda do |state|
|
||||||
state.nil_transitions.each do |range, dest_state|
|
state.nil_transitions.each do |transition|
|
||||||
unless states.include?(dest_state)
|
unless states.include?(transition.destination)
|
||||||
states << dest_state
|
states << transition.destination
|
||||||
analyze_state[dest_state]
|
analyze_state[transition.destination]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -36,14 +51,14 @@ module Imbecile
|
|||||||
end
|
end
|
||||||
|
|
||||||
def nil_transitions
|
def nil_transitions
|
||||||
@transitions.select do |code_point, dest_state|
|
@transitions.select do |transition|
|
||||||
code_point.nil?
|
transition.nil?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cp_transitions
|
def cp_transitions
|
||||||
@transitions.select do |code_point, dest_state|
|
@transitions.reject do |transition|
|
||||||
code_point
|
transition.nil?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,13 +94,13 @@ module Imbecile
|
|||||||
visit = lambda do |state|
|
visit = lambda do |state|
|
||||||
accepts_s = state.accepts ? " *" : ""
|
accepts_s = state.accepts ? " *" : ""
|
||||||
rv += "#{state_id[state]}#{accepts_s}:\n"
|
rv += "#{state_id[state]}#{accepts_s}:\n"
|
||||||
state.transitions.each do |code_point_range, dest_state|
|
state.transitions.each do |transition|
|
||||||
if code_point_range.nil?
|
if transition.nil?
|
||||||
range_s = "nil"
|
range_s = "nil"
|
||||||
else
|
else
|
||||||
range_s = chr[code_point_range.first]
|
range_s = chr[transition.code_point_range.first]
|
||||||
if code_point_range.size > 1
|
if transition.code_point_range.size > 1
|
||||||
range_s += "-" + chr[code_point_range.last]
|
range_s += "-" + chr[transition.code_point_range.last]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
accepts_s = dest_state.accepts ? " *" : ""
|
accepts_s = dest_state.accepts ? " *" : ""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user