Class: Flexr::Automaton::DFA
- Inherits:
-
Object
- Object
- Flexr::Automaton::DFA
- Defined in:
- lib/flexr/automaton/dfa.rb
Instance Attribute Summary collapse
-
#accepts ⇒ Object
readonly
Returns the value of attribute accepts.
-
#class_count ⇒ Object
readonly
Returns the value of attribute class_count.
-
#direct ⇒ Object
readonly
Returns the value of attribute direct.
-
#ec ⇒ Object
readonly
Returns the value of attribute ec.
-
#packed ⇒ Object
readonly
Returns the value of attribute packed.
-
#rule_ids ⇒ Object
readonly
Returns the value of attribute rule_ids.
-
#start ⇒ Object
readonly
Returns the value of attribute start.
-
#states ⇒ Object
readonly
Returns the value of attribute states.
-
#transitions ⇒ Object
readonly
Returns the value of attribute transitions.
Instance Method Summary collapse
- #accept?(bytes) ⇒ Boolean
-
#initialize(accepts:, ec:, class_count:, start:, rule_ids:, transitions: nil, packed: nil, direct: nil, state_count: nil) ⇒ DFA
constructor
A new instance of DFA.
- #stats ⇒ Object
- #transition(state, byte) ⇒ Object
-
#transition_direct(state, byte) ⇒ Object
Generated direct lexers use a flattened dispatch representation.
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.
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
#accepts ⇒ Object (readonly)
Returns the value of attribute accepts.
49 50 51 |
# File 'lib/flexr/automaton/dfa.rb', line 49 def accepts @accepts end |
#class_count ⇒ Object (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 |
#direct ⇒ Object (readonly)
Returns the value of attribute direct.
49 50 51 |
# File 'lib/flexr/automaton/dfa.rb', line 49 def direct @direct end |
#ec ⇒ Object (readonly)
Returns the value of attribute ec.
49 50 51 |
# File 'lib/flexr/automaton/dfa.rb', line 49 def ec @ec end |
#packed ⇒ Object (readonly)
Returns the value of attribute packed.
49 50 51 |
# File 'lib/flexr/automaton/dfa.rb', line 49 def packed @packed end |
#rule_ids ⇒ Object (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 |
#start ⇒ Object (readonly)
Returns the value of attribute start.
49 50 51 |
# File 'lib/flexr/automaton/dfa.rb', line 49 def start @start end |
#states ⇒ Object (readonly)
Returns the value of attribute states.
49 50 51 |
# File 'lib/flexr/automaton/dfa.rb', line 49 def states @states end |
#transitions ⇒ Object (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
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 |
#stats ⇒ Object
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 |