Class: ActionDispatch::Journey::GTG::TransitionTable

Inherits:
Object
  • Object
show all
Includes:
NFA::Dot
Defined in:
lib/action_dispatch/journey/gtg/transition_table.rb

Overview

:nodoc:

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from NFA::Dot

#to_dot

Constructor Details

#initializeTransitionTable

Returns a new instance of TransitionTable.

[View source]

13
14
15
16
17
18
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 13

def initialize
  @regexp_states = {}
  @string_states = {}
  @accepting     = {}
  @memos         = Hash.new { |h, k| h[k] = [] }
end

Instance Attribute Details

#memosObject (readonly)

Returns the value of attribute memos.


11
12
13
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 11

def memos
  @memos
end

Instance Method Details

#[]=(from, to, sym) ⇒ Object

[View source]

124
125
126
127
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 124

def []=(from, to, sym)
  to_mappings = states_hash_for(sym)[from] ||= {}
  to_mappings[sym] = to
end

#accepting?(state) ⇒ Boolean

Returns:

  • (Boolean)
[View source]

28
29
30
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 28

def accepting?(state)
  @accepting[state]
end

#accepting_statesObject

[View source]

24
25
26
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 24

def accepting_states
  @accepting.keys
end

#add_accepting(state) ⇒ Object

[View source]

20
21
22
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 20

def add_accepting(state)
  @accepting[state] = true
end

#add_memo(idx, memo) ⇒ Object

[View source]

32
33
34
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 32

def add_memo(idx, memo)
  @memos[idx] << memo
end

#as_json(options = nil) ⇒ Object

[View source]

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 60

def as_json(options = nil)
  simple_regexp = Hash.new { |h, k| h[k] = {} }

  @regexp_states.each do |from, hash|
    hash.each do |re, to|
      simple_regexp[from][re.source] = to
    end
  end

  {
    regexp_states: simple_regexp,
    string_states: @string_states,
    accepting:     @accepting
  }
end

#eclosure(t) ⇒ Object

[View source]

40
41
42
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 40

def eclosure(t)
  Array(t)
end

#memo(idx) ⇒ Object

[View source]

36
37
38
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 36

def memo(idx)
  @memos[idx]
end

#move(t, a) ⇒ Object

[View source]

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 44

def move(t, a)
  return [] if t.empty?

  regexps = []

  t.map { |s|
    if states = @regexp_states[s]
      regexps.concat states.map { |re, v| re === a ? v : nil }
    end

    if states = @string_states[s]
      states[a]
    end
  }.compact.concat regexps
end

#statesObject

[View source]

129
130
131
132
133
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 129

def states
  ss = @string_states.keys + @string_states.values.flat_map(&:values)
  rs = @regexp_states.keys + @regexp_states.values.flat_map(&:values)
  (ss + rs).uniq
end

#to_svgObject

[View source]

76
77
78
79
80
81
82
83
84
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 76

def to_svg
  svg = IO.popen("dot -Tsvg", "w+") { |f|
    f.write(to_dot)
    f.close_write
    f.readlines
  }
  3.times { svg.shift }
  svg.join.sub(/width="[^"]*"/, "").sub(/height="[^"]*"/, "")
end

#transitionsObject

[View source]

135
136
137
138
139
140
141
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 135

def transitions
  @string_states.flat_map { |from, hash|
    hash.map { |s, to| [from, s, to] }
  } + @regexp_states.flat_map { |from, hash|
    hash.map { |s, to| [from, s, to] }
  }
end

#visualizer(paths, title = "FSM") ⇒ Object

[View source]

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/action_dispatch/journey/gtg/transition_table.rb', line 86

def visualizer(paths, title = "FSM")
  viz_dir   = File.join __dir__, "..", "visualizer"
  fsm_js    = File.read File.join(viz_dir, "fsm.js")
  fsm_css   = File.read File.join(viz_dir, "fsm.css")
  erb       = File.read File.join(viz_dir, "index.html.erb")
  states    = "function tt() { return #{to_json}; }"

  fun_routes = paths.sample(3).map do |ast|
    ast.map { |n|
      case n
      when Nodes::Symbol
        case n.left
        when ":id" then rand(100).to_s
        when ":format" then %w{ xml json }.sample
        else
          "omg"
        end
      when Nodes::Terminal then n.symbol
      else
        nil
      end
    }.compact.join
  end

  stylesheets = [fsm_css]
  svg         = to_svg
  javascripts = [states, fsm_js]

  fun_routes  = fun_routes
  stylesheets = stylesheets
  svg         = svg
  javascripts = javascripts

  require "erb"
  template = ERB.new erb
  template.result(binding)
end