Class: Flexr::Automaton::DFA

Inherits:
Object
  • Object
show all
Defined in:
lib/flexr/automaton/dfa.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(accepts:, ec:, class_count:, start:, rule_ids:, transitions: nil, packed: nil, direct: nil, state_count: nil) ⇒ DFA

Returns a new instance of DFA.

Raises:

  • (ArgumentError)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/flexr/automaton/dfa.rb', line 51

def initialize(accepts:, ec:, class_count:, start:, rule_ids:, transitions: nil, packed: nil, direct: nil,
               state_count: nil)
  @packed = freeze_representation(packed)
  @direct = freeze_representation(direct)
  @states = state_count || transitions&.length || direct_state_count
  raise ArgumentError, "state_count is required without dense transitions" unless @states

  @transitions = transition_rows(transitions)
  @accepts = accepts.map do |rules|
    rules.map do |acceptance|
      next acceptance.freeze if acceptance.is_a?(Acceptance)

      Acceptance.new(rule_index: acceptance[0], pattern_index: acceptance[1],
                     bol_only: acceptance[2], end_anchor: acceptance[3]).freeze
    end.freeze
  end.freeze
  @ec = ec.freeze
  @class_count = class_count
  @start = start
  @rule_ids = rule_ids.map { |id| id.respond_to?(:rule_index) ? id.rule_index : id }.uniq.sort.freeze
  freeze
end

Instance Attribute Details

#acceptsObject (readonly)

Returns the value of attribute accepts.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def accepts
  @accepts
end

#class_countObject (readonly)

Returns the value of attribute class_count.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def class_count
  @class_count
end

#directObject (readonly)

Returns the value of attribute direct.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def direct
  @direct
end

#ecObject (readonly)

Returns the value of attribute ec.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def ec
  @ec
end

#packedObject (readonly)

Returns the value of attribute packed.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def packed
  @packed
end

#rule_idsObject (readonly)

Returns the value of attribute rule_ids.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def rule_ids
  @rule_ids
end

#startObject (readonly)

Returns the value of attribute start.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def start
  @start
end

#statesObject (readonly)

Returns the value of attribute states.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def states
  @states
end

#transitionsObject (readonly)

Returns the value of attribute transitions.



49
50
51
# File 'lib/flexr/automaton/dfa.rb', line 49

def transitions
  @transitions
end

Instance Method Details

#accept?(bytes) ⇒ Boolean

Returns:

  • (Boolean)


93
94
95
96
97
98
99
100
101
# File 'lib/flexr/automaton/dfa.rb', line 93

def accept?(bytes)
  data = bytes.dup.force_encoding(Encoding::BINARY)
  state = @start
  data.each_byte do |byte|
    state = transition(state, byte)
    return false unless state
  end
  !@accepts[state].empty?
end

#statsObject



103
104
105
# File 'lib/flexr/automaton/dfa.rb', line 103

def stats
  { states: states, classes: class_count, accepting_states: accepts.count { |rules| !rules.empty? } }
end

#transition(state, byte) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/flexr/automaton/dfa.rb', line 74

def transition(state, byte)
  class_id = @ec[byte]
  return direct_transition(state, class_id) if @direct
  return @transitions[state][class_id] unless @packed

  packed_transition(state, class_id)
end

#transition_direct(state, byte) ⇒ Object

Generated direct lexers use a flattened dispatch representation. The interpreter keeps this route separate from packed/table equivalence.



84
85
86
87
88
89
90
91
# File 'lib/flexr/automaton/dfa.rb', line 84

def transition_direct(state, byte)
  if @direct
    class_id = @ec[byte]
    return direct_transition(state, class_id)
  end

  @transitions[state][@ec[byte]]
end