actionpack 3.2.19 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +850 -401
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +39 -37
  7. data/lib/abstract_controller/callbacks.rb +101 -82
  8. data/lib/abstract_controller/collector.rb +7 -3
  9. data/lib/abstract_controller/helpers.rb +25 -13
  10. data/lib/abstract_controller/layouts.rb +74 -74
  11. data/lib/abstract_controller/logger.rb +1 -2
  12. data/lib/abstract_controller/rendering.rb +30 -13
  13. data/lib/abstract_controller/translation.rb +16 -1
  14. data/lib/abstract_controller/url_for.rb +6 -6
  15. data/lib/abstract_controller/view_paths.rb +1 -1
  16. data/lib/abstract_controller.rb +1 -8
  17. data/lib/action_controller/base.rb +46 -22
  18. data/lib/action_controller/caching/fragments.rb +23 -53
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/log_subscriber.rb +16 -8
  23. data/lib/action_controller/metal/conditional_get.rb +76 -32
  24. data/lib/action_controller/metal/data_streaming.rb +20 -26
  25. data/lib/action_controller/metal/exceptions.rb +19 -6
  26. data/lib/action_controller/metal/flash.rb +24 -9
  27. data/lib/action_controller/metal/force_ssl.rb +70 -12
  28. data/lib/action_controller/metal/head.rb +25 -4
  29. data/lib/action_controller/metal/helpers.rb +5 -9
  30. data/lib/action_controller/metal/hide_actions.rb +0 -1
  31. data/lib/action_controller/metal/http_authentication.rb +107 -83
  32. data/lib/action_controller/metal/implicit_render.rb +1 -1
  33. data/lib/action_controller/metal/instrumentation.rb +2 -1
  34. data/lib/action_controller/metal/live.rb +175 -0
  35. data/lib/action_controller/metal/mime_responds.rb +161 -47
  36. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  37. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  38. data/lib/action_controller/metal/redirecting.rb +15 -20
  39. data/lib/action_controller/metal/renderers.rb +11 -9
  40. data/lib/action_controller/metal/rendering.rb +9 -1
  41. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  42. data/lib/action_controller/metal/responder.rb +20 -19
  43. data/lib/action_controller/metal/streaming.rb +12 -18
  44. data/lib/action_controller/metal/strong_parameters.rb +520 -0
  45. data/lib/action_controller/metal/testing.rb +13 -18
  46. data/lib/action_controller/metal/url_for.rb +28 -25
  47. data/lib/action_controller/metal.rb +17 -32
  48. data/lib/action_controller/model_naming.rb +12 -0
  49. data/lib/action_controller/railtie.rb +33 -17
  50. data/lib/action_controller/railties/helpers.rb +22 -0
  51. data/lib/action_controller/record_identifier.rb +18 -72
  52. data/lib/action_controller/test_case.rb +251 -131
  53. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  54. data/lib/action_controller.rb +15 -6
  55. data/lib/action_dispatch/http/cache.rb +63 -11
  56. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  57. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  58. data/lib/action_dispatch/http/headers.rb +49 -17
  59. data/lib/action_dispatch/http/mime_negotiation.rb +24 -1
  60. data/lib/action_dispatch/http/mime_type.rb +154 -100
  61. data/lib/action_dispatch/http/mime_types.rb +1 -1
  62. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  63. data/lib/action_dispatch/http/parameters.rb +28 -28
  64. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  65. data/lib/action_dispatch/http/request.rb +64 -18
  66. data/lib/action_dispatch/http/response.rb +130 -35
  67. data/lib/action_dispatch/http/upload.rb +63 -20
  68. data/lib/action_dispatch/http/url.rb +98 -35
  69. data/lib/action_dispatch/journey/backwards.rb +5 -0
  70. data/lib/action_dispatch/journey/formatter.rb +146 -0
  71. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  72. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  73. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  74. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  75. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  76. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  77. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  78. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  79. data/lib/action_dispatch/journey/parser.rb +206 -0
  80. data/lib/action_dispatch/journey/parser.y +47 -0
  81. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  82. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  83. data/lib/action_dispatch/journey/route.rb +124 -0
  84. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  85. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  86. data/lib/action_dispatch/journey/router.rb +166 -0
  87. data/lib/action_dispatch/journey/routes.rb +75 -0
  88. data/lib/action_dispatch/journey/scanner.rb +61 -0
  89. data/lib/action_dispatch/journey/visitors.rb +197 -0
  90. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  91. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  92. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  93. data/lib/action_dispatch/journey.rb +5 -0
  94. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  95. data/lib/action_dispatch/middleware/cookies.rb +259 -114
  96. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  97. data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -3
  98. data/lib/action_dispatch/middleware/flash.rb +58 -58
  99. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  100. data/lib/action_dispatch/middleware/public_exceptions.rb +30 -14
  101. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  102. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  103. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  104. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  105. data/lib/action_dispatch/middleware/session/cookie_store.rb +82 -28
  106. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  107. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  108. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  109. data/lib/action_dispatch/middleware/stack.rb +6 -1
  110. data/lib/action_dispatch/middleware/static.rb +2 -1
  111. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  112. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  113. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +7 -9
  114. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +127 -5
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  117. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  118. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  119. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  120. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  121. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  122. data/lib/action_dispatch/railtie.rb +16 -6
  123. data/lib/action_dispatch/request/session.rb +181 -0
  124. data/lib/action_dispatch/routing/inspector.rb +240 -0
  125. data/lib/action_dispatch/routing/mapper.rb +540 -291
  126. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  127. data/lib/action_dispatch/routing/redirection.rb +46 -29
  128. data/lib/action_dispatch/routing/route_set.rb +207 -164
  129. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  130. data/lib/action_dispatch/routing/url_for.rb +48 -33
  131. data/lib/action_dispatch/routing.rb +48 -83
  132. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  133. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  134. data/lib/action_dispatch/testing/assertions/routing.rb +42 -41
  135. data/lib/action_dispatch/testing/assertions/selector.rb +17 -22
  136. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  137. data/lib/action_dispatch/testing/integration.rb +65 -51
  138. data/lib/action_dispatch/testing/test_process.rb +9 -6
  139. data/lib/action_dispatch/testing/test_request.rb +7 -3
  140. data/lib/action_dispatch.rb +21 -15
  141. data/lib/action_pack/version.rb +7 -6
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_view/base.rb +15 -34
  144. data/lib/action_view/buffers.rb +7 -1
  145. data/lib/action_view/context.rb +4 -4
  146. data/lib/action_view/dependency_tracker.rb +93 -0
  147. data/lib/action_view/digestor.rb +85 -0
  148. data/lib/action_view/flows.rb +1 -4
  149. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  150. data/lib/action_view/helpers/asset_tag_helper.rb +215 -352
  151. data/lib/action_view/helpers/asset_url_helper.rb +355 -0
  152. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  153. data/lib/action_view/helpers/cache_helper.rb +150 -18
  154. data/lib/action_view/helpers/capture_helper.rb +44 -31
  155. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  156. data/lib/action_view/helpers/date_helper.rb +269 -248
  157. data/lib/action_view/helpers/debug_helper.rb +10 -11
  158. data/lib/action_view/helpers/form_helper.rb +931 -537
  159. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  160. data/lib/action_view/helpers/form_tag_helper.rb +190 -90
  161. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  162. data/lib/action_view/helpers/number_helper.rb +148 -329
  163. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  164. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  165. data/lib/action_view/helpers/rendering_helper.rb +2 -2
  166. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  167. data/lib/action_view/helpers/tag_helper.rb +46 -33
  168. data/lib/action_view/helpers/tags/base.rb +147 -0
  169. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  170. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  171. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  172. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  173. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  174. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  175. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  176. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  177. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  178. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  179. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  180. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  181. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  182. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  183. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  184. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  185. data/lib/action_view/helpers/tags/label.rb +65 -0
  186. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  187. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  188. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  189. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  190. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  191. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  192. data/lib/action_view/helpers/tags/select.rb +40 -0
  193. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  194. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  195. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  196. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  197. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  198. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  199. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  200. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  201. data/lib/action_view/helpers/tags.rb +39 -0
  202. data/lib/action_view/helpers/text_helper.rb +130 -114
  203. data/lib/action_view/helpers/translation_helper.rb +32 -16
  204. data/lib/action_view/helpers/url_helper.rb +211 -270
  205. data/lib/action_view/helpers.rb +2 -4
  206. data/lib/action_view/locale/en.yml +1 -105
  207. data/lib/action_view/log_subscriber.rb +6 -4
  208. data/lib/action_view/lookup_context.rb +15 -28
  209. data/lib/action_view/model_naming.rb +12 -0
  210. data/lib/action_view/path_set.rb +8 -20
  211. data/lib/action_view/railtie.rb +6 -22
  212. data/lib/action_view/record_identifier.rb +84 -0
  213. data/lib/action_view/renderer/abstract_renderer.rb +25 -19
  214. data/lib/action_view/renderer/partial_renderer.rb +158 -81
  215. data/lib/action_view/renderer/renderer.rb +8 -12
  216. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  217. data/lib/action_view/renderer/template_renderer.rb +12 -10
  218. data/lib/action_view/routing_url_for.rb +107 -0
  219. data/lib/action_view/template/error.rb +22 -12
  220. data/lib/action_view/template/handlers/builder.rb +1 -1
  221. data/lib/action_view/template/handlers/erb.rb +40 -19
  222. data/lib/action_view/template/handlers/raw.rb +11 -0
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/resolver.rb +107 -53
  225. data/lib/action_view/template/text.rb +12 -8
  226. data/lib/action_view/template/types.rb +57 -0
  227. data/lib/action_view/template.rb +25 -23
  228. data/lib/action_view/test_case.rb +67 -42
  229. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  230. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  231. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +13 -2
  232. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +9 -9
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  235. data/lib/action_view/vendor/html-scanner.rb +20 -0
  236. data/lib/action_view.rb +17 -8
  237. metadata +184 -214
  238. data/lib/action_controller/caching/actions.rb +0 -185
  239. data/lib/action_controller/caching/pages.rb +0 -187
  240. data/lib/action_controller/caching/sweeping.rb +0 -97
  241. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  242. data/lib/action_controller/metal/compatibility.rb +0 -65
  243. data/lib/action_controller/metal/session_management.rb +0 -14
  244. data/lib/action_controller/railties/paths.rb +0 -25
  245. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  246. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  247. data/lib/action_dispatch/middleware/head.rb +0 -18
  248. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  249. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  250. data/lib/action_view/asset_paths.rb +0 -142
  251. data/lib/action_view/helpers/asset_paths.rb +0 -7
  252. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  253. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  254. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  255. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  256. data/lib/sprockets/assets.rake +0 -99
  257. data/lib/sprockets/bootstrap.rb +0 -37
  258. data/lib/sprockets/compressors.rb +0 -83
  259. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  260. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/railtie.rb +0 -62
  263. data/lib/sprockets/static_compiler.rb +0 -56
