Add CodePointRange class
This commit is contained in:
1 parent
3a1650906e
commit
3987f08cd7
6 files changed
+142
-64
No files matched your search
+21
-11
@@ -24,12 +24,10 @@ module Imbecile
|
||||
def nil_transition_states
|
||||
states = Set[self]
|
||||
analyze_state = lambda do |state|
|
||||
state.transitions.each do |range, dest_state|
|
||||
if range.nil?
|
||||
unless states.include?(dest_state)
|
||||
states << dest_state
|
||||
analyze_state[dest_state]
|
||||
end
|
||||
state.nil_transitions.each do |range, dest_state|
|
||||
unless states.include?(dest_state)
|
||||
states << dest_state
|
||||
analyze_state[dest_state]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -37,6 +35,18 @@ module Imbecile
|
||||
states
|
||||
end
|
||||
|
||||
def nil_transitions
|
||||
@transitions.select do |code_point, dest_state|
|
||||
code_point.nil?
|
||||
end
|
||||
end
|
||||
|
||||
def cp_transitions
|
||||
@transitions.select do |code_point, dest_state|
|
||||
code_point
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
attr_accessor :start_state
|
||||
@@ -69,13 +79,13 @@ module Imbecile
|
||||
visit = lambda do |state|
|
||||
accepts_s = state.accepts ? " *" : ""
|
||||
rv += "#{state_id[state]}#{accepts_s}:\n"
|
||||
state.transitions.each do |range, dest_state|
|
||||
if range.nil?
|
||||
state.transitions.each do |code_point_range, dest_state|
|
||||
if code_point_range.nil?
|
||||
range_s = "nil"
|
||||
else
|
||||
range_s = chr[range.first]
|
||||
if range.size > 1
|
||||
range_s += "-" + chr[range.last]
|
||||
range_s = chr[code_point_range.first]
|
||||
if code_point_range.size > 1
|
||||
range_s += "-" + chr[code_point_range.last]
|
||||
end
|
||||
end
|
||||
accepts_s = dest_state.accepts ? " *" : ""
|
||||
|
||||
+12
-27
@@ -68,18 +68,19 @@ module Imbecile
|
||||
end
|
||||
|
||||
class CharacterRangeUnit < Unit
|
||||
attr_accessor :min_code_point
|
||||
attr_accessor :max_code_point
|
||||
attr_reader :code_point_range
|
||||
def initialize(c1, c2 = nil)
|
||||
@min_code_point = c1.ord
|
||||
@max_code_point = c2 ? c2.ord : @min_code_point
|
||||
@code_point_range = CodePointRange.new(c1, c2)
|
||||
end
|
||||
def range
|
||||
@min_code_point..@max_code_point
|
||||
def first
|
||||
@code_point_range.first
|
||||
end
|
||||
def last
|
||||
@code_point_range.last
|
||||
end
|
||||
def to_nfa
|
||||
nfa = NFA.new
|
||||
nfa.start_state.add_transition(range, nfa.end_state)
|
||||
nfa.start_state.add_transition(@code_point_range, nfa.end_state)
|
||||
nfa
|
||||
end
|
||||
end
|
||||
@@ -108,32 +109,16 @@ module Imbecile
|
||||
if @units.empty?
|
||||
nfa.start_state.add_transition(nil, nfa.end_state)
|
||||
else
|
||||
ranges = @units.map(&:range)
|
||||
code_point_ranges = @units.map(&:code_point_range)
|
||||
if @negate
|
||||
ranges = negate_ranges(ranges)
|
||||
code_point_ranges = CodePointRange.invert_ranges(code_point_ranges)
|
||||
end
|
||||
ranges.each do |range|
|
||||
nfa.start_state.add_transition(range, nfa.end_state)
|
||||
code_point_ranges.each do |code_point_range|
|
||||
nfa.start_state.add_transition(code_point_range, nfa.end_state)
|
||||
end
|
||||
end
|
||||
nfa
|
||||
end
|
||||
private
|
||||
def negate_ranges(ranges)
|
||||
ranges = ranges.sort_by(&:first)
|
||||
new_ranges = []
|
||||
last_cp = -1
|
||||
ranges.each do |range|
|
||||
if range.first > (last_cp + 1)
|
||||
new_ranges << ((last_cp + 1)..(range.first - 1))
|
||||
last_cp = range.last
|
||||
end
|
||||
end
|
||||
if last_cp < 0xFFFFFFFF
|
||||
new_ranges << ((last_cp + 1)..0xFFFFFFFF)
|
||||
end
|
||||
new_ranges
|
||||
end
|
||||
end
|
||||
|
||||
class MultiplicityUnit < Unit
|
||||
|
||||
Reference in new issue
Block a user