Class: LLIP::RegexpSpecification

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/llip/regexp_specification.rb

Overview

This class represents a specification for a Regexp as an Hash of State because of the equivalence between finite state machines and regular expressions.

Defined Under Namespace

Classes: State

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil) ⇒ RegexpSpecification

The name is stored in the attribute name.



21
22
23
24
# File 'lib/llip/regexp_specification.rb', line 21

def initialize(name=nil)
  @states = Hash.new { |hash,key| raise "Unknown RegexpSpecification::State #{key}" }
  @name = name.to_sym if name
end

Instance Attribute Details

#initObject (readonly)

The first value inserted in the RegexpSpecification



15
16
17
# File 'lib/llip/regexp_specification.rb', line 15

def init
  @init
end

#nameObject

The name of the RegexpSpecification. Its default is nil



12
13
14
# File 'lib/llip/regexp_specification.rb', line 12

def name
  @name
end

#statesObject (readonly)

It’s an hash containing all the states that compose this RegexpSpecification



18
19
20
# File 'lib/llip/regexp_specification.rb', line 18

def states
  @states
end

Class Method Details

.last_accessor(state, last = [], examined = {}, prev = nil) ⇒ Object

:call-seq: RegexpSpecification.last_accessor(RegexpSpecification::State) => Array

Returns an Array which contains all the last states reachable starting from state. The states in the array may be duplicated.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/llip/regexp_specification.rb', line 137

def self.last_accessor(state,last=[],examined={},prev=nil)
  
  future_states = state.values.uniq
  
  future_states << state.error if ( state.error.kind_of? RegexpSpecification::State or state.error.kind_of? RegexpSpecification ) and state.error != state 
  
  unless examined.has_key? state
    examined[state] = {}
    examined[state][prev] = true	
    
    if future_states.size == 0
      last << state
    else
      future_states.each do |s|
        last_accessor(s,last,examined,state)
      end
    end
  else
    future_state_unvisited = future_states.select { |s| not examined[s] }
    last << state if future_state_unvisited.size == 0 and ( examined[state][prev] or examined[state][state] or prev == state )
    examined[state][prev] = true
  end
  last
end

.mix(first, second) ⇒ Object

This method is used by RegexpAbstractScanner to mix two different RegexpSpecification which have starting chars in common. It raises an exception if the two regexp have some common chars marked as final.



164
165
166
167
168
# File 'lib/llip/regexp_specification.rb', line 164

def self.mix(first,second)
  regexp = self.new("mix between '#{first.name}' and '#{second.name}'") 
  mix_accessor(first.init,second.init,regexp,regexp.add_state)
  regexp
end

Instance Method Details

#add_state(arg = {}) ⇒ Object

:call-seq: add_state(RegexpSpecification::State) => RegexpSpecification::State add_state({}) => RegexpSpecification::State add_state => RegexpSpecification::State

Adds a State to the RegexpSpecification with the name as a key. If an hash is passed, it will create a State with that hash as a parameter. If nothing is passed, an empty Hash is taken as the default.



34
35
36
37
38
39
40
41
# File 'lib/llip/regexp_specification.rb', line 34

def add_state(arg={})
  unless arg.kind_of? State or arg.kind_of? RegexpSpecification
    arg = State.new(arg)
  end
  @init ||= arg
  arg.regexp = self
  @states[arg.name]=arg
end

#lastObject

Calls init.last

See State#last



59
60
61
62
# File 'lib/llip/regexp_specification.rb', line 59

def last
  return [] unless @init
  @init.last
end

#starting_charsObject

Returns :everything if the init State has an error which is not a State. Returns the init State keys otherwise.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/llip/regexp_specification.rb', line 44

def starting_chars
  if self.init
    if self.init.error.kind_of? State
      :everything
    else
      self.init.keys
    end
  else
    []
  end	
end