@@ -0,0 +1,76 @@
1
+ require 'action_dispatch/journey/nfa/transition_table'
2
+ require 'action_dispatch/journey/gtg/transition_table'
3
+
4
+ module ActionDispatch
5
+ module Journey # :nodoc:
6
+ module NFA # :nodoc:
7
+ class Visitor < Visitors::Visitor # :nodoc:
8
+ def initialize(tt)
9
+ @tt = tt
10
+ @i = -1
11
+ end
12
+
13
+ def visit_CAT(node)
14
+ left = visit(node.left)
15
+ right = visit(node.right)
16
+
17
+ @tt.merge(left.last, right.first)
18
+
19
+ [left.first, right.last]
20
+ end
21
+
22
+ def visit_GROUP(node)
23
+ from = @i += 1
24
+ left = visit(node.left)
25
+ to = @i += 1
26
+
27
+ @tt.accepting = to
28
+
29
+ @tt[from, left.first] = nil
30
+ @tt[left.last, to] = nil
31
+ @tt[from, to] = nil
32
+
33
+ [from, to]
34
+ end
35
+
36
+ def visit_OR(node)
37
+ from = @i += 1
38
+ children = node.children.map { |c| visit(c) }
39
+ to = @i += 1
40
+
41
+ children.each do |child|
42
+ @tt[from, child.first] = nil
43
+ @tt[child.last, to] = nil
44
+ end
45
+
46
+ @tt.accepting = to
47
+
48
+ [from, to]
49
+ end
50
+
51
+ def terminal(node)
52
+ from_i = @i += 1 # new state
53
+ to_i = @i += 1 # new state
54
+
55
+ @tt[from_i, to_i] = node
56
+ @tt.accepting = to_i
57
+ @tt.add_memo(to_i, node.memo)
58
+
59
+ [from_i, to_i]
60
+ end
61
+ end
62
+
63
+ class Builder # :nodoc:
64
+ def initialize(ast)
65
+ @ast = ast
66
+ end
67
+
68
+ def transition_table
69
+ tt = TransitionTable.new
70
+ Visitor.new(tt).accept(@ast)
71
+ tt
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ module ActionDispatch
4
+ module Journey # :nodoc:
5
+ module NFA # :nodoc:
6
+ module Dot # :nodoc:
7
+ def to_dot
8
+ edges = transitions.map { |from, sym, to|
9
+ " #{from} -> #{to} [label=\"#{sym || 'ε'}\"];"
10
+ }
11
+
12
+ #memo_nodes = memos.values.flatten.map { |n|
13
+ # label = n
14
+ # if Journey::Route === n
15
+ # label = "#{n.verb.source} #{n.path.spec}"
16
+ # end
17
+ # " #{n.object_id} [label=\"#{label}\", shape=box];"
18
+ #}
19
+ #memo_edges = memos.map { |k, memos|
20
+ # (memos || []).map { |v| " #{k} -> #{v.object_id};" }
21
+ #}.flatten.uniq
22
+
23
+ <<-eodot
24
+ digraph nfa {
25
+ rankdir=LR;
26
+ node [shape = doublecircle];
27
+ #{accepting_states.join ' '};
28
+ node [shape = circle];
29
+ #{edges.join "\n"}
30
+ }
31
+ eodot
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ require 'strscan'
2
+
3
+ module ActionDispatch
4
+ module Journey # :nodoc:
5
+ module NFA # :nodoc:
6
+ class MatchData # :nodoc:
7
+ attr_reader :memos
8
+
9
+ def initialize(memos)
10
+ @memos = memos
11
+ end
12
+ end
13
+
14
+ class Simulator # :nodoc:
15
+ attr_reader :tt
16
+
17
+ def initialize(transition_table)
18
+ @tt = transition_table
19
+ end
20
+
21
+ def simulate(string)
22
+ input = StringScanner.new(string)
23
+ state = tt.eclosure(0)
24
+ until input.eos?
25
+ sym = input.scan(%r([/.?]|[^/.?]+))
26
+
27
+ # FIXME: tt.eclosure is not needed for the GTG
28
+ state = tt.eclosure(tt.move(state, sym))
29
+ end
30
+
31
+ acceptance_states = state.find_all { |s|
32
+ tt.accepting?(tt.eclosure(s).sort.last)
33
+ }
34
+
35
+ return if acceptance_states.empty?
36
+
37
+ memos = acceptance_states.map { |x| tt.memo(x) }.flatten.compact
38
+
39
+ MatchData.new(memos)
40
+ end
41
+
42
+ alias :=~ :simulate
43
+ alias :match :simulate
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,163 @@
1
+ require 'action_dispatch/journey/nfa/dot'
2
+
3
+ module ActionDispatch
4
+ module Journey # :nodoc:
5
+ module NFA # :nodoc:
6
+ class TransitionTable # :nodoc:
7
+ include Journey::NFA::Dot
8
+
9
+ attr_accessor :accepting
10
+ attr_reader :memos
11
+
12
+ def initialize
13
+ @table = Hash.new { |h,f| h[f] = {} }
14
+ @memos = {}
15
+ @accepting = nil
16
+ @inverted = nil
17
+ end
18
+
19
+ def accepting?(state)
20
+ accepting == state
21
+ end
22
+
23
+ def accepting_states
24
+ [accepting]
25
+ end
26
+
27
+ def add_memo(idx, memo)
28
+ @memos[idx] = memo
29
+ end
30
+
31
+ def memo(idx)
32
+ @memos[idx]
33
+ end
34
+
35
+ def []=(i, f, s)
36
+ @table[f][i] = s
37
+ end
38
+
39
+ def merge(left, right)
40
+ @memos[right] = @memos.delete(left)
41
+ @table[right] = @table.delete(left)
42
+ end
43
+
44
+ def states
45
+ (@table.keys + @table.values.map(&:keys).flatten).uniq
46
+ end
47
+
48
+ # Returns a generalized transition graph with reduced states. The states
49
+ # are reduced like a DFA, but the table must be simulated like an NFA.
50
+ #
51
+ # Edges of the GTG are regular expressions.
52
+ def generalized_table
53
+ gt = GTG::TransitionTable.new
54
+ marked = {}
55
+ state_id = Hash.new { |h,k| h[k] = h.length }
56
+ alphabet = self.alphabet
57
+
58
+ stack = [eclosure(0)]
59
+
60
+ until stack.empty?
61
+ state = stack.pop
62
+ next if marked[state] || state.empty?
63
+
64
+ marked[state] = true
65
+
66
+ alphabet.each do |alpha|
67
+ next_state = eclosure(following_states(state, alpha))
68
+ next if next_state.empty?
69
+
70
+ gt[state_id[state], state_id[next_state]] = alpha
71
+ stack << next_state
72
+ end
73
+ end
74
+
75
+ final_groups = state_id.keys.find_all { |s|
76
+ s.sort.last == accepting
77
+ }
78
+
79
+ final_groups.each do |states|
80
+ id = state_id[states]
81
+
82
+ gt.add_accepting(id)
83
+ save = states.find { |s|
84
+ @memos.key?(s) && eclosure(s).sort.last == accepting
85
+ }
86
+
87
+ gt.add_memo(id, memo(save))
88
+ end
89
+
90
+ gt
91
+ end
92
+
93
+ # Returns set of NFA states to which there is a transition on ast symbol
94
+ # +a+ from some state +s+ in +t+.
95
+ def following_states(t, a)
96
+ Array(t).map { |s| inverted[s][a] }.flatten.uniq
97
+ end
98
+
99
+ # Returns set of NFA states to which there is a transition on ast symbol
100
+ # +a+ from some state +s+ in +t+.
101
+ def move(t, a)
102
+ Array(t).map { |s|
103
+ inverted[s].keys.compact.find_all { |sym|
104
+ sym === a
105
+ }.map { |sym| inverted[s][sym] }
106
+ }.flatten.uniq
107
+ end
108
+
109
+ def alphabet
110
+ inverted.values.map(&:keys).flatten.compact.uniq.sort_by { |x| x.to_s }
111
+ end
112
+
113
+ # Returns a set of NFA states reachable from some NFA state +s+ in set
114
+ # +t+ on nil-transitions alone.
115
+ def eclosure(t)
116
+ stack = Array(t)
117
+ seen = {}
118
+ children = []
119
+
120
+ until stack.empty?
121
+ s = stack.pop
122
+ next if seen[s]
123
+
124
+ seen[s] = true
125
+ children << s
126
+
127
+ stack.concat(inverted[s][nil])
128
+ end
129
+
130
+ children.uniq
131
+ end
132
+
133
+ def transitions
134
+ @table.map { |to, hash|
135
+ hash.map { |from, sym| [from, sym, to] }
136
+ }.flatten(1)
137
+ end
138
+
139
+ private
140
+
141
+ def inverted
142
+ return @inverted if @inverted
143
+
144
+ @inverted = Hash.new { |h, from|
145
+ h[from] = Hash.new { |j, s| j[s] = [] }
146
+ }
147
+
148
+ @table.each { |to, hash|
149
+ hash.each { |from, sym|
150
+ if sym
151
+ sym = Nodes::Symbol === sym ? sym.regexp : sym.left
152
+ end
153
+
154
+ @inverted[from][sym] << to
155
+ }
156
+ }
157
+
158
+ @inverted
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,124 @@
1
+ require 'action_dispatch/journey/visitors'
2
+
3
+ module ActionDispatch
4
+ module Journey # :nodoc:
5
+ module Nodes # :nodoc:
6
+ class Node # :nodoc:
7
+ include Enumerable
8
+
9
+ attr_accessor :left, :memo
10
+
11
+ def initialize(left)
12
+ @left = left
13
+ @memo = nil
14
+ end
15
+
16
+ def each(&block)
17
+ Visitors::Each.new(block).accept(self)
18
+ end
19
+
20
+ def to_s
21
+ Visitors::String.new.accept(self)
22
+ end
23
+
24
+ def to_dot
25
+ Visitors::Dot.new.accept(self)
26
+ end
27
+
28
+ def to_sym
29
+ name.to_sym
30
+ end
31
+
32
+ def name
33
+ left.tr '*:', ''
34
+ end
35
+
36
+ def type
37
+ raise NotImplementedError
38
+ end
39
+
40
+ def symbol?; false; end
41
+ def literal?; false; end
42
+ end
43
+
44
+ class Terminal < Node # :nodoc:
45
+ alias :symbol :left
46
+ end
47
+
48
+ class Literal < Terminal # :nodoc:
49
+ def literal?; true; end
50
+ def type; :LITERAL; end
51
+ end
52
+
53
+ class Dummy < Literal # :nodoc:
54
+ def initialize(x = Object.new)
55
+ super
56
+ end
57
+
58
+ def literal?; false; end
59
+ end
60
+
61
+ %w{ Symbol Slash Dot }.each do |t|
62
+ class_eval <<-eoruby, __FILE__, __LINE__ + 1
63
+ class #{t} < Terminal;
64
+ def type; :#{t.upcase}; end
65
+ end
66
+ eoruby
67
+ end
68
+
69
+ class Symbol < Terminal # :nodoc:
70
+ attr_accessor :regexp
71
+ alias :symbol :regexp
72
+
73
+ DEFAULT_EXP = /[^\.\/\?]+/
74
+ def initialize(left)
75
+ super
76
+ @regexp = DEFAULT_EXP
77
+ end
78
+
79
+ def default_regexp?
80
+ regexp == DEFAULT_EXP
81
+ end
82
+
83
+ def symbol?; true; end
84
+ end
85
+
86
+ class Unary < Node # :nodoc:
87
+ def children; [left] end
88
+ end
89
+
90
+ class Group < Unary # :nodoc:
91
+ def type; :GROUP; end
92
+ end
93
+
94
+ class Star < Unary # :nodoc:
95
+ def type; :STAR; end
96
+ end
97
+
98
+ class Binary < Node # :nodoc:
99
+ attr_accessor :right
100
+
101
+ def initialize(left, right)
102
+ super(left)
103
+ @right = right
104
+ end
105
+
106
+ def children; [left, right] end
107
+ end
108
+
109
+ class Cat < Binary # :nodoc:
110
+ def type; :CAT; end
111
+ end
112
+
113
+ class Or < Node # :nodoc:
114
+ attr_reader :children
115
+
116
+ def initialize(children)
117
+ @children = children
118
+ end
119
+
120
+ def type; :OR; end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,206 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.9
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+
10
+ require 'action_dispatch/journey/parser_extras'
11
+ module ActionDispatch
12
+ module Journey # :nodoc:
13
+ class Parser < Racc::Parser # :nodoc:
14
+ ##### State transition tables begin ###
15
+
16
+ racc_action_table = [
17
+ 17, 21, 13, 15, 14, 7, nil, 16, 8, 19,
18
+ 13, 15, 14, 7, 23, 16, 8, 19, 13, 15,
19
+ 14, 7, nil, 16, 8, 13, 15, 14, 7, nil,
20
+ 16, 8, 13, 15, 14, 7, nil, 16, 8 ]
21
+
22
+ racc_action_check = [
23
+ 1, 17, 1, 1, 1, 1, nil, 1, 1, 1,
24
+ 20, 20, 20, 20, 20, 20, 20, 20, 7, 7,
25
+ 7, 7, nil, 7, 7, 19, 19, 19, 19, nil,
26
+ 19, 19, 0, 0, 0, 0, nil, 0, 0 ]
27
+
28
+ racc_action_pointer = [
29
+ 30, 0, nil, nil, nil, nil, nil, 16, nil, nil,
30
+ nil, nil, nil, nil, nil, nil, nil, 1, nil, 23,
31
+ 8, nil, nil, nil ]
32
+
33
+ racc_action_default = [
34
+ -18, -18, -2, -3, -4, -5, -6, -18, -9, -10,
35
+ -11, -12, -13, -14, -15, -16, -17, -18, -1, -18,
36
+ -18, 24, -8, -7 ]
37
+
38
+ racc_goto_table = [
39
+ 18, 1, nil, nil, nil, nil, nil, nil, 20, nil,
40
+ nil, nil, nil, nil, nil, nil, nil, nil, 22, 18 ]
41
+
42
+ racc_goto_check = [
43
+ 2, 1, nil, nil, nil, nil, nil, nil, 1, nil,
44
+ nil, nil, nil, nil, nil, nil, nil, nil, 2, 2 ]
45
+
46
+ racc_goto_pointer = [
47
+ nil, 1, -1, nil, nil, nil, nil, nil, nil, nil,
48
+ nil ]
49
+
50
+ racc_goto_default = [
51
+ nil, nil, 2, 3, 4, 5, 6, 9, 10, 11,
52
+ 12 ]
53
+
54
+ racc_reduce_table = [
55
+ 0, 0, :racc_error,
56
+ 2, 11, :_reduce_1,
57
+ 1, 11, :_reduce_2,
58
+ 1, 11, :_reduce_none,
59
+ 1, 12, :_reduce_none,
60
+ 1, 12, :_reduce_none,
61
+ 1, 12, :_reduce_none,
62
+ 3, 15, :_reduce_7,
63
+ 3, 13, :_reduce_8,
64
+ 1, 16, :_reduce_9,
65
+ 1, 14, :_reduce_none,
66
+ 1, 14, :_reduce_none,
67
+ 1, 14, :_reduce_none,
68
+ 1, 14, :_reduce_none,
69
+ 1, 19, :_reduce_14,
70
+ 1, 17, :_reduce_15,
71
+ 1, 18, :_reduce_16,
72
+ 1, 20, :_reduce_17 ]
73
+
74
+ racc_reduce_n = 18
75
+
76
+ racc_shift_n = 24
77
+
78
+ racc_token_table = {
79
+ false => 0,
80
+ :error => 1,
81
+ :SLASH => 2,
82
+ :LITERAL => 3,
83
+ :SYMBOL => 4,
84
+ :LPAREN => 5,
85
+ :RPAREN => 6,
86
+ :DOT => 7,
87
+ :STAR => 8,
88
+ :OR => 9 }
89
+
90
+ racc_nt_base = 10
91
+
92
+ racc_use_result_var = true
93
+
94
+ Racc_arg = [
95
+ racc_action_table,
96
+ racc_action_check,
97
+ racc_action_default,
98
+ racc_action_pointer,
99
+ racc_goto_table,
100
+ racc_goto_check,
101
+ racc_goto_default,
102
+ racc_goto_pointer,
103
+ racc_nt_base,
104
+ racc_reduce_table,
105
+ racc_token_table,
106
+ racc_shift_n,
107
+ racc_reduce_n,
108
+ racc_use_result_var ]
109
+
110
+ Racc_token_to_s_table = [
111
+ "$end",
112
+ "error",
113
+ "SLASH",
114
+ "LITERAL",
115
+ "SYMBOL",
116
+ "LPAREN",
117
+ "RPAREN",
118
+ "DOT",
119
+ "STAR",
120
+ "OR",
121
+ "$start",
122
+ "expressions",
123
+ "expression",
124
+ "or",
125
+ "terminal",
126
+ "group",
127
+ "star",
128
+ "symbol",
129
+ "literal",
130
+ "slash",
131
+ "dot" ]
132
+
133
+ Racc_debug_parser = false
134
+
135
+ ##### State transition tables end #####
136
+
137
+ # reduce 0 omitted
138
+
139
+ def _reduce_1(val, _values, result)
140
+ result = Cat.new(val.first, val.last)
141
+ result
142
+ end
143
+
144
+ def _reduce_2(val, _values, result)
145
+ result = val.first
146
+ result
147
+ end
148
+
149
+ # reduce 3 omitted
150
+
151
+ # reduce 4 omitted
152
+
153
+ # reduce 5 omitted
154
+
155
+ # reduce 6 omitted
156
+
157
+ def _reduce_7(val, _values, result)
158
+ result = Group.new(val[1])
159
+ result
160
+ end
161
+
162
+ def _reduce_8(val, _values, result)
163
+ result = Or.new([val.first, val.last])
164
+ result
165
+ end
166
+
167
+ def _reduce_9(val, _values, result)
168
+ result = Star.new(Symbol.new(val.last))
169
+ result
170
+ end
171
+
172
+ # reduce 10 omitted
173
+
174
+ # reduce 11 omitted
175
+
176
+ # reduce 12 omitted
177
+
178
+ # reduce 13 omitted
179
+
180
+ def _reduce_14(val, _values, result)
181
+ result = Slash.new('/')
182
+ result
183
+ end
184
+
185
+ def _reduce_15(val, _values, result)
186
+ result = Symbol.new(val.first)
187
+ result
188
+ end
189
+
190
+ def _reduce_16(val, _values, result)
191
+ result = Literal.new(val.first)
192
+ result
193
+ end
194
+
195
+ def _reduce_17(val, _values, result)
196
+ result = Dot.new(val.first)
197
+ result
198
+ end
199
+
200
+ def _reduce_none(val, _values, result)
201
+ val[0]
202
+ end
203
+
204
+ end # class Parser
205
+ end # module Journey
206
+ end # module ActionDispatch
@@ -0,0 +1,47 @@
1
+ class ActionDispatch::Journey::Parser
2
+
3
+ token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR
4
+
5
+ rule
6
+ expressions
7
+ : expressions expression { result = Cat.new(val.first, val.last) }
8
+ | expression { result = val.first }
9
+ | or
10
+ ;
11
+ expression
12
+ : terminal
13
+ | group
14
+ | star
15
+ ;
16
+ group
17
+ : LPAREN expressions RPAREN { result = Group.new(val[1]) }
18
+ ;
19
+ or
20
+ : expressions OR expression { result = Or.new([val.first, val.last]) }
21
+ ;
22
+ star
23
+ : STAR { result = Star.new(Symbol.new(val.last)) }
24
+ ;
25
+ terminal
26
+ : symbol
27
+ | literal
28
+ | slash
29
+ | dot
30
+ ;
31
+ slash
32
+ : SLASH { result = Slash.new('/') }
33
+ ;
34
+ symbol
35
+ : SYMBOL { result = Symbol.new(val.first) }
36
+ ;
37
+ literal
38
+ : LITERAL { result = Literal.new(val.first) }
39
+ dot
40
+ : DOT { result = Dot.new(val.first) }
41
+ ;
42
+
43
+ end
44
+
45
+ ---- header
46
+
47
+ require 'action_dispatch/journey/parser_extras'
@@ -0,0 +1,23 @@
1
+ require 'action_dispatch/journey/scanner'
2
+ require 'action_dispatch/journey/nodes/node'
3
+
4
+ module ActionDispatch
5
+ module Journey # :nodoc:
6
+ class Parser < Racc::Parser # :nodoc:
7
+ include Journey::Nodes
8
+
9
+ def initialize
10
+ @scanner = Scanner.new
11
+ end
12
+
13
+ def parse(string)
14
+ @scanner.scan_setup(string)
15
+ do_parse
16
+ end
17
+
18
+ def next_token
19
+ @scanner.next_token
20
+ end
21
+ end
22
+ end
23
+ end