lrama 0.7.0 → 0.7.1

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 (260) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/codespell.yaml +1 -1
  4. data/.github/workflows/gh-pages.yml +5 -6
  5. data/.github/workflows/test.yaml +25 -14
  6. data/Gemfile +4 -3
  7. data/NEWS.md +370 -35
  8. data/README.md +7 -88
  9. data/Rakefile +3 -2
  10. data/Steepfile +11 -5
  11. data/doc/Index.md +1 -1
  12. data/doc/development/compressed_state_table/parser.rb +2 -0
  13. data/doc/development/profiling.md +44 -0
  14. data/exe/lrama +1 -1
  15. data/lib/lrama/bitmap.rb +18 -5
  16. data/lib/lrama/command.rb +95 -43
  17. data/lib/lrama/context.rb +22 -24
  18. data/lib/lrama/counterexamples/derivation.rb +14 -4
  19. data/lib/lrama/counterexamples/example.rb +47 -22
  20. data/lib/lrama/counterexamples/node.rb +30 -0
  21. data/lib/lrama/counterexamples/path.rb +12 -14
  22. data/lib/lrama/counterexamples/state_item.rb +24 -1
  23. data/lib/lrama/counterexamples/triple.rb +27 -9
  24. data/lib/lrama/counterexamples.rb +216 -88
  25. data/lib/lrama/diagram.rb +77 -0
  26. data/lib/lrama/digraph.rb +28 -7
  27. data/lib/lrama/erb.rb +29 -0
  28. data/lib/lrama/grammar/auxiliary.rb +6 -1
  29. data/lib/lrama/grammar/binding.rb +37 -25
  30. data/lib/lrama/grammar/code/destructor_code.rb +11 -0
  31. data/lib/lrama/grammar/code/initial_action_code.rb +3 -0
  32. data/lib/lrama/grammar/code/no_reference_code.rb +3 -0
  33. data/lib/lrama/grammar/code/printer_code.rb +11 -0
  34. data/lib/lrama/grammar/code/rule_action.rb +17 -0
  35. data/lib/lrama/grammar/code.rb +16 -1
  36. data/lib/lrama/grammar/counter.rb +10 -0
  37. data/lib/lrama/grammar/destructor.rb +14 -1
  38. data/lib/lrama/grammar/error_token.rb +14 -1
  39. data/lib/lrama/grammar/inline/resolver.rb +80 -0
  40. data/lib/lrama/grammar/inline.rb +3 -0
  41. data/lib/lrama/grammar/{parameterizing_rule → parameterized}/resolver.rb +19 -8
  42. data/lib/lrama/grammar/{parameterizing_rule → parameterized}/rhs.rb +7 -2
  43. data/lib/lrama/grammar/parameterized/rule.rb +36 -0
  44. data/lib/lrama/grammar/parameterized.rb +5 -0
  45. data/lib/lrama/grammar/percent_code.rb +12 -1
  46. data/lib/lrama/grammar/precedence.rb +43 -1
  47. data/lib/lrama/grammar/printer.rb +9 -0
  48. data/lib/lrama/grammar/reference.rb +13 -0
  49. data/lib/lrama/grammar/rule.rb +61 -1
  50. data/lib/lrama/grammar/rule_builder.rb +84 -69
  51. data/lib/lrama/grammar/stdlib.y +68 -48
  52. data/lib/lrama/grammar/symbol.rb +63 -19
  53. data/lib/lrama/grammar/symbols/resolver.rb +64 -3
  54. data/lib/lrama/grammar/type.rb +13 -1
  55. data/lib/lrama/grammar/union.rb +12 -1
  56. data/lib/lrama/grammar.rb +231 -35
  57. data/lib/lrama/lexer/location.rb +25 -8
  58. data/lib/lrama/lexer/token/base.rb +73 -0
  59. data/lib/lrama/lexer/token/char.rb +15 -2
  60. data/lib/lrama/lexer/token/empty.rb +14 -0
  61. data/lib/lrama/lexer/token/ident.rb +2 -2
  62. data/lib/lrama/lexer/token/instantiate_rule.rb +4 -4
  63. data/lib/lrama/lexer/token/int.rb +14 -0
  64. data/lib/lrama/lexer/token/str.rb +11 -0
  65. data/lib/lrama/lexer/token/tag.rb +2 -2
  66. data/lib/lrama/lexer/token/token.rb +11 -0
  67. data/lib/lrama/lexer/token/user_code.rb +63 -37
  68. data/lib/lrama/lexer/token.rb +6 -56
  69. data/lib/lrama/lexer.rb +51 -23
  70. data/lib/lrama/logger.rb +12 -2
  71. data/lib/lrama/option_parser.rb +63 -9
  72. data/lib/lrama/options.rb +25 -7
  73. data/lib/lrama/output.rb +4 -11
  74. data/lib/lrama/parser.rb +854 -723
  75. data/lib/lrama/reporter/conflicts.rb +44 -0
  76. data/lib/lrama/reporter/grammar.rb +39 -0
  77. data/lib/lrama/reporter/precedences.rb +54 -0
  78. data/lib/lrama/reporter/profile/call_stack.rb +45 -0
  79. data/lib/lrama/reporter/profile/memory.rb +44 -0
  80. data/lib/lrama/reporter/profile.rb +4 -0
  81. data/lib/lrama/reporter/rules.rb +43 -0
  82. data/lib/lrama/reporter/states.rb +387 -0
  83. data/lib/lrama/reporter/terms.rb +44 -0
  84. data/lib/lrama/reporter.rb +39 -0
  85. data/lib/lrama/state/action/goto.rb +33 -0
  86. data/lib/lrama/state/action/reduce.rb +71 -0
  87. data/lib/lrama/state/action/shift.rb +39 -0
  88. data/lib/lrama/state/action.rb +5 -0
  89. data/lib/lrama/state/inadequacy_annotation.rb +140 -0
  90. data/lib/lrama/{states → state}/item.rb +33 -4
  91. data/lib/lrama/state/reduce_reduce_conflict.rb +14 -1
  92. data/lib/lrama/state/resolved_conflict.rb +38 -4
  93. data/lib/lrama/state/shift_reduce_conflict.rb +14 -1
  94. data/lib/lrama/state.rb +301 -200
  95. data/lib/lrama/states.rb +447 -175
  96. data/lib/lrama/tracer/actions.rb +22 -0
  97. data/lib/lrama/tracer/closure.rb +30 -0
  98. data/lib/lrama/tracer/duration.rb +38 -0
  99. data/lib/lrama/tracer/only_explicit_rules.rb +24 -0
  100. data/lib/lrama/tracer/rules.rb +23 -0
  101. data/lib/lrama/tracer/state.rb +33 -0
  102. data/lib/lrama/tracer.rb +51 -0
  103. data/lib/lrama/version.rb +2 -1
  104. data/lib/lrama/warnings/conflicts.rb +27 -0
  105. data/lib/lrama/warnings/implicit_empty.rb +29 -0
  106. data/lib/lrama/warnings/name_conflicts.rb +63 -0
  107. data/lib/lrama/warnings/redefined_rules.rb +23 -0
  108. data/lib/lrama/warnings/required.rb +23 -0
  109. data/lib/lrama/warnings/useless_precedence.rb +25 -0
  110. data/lib/lrama/warnings.rb +33 -0
  111. data/lib/lrama.rb +5 -5
  112. data/parser.y +495 -404
  113. data/rbs_collection.lock.yaml +27 -3
  114. data/rbs_collection.yaml +2 -0
  115. data/sig/generated/lrama/bitmap.rbs +12 -4
  116. data/sig/generated/lrama/counterexamples/derivation.rbs +36 -0
  117. data/sig/generated/lrama/counterexamples/example.rbs +58 -0
  118. data/sig/generated/lrama/counterexamples/node.rbs +18 -0
  119. data/sig/generated/lrama/counterexamples/path.rbs +23 -0
  120. data/sig/generated/lrama/counterexamples/state_item.rbs +19 -0
  121. data/sig/generated/lrama/counterexamples/triple.rbs +32 -0
  122. data/sig/generated/lrama/counterexamples.rbs +98 -0
  123. data/sig/generated/lrama/diagram.rbs +34 -0
  124. data/sig/generated/lrama/digraph.rbs +26 -6
  125. data/sig/generated/lrama/erb.rbs +14 -0
  126. data/sig/generated/lrama/grammar/auxiliary.rbs +16 -0
  127. data/sig/generated/lrama/grammar/binding.rbs +18 -12
  128. data/sig/generated/lrama/grammar/code/destructor_code.rbs +26 -0
  129. data/sig/{lrama → generated/lrama}/grammar/code/initial_action_code.rbs +6 -0
  130. data/sig/{lrama → generated/lrama}/grammar/code/no_reference_code.rbs +6 -0
  131. data/sig/generated/lrama/grammar/code/printer_code.rbs +26 -0
  132. data/sig/generated/lrama/grammar/code/rule_action.rbs +63 -0
  133. data/sig/generated/lrama/grammar/code.rbs +38 -0
  134. data/sig/{lrama → generated/lrama}/grammar/counter.rbs +4 -0
  135. data/sig/generated/lrama/grammar/destructor.rbs +19 -0
  136. data/sig/generated/lrama/grammar/error_token.rbs +19 -0
  137. data/sig/generated/lrama/grammar/inline/resolver.rbs +26 -0
  138. data/sig/generated/lrama/grammar/parameterized/resolver.rbs +42 -0
  139. data/sig/generated/lrama/grammar/parameterized/rhs.rbs +21 -0
  140. data/sig/generated/lrama/grammar/parameterized/rule.rbs +28 -0
  141. data/sig/{lrama → generated/lrama}/grammar/percent_code.rbs +8 -0
  142. data/sig/generated/lrama/grammar/precedence.rbs +45 -0
  143. data/sig/{lrama/grammar/error_token.rbs → generated/lrama/grammar/printer.rbs} +8 -3
  144. data/sig/generated/lrama/grammar/reference.rbs +31 -0
  145. data/sig/generated/lrama/grammar/rule.rbs +83 -0
  146. data/sig/generated/lrama/grammar/rule_builder.rbs +91 -0
  147. data/sig/generated/lrama/grammar/symbol.rbs +89 -0
  148. data/sig/generated/lrama/grammar/symbols/resolver.rbs +131 -0
  149. data/sig/generated/lrama/grammar/type.rbs +21 -0
  150. data/sig/generated/lrama/grammar/union.rbs +17 -0
  151. data/sig/generated/lrama/grammar.rbs +289 -0
  152. data/sig/generated/lrama/lexer/location.rbs +12 -3
  153. data/sig/generated/lrama/lexer/token/base.rbs +53 -0
  154. data/sig/generated/lrama/lexer/token/char.rbs +9 -2
  155. data/sig/generated/lrama/lexer/token/empty.rbs +11 -0
  156. data/sig/generated/lrama/lexer/token/ident.rbs +2 -2
  157. data/sig/generated/lrama/lexer/token/instantiate_rule.rbs +5 -5
  158. data/sig/generated/lrama/lexer/token/int.rbs +13 -0
  159. data/sig/generated/lrama/lexer/token/str.rbs +10 -0
  160. data/sig/generated/lrama/lexer/token/tag.rbs +2 -2
  161. data/sig/generated/lrama/lexer/token/token.rbs +10 -0
  162. data/sig/generated/lrama/lexer/token/user_code.rbs +2 -2
  163. data/sig/generated/lrama/lexer/token.rbs +1 -39
  164. data/sig/generated/lrama/lexer.rbs +54 -0
  165. data/sig/generated/lrama/logger.rbs +6 -0
  166. data/sig/generated/lrama/option_parser.rbs +52 -0
  167. data/sig/{lrama → generated/lrama}/options.rbs +27 -3
  168. data/sig/generated/lrama/reporter/conflicts.rbs +18 -0
  169. data/sig/generated/lrama/reporter/grammar.rbs +13 -0
  170. data/sig/generated/lrama/reporter/precedences.rbs +15 -0
  171. data/sig/generated/lrama/reporter/profile/call_stack.rbs +19 -0
  172. data/sig/generated/lrama/reporter/profile/memory.rbs +19 -0
  173. data/sig/generated/lrama/reporter/rules.rbs +13 -0
  174. data/sig/generated/lrama/reporter/states.rbs +69 -0
  175. data/sig/generated/lrama/reporter/terms.rbs +13 -0
  176. data/sig/generated/lrama/reporter.rbs +13 -0
  177. data/sig/generated/lrama/state/action/goto.rbs +28 -0
  178. data/sig/generated/lrama/state/action/reduce.rbs +49 -0
  179. data/sig/generated/lrama/state/action/shift.rbs +33 -0
  180. data/sig/generated/lrama/state/inadequacy_annotation.rbs +45 -0
  181. data/sig/generated/lrama/state/item.rbs +75 -0
  182. data/sig/generated/lrama/state/reduce_reduce_conflict.rbs +19 -0
  183. data/sig/generated/lrama/state/resolved_conflict.rbs +38 -0
  184. data/sig/generated/lrama/state/shift_reduce_conflict.rbs +19 -0
  185. data/sig/generated/lrama/state.rbs +231 -0
  186. data/sig/generated/lrama/states.rbs +215 -0
  187. data/sig/generated/lrama/tracer/actions.rbs +13 -0
  188. data/sig/generated/lrama/tracer/closure.rbs +13 -0
  189. data/sig/generated/lrama/tracer/duration.rbs +18 -0
  190. data/sig/generated/lrama/tracer/only_explicit_rules.rbs +13 -0
  191. data/sig/generated/lrama/tracer/rules.rbs +13 -0
  192. data/sig/generated/lrama/tracer/state.rbs +16 -0
  193. data/sig/generated/lrama/tracer.rbs +23 -0
  194. data/sig/generated/lrama/version.rbs +5 -0
  195. data/sig/generated/lrama/warnings/conflicts.rbs +13 -0
  196. data/sig/generated/lrama/warnings/implicit_empty.rbs +17 -0
  197. data/sig/generated/lrama/warnings/name_conflicts.rbs +31 -0
  198. data/sig/generated/lrama/warnings/redefined_rules.rbs +13 -0
  199. data/sig/generated/lrama/warnings/required.rbs +13 -0
  200. data/sig/generated/lrama/warnings/useless_precedence.rbs +13 -0
  201. data/sig/generated/lrama/warnings.rbs +11 -0
  202. data/sig/railroad_diagrams/railroad_diagrams.rbs +16 -0
  203. data/template/bison/_yacc.h +8 -0
  204. data/template/diagram/diagram.html +102 -0
  205. metadata +126 -66
  206. data/lib/lrama/counterexamples/production_path.rb +0 -19
  207. data/lib/lrama/counterexamples/start_path.rb +0 -23
  208. data/lib/lrama/counterexamples/transition_path.rb +0 -19
  209. data/lib/lrama/diagnostics.rb +0 -36
  210. data/lib/lrama/grammar/parameterizing_rule/rule.rb +0 -24
  211. data/lib/lrama/grammar/parameterizing_rule.rb +0 -5
  212. data/lib/lrama/grammar_validator.rb +0 -37
  213. data/lib/lrama/report/duration.rb +0 -27
  214. data/lib/lrama/report/profile.rb +0 -16
  215. data/lib/lrama/report.rb +0 -4
  216. data/lib/lrama/state/reduce.rb +0 -37
  217. data/lib/lrama/state/shift.rb +0 -15
  218. data/lib/lrama/states_reporter.rb +0 -362
  219. data/lib/lrama/trace_reporter.rb +0 -45
  220. data/sig/generated/lrama/trace_reporter.rbs +0 -25
  221. data/sig/lrama/counterexamples/derivation.rbs +0 -33
  222. data/sig/lrama/counterexamples/example.rbs +0 -45
  223. data/sig/lrama/counterexamples/path.rbs +0 -21
  224. data/sig/lrama/counterexamples/production_path.rbs +0 -11
  225. data/sig/lrama/counterexamples/start_path.rbs +0 -13
  226. data/sig/lrama/counterexamples/state_item.rbs +0 -10
  227. data/sig/lrama/counterexamples/transition_path.rbs +0 -11
  228. data/sig/lrama/counterexamples/triple.rbs +0 -20
  229. data/sig/lrama/counterexamples.rbs +0 -29
  230. data/sig/lrama/grammar/auxiliary.rbs +0 -10
  231. data/sig/lrama/grammar/code/destructor_code.rbs +0 -14
  232. data/sig/lrama/grammar/code/printer_code.rbs +0 -14
  233. data/sig/lrama/grammar/code/rule_action.rbs +0 -19
  234. data/sig/lrama/grammar/code.rbs +0 -24
  235. data/sig/lrama/grammar/destructor.rbs +0 -13
  236. data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +0 -24
  237. data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +0 -14
  238. data/sig/lrama/grammar/parameterizing_rule/rule.rbs +0 -16
  239. data/sig/lrama/grammar/parameterizing_rule.rbs +0 -6
  240. data/sig/lrama/grammar/precedence.rbs +0 -13
  241. data/sig/lrama/grammar/printer.rbs +0 -13
  242. data/sig/lrama/grammar/reference.rbs +0 -22
  243. data/sig/lrama/grammar/rule.rbs +0 -45
  244. data/sig/lrama/grammar/rule_builder.rbs +0 -47
  245. data/sig/lrama/grammar/symbol.rbs +0 -38
  246. data/sig/lrama/grammar/symbols/resolver.rbs +0 -60
  247. data/sig/lrama/grammar/type.rbs +0 -11
  248. data/sig/lrama/grammar/union.rbs +0 -12
  249. data/sig/lrama/grammar.rbs +0 -108
  250. data/sig/lrama/report/duration.rbs +0 -11
  251. data/sig/lrama/report/profile.rbs +0 -7
  252. data/sig/lrama/state/reduce.rbs +0 -20
  253. data/sig/lrama/state/reduce_reduce_conflict.rbs +0 -13
  254. data/sig/lrama/state/resolved_conflict.rbs +0 -14
  255. data/sig/lrama/state/shift.rbs +0 -14
  256. data/sig/lrama/state/shift_reduce_conflict.rbs +0 -13
  257. data/sig/lrama/state.rbs +0 -79
  258. data/sig/lrama/states/item.rbs +0 -30
  259. data/sig/lrama/states.rbs +0 -101
  260. data/sig/lrama/warning.rbs +0 -16
data/lib/lrama/state.rb CHANGED
@@ -1,17 +1,62 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
- require_relative "state/reduce"
4
+ require_relative "state/action"
5
+ require_relative "state/inadequacy_annotation"
6
+ require_relative "state/item"
4
7
  require_relative "state/reduce_reduce_conflict"
5
8
  require_relative "state/resolved_conflict"
6
- require_relative "state/shift"
7
9
  require_relative "state/shift_reduce_conflict"
8
10
 
9
11
  module Lrama
10
12
  class State
11
- attr_reader :id, :accessing_symbol, :kernels, :conflicts, :resolved_conflicts,
12
- :default_reduction_rule, :closure, :items
13
- attr_accessor :shifts, :reduces, :ielr_isocores, :lalr_isocore
14
-
13
+ # TODO: rbs-inline 0.11.0 doesn't support instance variables.
14
+ # Move these type declarations above instance variable definitions, once it's supported.
15
+ # see: https://github.com/soutaro/rbs-inline/pull/149
16
+ #
17
+ # @rbs!
18
+ # type conflict = State::ShiftReduceConflict | State::ReduceReduceConflict
19
+ # type transition = Action::Shift | Action::Goto
20
+ # type lookahead_set = Hash[Item, Array[Grammar::Symbol]]
21
+ #
22
+ # @id: Integer
23
+ # @accessing_symbol: Grammar::Symbol
24
+ # @kernels: Array[Item]
25
+ # @items: Array[Item]
26
+ # @items_to_state: Hash[Array[Item], State]
27
+ # @conflicts: Array[conflict]
28
+ # @resolved_conflicts: Array[ResolvedConflict]
29
+ # @default_reduction_rule: Grammar::Rule?
30
+ # @closure: Array[Item]
31
+ # @nterm_transitions: Array[Action::Goto]
32
+ # @term_transitions: Array[Action::Shift]
33
+ # @transitions: Array[transition]
34
+ # @internal_dependencies: Hash[Action::Goto, Array[Action::Goto]]
35
+ # @successor_dependencies: Hash[Action::Goto, Array[Action::Goto]]
36
+
37
+ attr_reader :id #: Integer
38
+ attr_reader :accessing_symbol #: Grammar::Symbol
39
+ attr_reader :kernels #: Array[Item]
40
+ attr_reader :conflicts #: Array[conflict]
41
+ attr_reader :resolved_conflicts #: Array[ResolvedConflict]
42
+ attr_reader :default_reduction_rule #: Grammar::Rule?
43
+ attr_reader :closure #: Array[Item]
44
+ attr_reader :items #: Array[Item]
45
+ attr_reader :annotation_list #: Array[InadequacyAnnotation]
46
+ attr_reader :predecessors #: Array[State]
47
+ attr_reader :items_to_state #: Hash[Array[Item], State]
48
+ attr_reader :lane_items #: Hash[State, Array[[Item, Item]]]
49
+
50
+ attr_accessor :_transitions #: Array[[Grammar::Symbol, Array[Item]]]
51
+ attr_accessor :reduces #: Array[Action::Reduce]
52
+ attr_accessor :ielr_isocores #: Array[State]
53
+ attr_accessor :lalr_isocore #: State
54
+ attr_accessor :lookaheads_recomputed #: bool
55
+ attr_accessor :follow_kernel_items #: Hash[Action::Goto, Hash[Item, bool]]
56
+ attr_accessor :always_follows #: Hash[Action::Goto, Array[Grammar::Symbol]]
57
+ attr_accessor :goto_follows #: Hash[Action::Goto, Array[Grammar::Symbol]]
58
+
59
+ # @rbs (Integer id, Grammar::Symbol accessing_symbol, Array[Item] kernels) -> void
15
60
  def initialize(id, accessing_symbol, kernels)
16
61
  @id = id
17
62
  @accessing_symbol = accessing_symbol
@@ -28,48 +73,72 @@ module Lrama
28
73
  @ielr_isocores = [self]
29
74
  @internal_dependencies = {}
30
75
  @successor_dependencies = {}
76
+ @annotation_list = []
77
+ @lookaheads_recomputed = false
78
+ @follow_kernel_items = {}
31
79
  @always_follows = {}
80
+ @goto_follows = {}
81
+ @lhs_contributions = {}
82
+ @lane_items = {}
83
+ end
84
+
85
+ # @rbs (State other) -> bool
86
+ def ==(other)
87
+ self.id == other.id
32
88
  end
33
89
 
90
+ # @rbs (Array[Item] closure) -> void
34
91
  def closure=(closure)
35
92
  @closure = closure
36
93
  @items = @kernels + @closure
37
94
  end
38
95
 
96
+ # @rbs () -> Array[Action::Reduce]
39
97
  def non_default_reduces
40
98
  reduces.reject do |reduce|
41
99
  reduce.rule == @default_reduction_rule
42
100
  end
43
101
  end
44
102
 
45
- def compute_shifts_reduces
46
- _shifts = {}
103
+ # @rbs () -> void
104
+ def compute_transitions_and_reduces
105
+ _transitions = {}
106
+ @_lane_items ||= {}
47
107
  reduces = []
48
108
  items.each do |item|
49
109
  # TODO: Consider what should be pushed
50
110
  if item.end_of_rule?
51
- reduces << Reduce.new(item)
111
+ reduces << Action::Reduce.new(item)
52
112
  else
53
113
  key = item.next_sym
54
- _shifts[key] ||= []
55
- _shifts[key] << item.new_by_next_position
114
+ _transitions[key] ||= []
115
+ @_lane_items[key] ||= []
116
+ next_item = item.new_by_next_position
117
+ _transitions[key] << next_item
118
+ @_lane_items[key] << [item, next_item]
56
119
  end
57
120
  end
58
121
 
59
122
  # It seems Bison 3.8.2 iterates transitions order by symbol number
60
- shifts = _shifts.sort_by do |next_sym, new_items|
123
+ transitions = _transitions.sort_by do |next_sym, to_items|
61
124
  next_sym.number
62
- end.map do |next_sym, new_items|
63
- Shift.new(next_sym, new_items.flatten)
64
125
  end
65
- self.shifts = shifts.freeze
126
+
127
+ self._transitions = transitions.freeze
66
128
  self.reduces = reduces.freeze
67
129
  end
68
130
 
131
+ # @rbs (Grammar::Symbol next_sym, State next_state) -> void
132
+ def set_lane_items(next_sym, next_state)
133
+ @lane_items[next_state] = @_lane_items[next_sym]
134
+ end
135
+
136
+ # @rbs (Array[Item] items, State next_state) -> void
69
137
  def set_items_to_state(items, next_state)
70
138
  @items_to_state[items] = next_state
71
139
  end
72
140
 
141
+ # @rbs (Grammar::Rule rule, Array[Grammar::Symbol] look_ahead) -> void
73
142
  def set_look_ahead(rule, look_ahead)
74
143
  reduce = reduces.find do |r|
75
144
  r.rule == rule
@@ -78,50 +147,78 @@ module Lrama
78
147
  reduce.look_ahead = look_ahead
79
148
  end
80
149
 
81
- def nterm_transitions
82
- @nterm_transitions ||= transitions.select {|shift, _| shift.next_sym.nterm? }
150
+ # @rbs (Grammar::Rule rule, Hash[Grammar::Symbol, Array[Action::Goto]] sources) -> void
151
+ def set_look_ahead_sources(rule, sources)
152
+ reduce = reduces.find do |r|
153
+ r.rule == rule
154
+ end
155
+
156
+ reduce.look_ahead_sources = sources
157
+ end
158
+
159
+ # @rbs () -> Array[Action::Goto]
160
+ def nterm_transitions # steep:ignore
161
+ @nterm_transitions ||= transitions.select {|transition| transition.is_a?(Action::Goto) }
83
162
  end
84
163
 
85
- def term_transitions
86
- @term_transitions ||= transitions.select {|shift, _| shift.next_sym.term? }
164
+ # @rbs () -> Array[Action::Shift]
165
+ def term_transitions # steep:ignore
166
+ @term_transitions ||= transitions.select {|transition| transition.is_a?(Action::Shift) }
87
167
  end
88
168
 
169
+ # @rbs () -> Array[transition]
89
170
  def transitions
90
- @transitions ||= shifts.map {|shift| [shift, @items_to_state[shift.next_items]] }
171
+ @transitions ||= _transitions.map do |next_sym, to_items|
172
+ if next_sym.term?
173
+ Action::Shift.new(self, next_sym, to_items.flatten, @items_to_state[to_items])
174
+ else
175
+ Action::Goto.new(self, next_sym, to_items.flatten, @items_to_state[to_items])
176
+ end
177
+ end
91
178
  end
92
179
 
93
- def update_transition(shift, next_state)
94
- set_items_to_state(shift.next_items, next_state)
180
+ # @rbs (transition transition, State next_state) -> void
181
+ def update_transition(transition, next_state)
182
+ set_items_to_state(transition.to_items, next_state)
95
183
  next_state.append_predecessor(self)
96
- clear_transitions_cache
184
+ update_transitions_caches(transition)
97
185
  end
98
186
 
99
- def clear_transitions_cache
187
+ # @rbs () -> void
188
+ def update_transitions_caches(transition)
189
+ new_transition =
190
+ if transition.next_sym.term?
191
+ Action::Shift.new(self, transition.next_sym, transition.to_items, @items_to_state[transition.to_items])
192
+ else
193
+ Action::Goto.new(self, transition.next_sym, transition.to_items, @items_to_state[transition.to_items])
194
+ end
195
+
196
+ @transitions.delete(transition)
197
+ @transitions << new_transition
100
198
  @nterm_transitions = nil
101
199
  @term_transitions = nil
102
- @transitions = nil
200
+
201
+ @follow_kernel_items[new_transition] = @follow_kernel_items.delete(transition)
202
+ @always_follows[new_transition] = @always_follows.delete(transition)
103
203
  end
104
204
 
205
+ # @rbs () -> Array[Action::Shift]
105
206
  def selected_term_transitions
106
- term_transitions.reject do |shift, next_state|
207
+ term_transitions.reject do |shift|
107
208
  shift.not_selected
108
209
  end
109
210
  end
110
211
 
111
212
  # Move to next state by sym
213
+ #
214
+ # @rbs (Grammar::Symbol sym) -> State
112
215
  def transition(sym)
113
216
  result = nil
114
217
 
115
218
  if sym.term?
116
- term_transitions.each do |shift, next_state|
117
- term = shift.next_sym
118
- result = next_state if term == sym
119
- end
219
+ result = term_transitions.find {|shift| shift.next_sym == sym }.to_state
120
220
  else
121
- nterm_transitions.each do |shift, next_state|
122
- nterm = shift.next_sym
123
- result = next_state if nterm == sym
124
- end
221
+ result = nterm_transitions.find {|goto| goto.next_sym == sym }.to_state
125
222
  end
126
223
 
127
224
  raise "Can not transit by #{sym} #{self}" if result.nil?
@@ -129,12 +226,14 @@ module Lrama
129
226
  result
130
227
  end
131
228
 
229
+ # @rbs (Item item) -> Action::Reduce
132
230
  def find_reduce_by_item!(item)
133
231
  reduces.find do |r|
134
232
  r.item == item
135
233
  end || (raise "reduce is not found. #{item}")
136
234
  end
137
235
 
236
+ # @rbs (Grammar::Rule default_reduction_rule) -> void
138
237
  def default_reduction_rule=(default_reduction_rule)
139
238
  @default_reduction_rule = default_reduction_rule
140
239
 
@@ -145,200 +244,219 @@ module Lrama
145
244
  end
146
245
  end
147
246
 
247
+ # @rbs () -> bool
148
248
  def has_conflicts?
149
249
  !@conflicts.empty?
150
250
  end
151
251
 
252
+ # @rbs () -> Array[conflict]
152
253
  def sr_conflicts
153
254
  @conflicts.select do |conflict|
154
255
  conflict.type == :shift_reduce
155
256
  end
156
257
  end
157
258
 
259
+ # @rbs () -> Array[conflict]
158
260
  def rr_conflicts
159
261
  @conflicts.select do |conflict|
160
262
  conflict.type == :reduce_reduce
161
263
  end
162
264
  end
163
265
 
266
+ # Clear information related to conflicts.
267
+ # IELR computation re-calculates conflicts and default reduction of states
268
+ # after LALR computation.
269
+ # Call this method before IELR computation to avoid duplicated conflicts information
270
+ # is stored.
271
+ #
272
+ # @rbs () -> void
273
+ def clear_conflicts
274
+ @conflicts = []
275
+ @resolved_conflicts = []
276
+ @default_reduction_rule = nil
277
+
278
+ term_transitions.each(&:clear_conflicts)
279
+ reduces.each(&:clear_conflicts)
280
+ end
281
+
282
+ # @rbs () -> bool
283
+ def split_state?
284
+ @lalr_isocore != self
285
+ end
286
+
287
+ # Definition 3.40 (propagate_lookaheads)
288
+ #
289
+ # @rbs (State next_state) -> lookahead_set
164
290
  def propagate_lookaheads(next_state)
165
- next_state.kernels.map {|item|
291
+ next_state.kernels.map {|next_kernel|
166
292
  lookahead_sets =
167
- if item.position == 1
168
- goto_follow_set(item.lhs)
169
- else
170
- kernel = kernels.find {|k| k.predecessor_item_of?(item) }
293
+ if next_kernel.position > 1
294
+ kernel = kernels.find {|k| k.predecessor_item_of?(next_kernel) }
171
295
  item_lookahead_set[kernel]
296
+ else
297
+ goto_follow_set(next_kernel.lhs)
172
298
  end
173
299
 
174
- [item, lookahead_sets & next_state.lookahead_set_filters[item]]
300
+ [next_kernel, lookahead_sets & next_state.lookahead_set_filters[next_kernel]]
175
301
  }.to_h
176
302
  end
177
303
 
178
- def lookaheads_recomputed
179
- !@item_lookahead_set.nil?
180
- end
181
-
182
- def compatible_lookahead?(filtered_lookahead)
304
+ # Definition 3.43 (is_compatible)
305
+ #
306
+ # @rbs (lookahead_set filtered_lookahead) -> bool
307
+ def is_compatible?(filtered_lookahead)
183
308
  !lookaheads_recomputed ||
184
- @lalr_isocore.annotation_list.all? {|token, actions|
185
- a = dominant_contribution(token, actions, item_lookahead_set)
186
- b = dominant_contribution(token, actions, filtered_lookahead)
309
+ @lalr_isocore.annotation_list.all? {|annotation|
310
+ a = annotation.dominant_contribution(item_lookahead_set)
311
+ b = annotation.dominant_contribution(filtered_lookahead)
187
312
  a.nil? || b.nil? || a == b
188
313
  }
189
314
  end
190
315
 
316
+ # Definition 3.38 (lookahead_set_filters)
317
+ #
318
+ # @rbs () -> lookahead_set
191
319
  def lookahead_set_filters
192
- kernels.map {|kernel|
193
- [kernel,
194
- @lalr_isocore.annotation_list.select {|token, actions|
195
- token.term? && actions.any? {|action, contributions|
196
- !contributions.nil? && contributions.key?(kernel) && contributions[kernel]
197
- }
198
- }.map {|token, _| token }
199
- ]
320
+ @lookahead_set_filters ||= kernels.map {|kernel|
321
+ [kernel, @lalr_isocore.annotation_list.select {|annotation| annotation.contributed?(kernel) }.map(&:token)]
200
322
  }.to_h
201
323
  end
202
324
 
203
- def dominant_contribution(token, actions, lookaheads)
204
- a = actions.select {|action, contributions|
205
- contributions.nil? || contributions.any? {|item, contributed| contributed && lookaheads[item].include?(token) }
206
- }.map {|action, _| action }
207
- return nil if a.empty?
208
- a.reject {|action|
209
- if action.is_a?(State::Shift)
210
- action.not_selected
211
- elsif action.is_a?(State::Reduce)
212
- action.not_selected_symbols.include?(token)
213
- end
214
- }
215
- end
216
-
325
+ # Definition 3.27 (inadequacy_lists)
326
+ #
327
+ # @rbs () -> Hash[Grammar::Symbol, Array[Action::Shift | Action::Reduce]]
217
328
  def inadequacy_list
218
329
  return @inadequacy_list if @inadequacy_list
219
330
 
220
- shift_contributions = shifts.map {|shift|
221
- [shift.next_sym, [shift]]
222
- }.to_h
223
- reduce_contributions = reduces.map {|reduce|
224
- (reduce.look_ahead || []).map {|sym|
225
- [sym, [reduce]]
226
- }.to_h
227
- }.reduce(Hash.new([])) {|hash, cont|
228
- hash.merge(cont) {|_, a, b| a | b }
229
- }
331
+ inadequacy_list = {}
230
332
 
231
- list = shift_contributions.merge(reduce_contributions) {|_, a, b| a | b }
232
- @inadequacy_list = list.select {|token, actions| token.term? && actions.size > 1 }
233
- end
234
-
235
- def annotation_list
236
- return @annotation_list if @annotation_list
237
-
238
- @annotation_list = annotate_manifestation
239
- @annotation_list = @items_to_state.values.map {|next_state| next_state.annotate_predecessor(self) }
240
- .reduce(@annotation_list) {|result, annotations|
241
- result.merge(annotations) {|_, actions_a, actions_b|
242
- if actions_a.nil? || actions_b.nil?
243
- actions_a || actions_b
244
- else
245
- actions_a.merge(actions_b) {|_, contributions_a, contributions_b|
246
- if contributions_a.nil? || contributions_b.nil?
247
- next contributions_a || contributions_b
248
- end
249
-
250
- contributions_a.merge(contributions_b) {|_, contributed_a, contributed_b|
251
- contributed_a || contributed_b
252
- }
253
- }
254
- end
255
- }
256
- }
333
+ term_transitions.each do |shift|
334
+ inadequacy_list[shift.next_sym] ||= []
335
+ inadequacy_list[shift.next_sym] << shift.dup
336
+ end
337
+ reduces.each do |reduce|
338
+ next if reduce.look_ahead.nil?
339
+
340
+ reduce.look_ahead.each do |token|
341
+ inadequacy_list[token] ||= []
342
+ inadequacy_list[token] << reduce.dup
343
+ end
344
+ end
345
+
346
+ @inadequacy_list = inadequacy_list.select {|token, actions| actions.size > 1 }
257
347
  end
258
348
 
349
+ # Definition 3.30 (annotate_manifestation)
350
+ #
351
+ # @rbs () -> void
259
352
  def annotate_manifestation
260
- inadequacy_list.transform_values {|actions|
261
- actions.map {|action|
262
- if action.is_a?(Shift)
353
+ inadequacy_list.each {|token, actions|
354
+ contribution_matrix = actions.map {|action|
355
+ if action.is_a?(Action::Shift)
263
356
  [action, nil]
264
- elsif action.is_a?(Reduce)
265
- if action.rule.empty_rule?
266
- [action, lhs_contributions(action.rule.lhs, inadequacy_list.key(actions))]
267
- else
268
- contributions = kernels.map {|kernel| [kernel, kernel.rule == action.rule && kernel.end_of_rule?] }.to_h
269
- [action, contributions]
270
- end
357
+ else
358
+ [action, action.rule.empty_rule? ? lhs_contributions(action.rule.lhs, token) : kernels.map {|k| [k, k.rule == action.item.rule && k.end_of_rule?] }.to_h]
271
359
  end
272
360
  }.to_h
361
+ @annotation_list << InadequacyAnnotation.new(self, token, actions, contribution_matrix)
273
362
  }
274
363
  end
275
364
 
365
+ # Definition 3.32 (annotate_predecessor)
366
+ #
367
+ # @rbs (State predecessor) -> void
276
368
  def annotate_predecessor(predecessor)
277
- annotation_list.transform_values {|actions|
278
- token = annotation_list.key(actions)
279
- actions.transform_values {|inadequacy|
280
- next nil if inadequacy.nil?
281
- lhs_adequacy = kernels.any? {|kernel|
282
- inadequacy[kernel] && kernel.position == 1 && predecessor.lhs_contributions(kernel.lhs, token).nil?
283
- }
284
- if lhs_adequacy
285
- next nil
369
+ propagating_list = annotation_list.map {|annotation|
370
+ contribution_matrix = annotation.contribution_matrix.map {|action, contributions|
371
+ if contributions.nil?
372
+ [action, nil]
373
+ elsif first_kernels.any? {|kernel| contributions[kernel] && predecessor.lhs_contributions(kernel.lhs, annotation.token).empty? }
374
+ [action, nil]
286
375
  else
287
- predecessor.kernels.map {|pred_k|
288
- [pred_k, kernels.any? {|k|
289
- inadequacy[k] && (
290
- pred_k.predecessor_item_of?(k) && predecessor.item_lookahead_set[pred_k].include?(token) ||
291
- k.position == 1 && predecessor.lhs_contributions(k.lhs, token)[pred_k]
292
- )
293
- }]
376
+ cs = predecessor.lane_items[self].map {|pred_kernel, kernel|
377
+ c = contributions[kernel] && (
378
+ (kernel.position > 1 && predecessor.item_lookahead_set[pred_kernel].include?(annotation.token)) ||
379
+ (kernel.position == 1 && predecessor.lhs_contributions(kernel.lhs, annotation.token)[pred_kernel])
380
+ )
381
+ [pred_kernel, c]
294
382
  }.to_h
383
+ [action, cs]
295
384
  end
296
- }
297
- }
385
+ }.to_h
386
+
387
+ # Observation 3.33 (Simple Split-Stable Dominance)
388
+ #
389
+ # If all of contributions in the contribution_matrix are
390
+ # always contribution or never contribution, we can stop annotate propagations
391
+ # to the predecessor state.
392
+ next nil if contribution_matrix.all? {|_, contributions| contributions.nil? || contributions.all? {|_, contributed| !contributed } }
393
+
394
+ InadequacyAnnotation.new(annotation.state, annotation.token, annotation.actions, contribution_matrix)
395
+ }.compact
396
+ predecessor.append_annotation_list(propagating_list)
298
397
  end
299
398
 
300
- def lhs_contributions(sym, token)
301
- shift, next_state = nterm_transitions.find {|sh, _| sh.next_sym == sym }
302
- if always_follows(shift, next_state).include?(token)
303
- nil
304
- else
305
- kernels.map {|kernel| [kernel, follow_kernel_items(shift, next_state, kernel) && item_lookahead_set[kernel].include?(token)] }.to_h
306
- end
399
+ # @rbs () -> Array[Item]
400
+ def first_kernels
401
+ @first_kernels ||= kernels.select {|kernel| kernel.position == 1 }
307
402
  end
308
403
 
309
- def follow_kernel_items(shift, next_state, kernel)
310
- queue = [[self, shift, next_state]]
311
- until queue.empty?
312
- st, sh, next_st = queue.pop
313
- return true if kernel.next_sym == sh.next_sym && kernel.symbols_after_transition.all?(&:nullable)
314
- st.internal_dependencies(sh, next_st).each {|v| queue << v }
404
+ # @rbs (Array[InadequacyAnnotation] propagating_list) -> void
405
+ def append_annotation_list(propagating_list)
406
+ annotation_list.each do |annotation|
407
+ merging_list = propagating_list.select {|a| a.state == annotation.state && a.token == annotation.token && a.actions == annotation.actions }
408
+ annotation.merge_matrix(merging_list.map(&:contribution_matrix))
409
+ propagating_list -= merging_list
315
410
  end
316
- false
411
+
412
+ @annotation_list += propagating_list
317
413
  end
318
414
 
415
+ # Definition 3.31 (compute_lhs_contributions)
416
+ #
417
+ # @rbs (Grammar::Symbol sym, Grammar::Symbol token) -> (nil | Hash[Item, bool])
418
+ def lhs_contributions(sym, token)
419
+ return @lhs_contributions[sym][token] unless @lhs_contributions.dig(sym, token).nil?
420
+
421
+ transition = nterm_transitions.find {|goto| goto.next_sym == sym }
422
+ @lhs_contributions[sym] ||= {}
423
+ @lhs_contributions[sym][token] =
424
+ if always_follows[transition].include?(token)
425
+ {}
426
+ else
427
+ kernels.map {|kernel| [kernel, follow_kernel_items[transition][kernel] && item_lookahead_set[kernel].include?(token)] }.to_h
428
+ end
429
+ end
430
+
431
+ # Definition 3.26 (item_lookahead_sets)
432
+ #
433
+ # @rbs () -> lookahead_set
319
434
  def item_lookahead_set
320
435
  return @item_lookahead_set if @item_lookahead_set
321
436
 
322
- kernels.map {|item|
437
+ @item_lookahead_set = kernels.map {|k| [k, []] }.to_h
438
+ @item_lookahead_set = kernels.map {|kernel|
323
439
  value =
324
- if item.lhs.accept_symbol?
440
+ if kernel.lhs.accept_symbol?
325
441
  []
326
- elsif item.position > 1
327
- prev_items = predecessors_with_item(item)
442
+ elsif kernel.position > 1
443
+ prev_items = predecessors_with_item(kernel)
328
444
  prev_items.map {|st, i| st.item_lookahead_set[i] }.reduce([]) {|acc, syms| acc |= syms }
329
- elsif item.position == 1
330
- prev_state = @predecessors.find {|p| p.shifts.any? {|shift| shift.next_sym == item.lhs } }
331
- shift, next_state = prev_state.nterm_transitions.find {|shift, _| shift.next_sym == item.lhs }
332
- prev_state.goto_follows(shift, next_state)
445
+ elsif kernel.position == 1
446
+ prev_state = @predecessors.find {|p| p.transitions.any? {|transition| transition.next_sym == kernel.lhs } }
447
+ goto = prev_state.nterm_transitions.find {|goto| goto.next_sym == kernel.lhs }
448
+ prev_state.goto_follows[goto]
333
449
  end
334
- [item, value]
450
+ [kernel, value]
335
451
  }.to_h
336
452
  end
337
453
 
454
+ # @rbs (lookahead_set k) -> void
338
455
  def item_lookahead_set=(k)
339
456
  @item_lookahead_set = k
340
457
  end
341
458
 
459
+ # @rbs (Item item) -> Array[[State, Item]]
342
460
  def predecessors_with_item(item)
343
461
  result = []
344
462
  @predecessors.each do |pre|
@@ -349,69 +467,53 @@ module Lrama
349
467
  result
350
468
  end
351
469
 
470
+ # @rbs (State prev_state) -> void
352
471
  def append_predecessor(prev_state)
353
472
  @predecessors << prev_state
354
473
  @predecessors.uniq!
355
474
  end
356
475
 
476
+ # Definition 3.39 (compute_goto_follow_set)
477
+ #
478
+ # @rbs (Grammar::Symbol nterm_token) -> Array[Grammar::Symbol]
357
479
  def goto_follow_set(nterm_token)
358
480
  return [] if nterm_token.accept_symbol?
359
- shift, next_state = @lalr_isocore.nterm_transitions.find {|sh, _| sh.next_sym == nterm_token }
481
+ goto = @lalr_isocore.nterm_transitions.find {|g| g.next_sym == nterm_token }
360
482
 
361
483
  @kernels
362
- .select {|kernel| follow_kernel_items(shift, next_state, kernel) }
484
+ .select {|kernel| @lalr_isocore.follow_kernel_items[goto][kernel] }
363
485
  .map {|kernel| item_lookahead_set[kernel] }
364
- .reduce(always_follows(shift, next_state)) {|result, terms| result |= terms }
365
- end
366
-
367
- def goto_follows(shift, next_state)
368
- queue = internal_dependencies(shift, next_state) + predecessor_dependencies(shift, next_state)
369
- terms = always_follows(shift, next_state)
370
- until queue.empty?
371
- st, sh, next_st = queue.pop
372
- terms |= st.always_follows(sh, next_st)
373
- st.internal_dependencies(sh, next_st).each {|v| queue << v }
374
- st.predecessor_dependencies(sh, next_st).each {|v| queue << v }
375
- end
376
- terms
377
- end
378
-
379
- def always_follows(shift, next_state)
380
- return @always_follows[[shift, next_state]] if @always_follows[[shift, next_state]]
381
-
382
- queue = internal_dependencies(shift, next_state) + successor_dependencies(shift, next_state)
383
- terms = []
384
- until queue.empty?
385
- st, sh, next_st = queue.pop
386
- terms |= next_st.term_transitions.map {|sh, _| sh.next_sym }
387
- st.internal_dependencies(sh, next_st).each {|v| queue << v }
388
- st.successor_dependencies(sh, next_st).each {|v| queue << v }
389
- end
390
- @always_follows[[shift, next_state]] = terms
486
+ .reduce(@lalr_isocore.always_follows[goto]) {|result, terms| result |= terms }
391
487
  end
392
488
 
393
- def internal_dependencies(shift, next_state)
394
- return @internal_dependencies[[shift, next_state]] if @internal_dependencies[[shift, next_state]]
489
+ # Definition 3.8 (Goto Follows Internal Relation)
490
+ #
491
+ # @rbs (Action::Goto goto) -> Array[Action::Goto]
492
+ def internal_dependencies(goto)
493
+ return @internal_dependencies[goto] if @internal_dependencies[goto]
395
494
 
396
495
  syms = @items.select {|i|
397
- i.next_sym == shift.next_sym && i.symbols_after_transition.all?(&:nullable) && i.position == 0
496
+ i.next_sym == goto.next_sym && i.symbols_after_transition.all?(&:nullable) && i.position == 0
398
497
  }.map(&:lhs).uniq
399
- @internal_dependencies[[shift, next_state]] = nterm_transitions.select {|sh, _| syms.include?(sh.next_sym) }.map {|goto| [self, *goto] }
498
+ @internal_dependencies[goto] = nterm_transitions.select {|goto2| syms.include?(goto2.next_sym) }
400
499
  end
401
500
 
402
- def successor_dependencies(shift, next_state)
403
- return @successor_dependencies[[shift, next_state]] if @successor_dependencies[[shift, next_state]]
501
+ # Definition 3.5 (Goto Follows Successor Relation)
502
+ #
503
+ # @rbs (Action::Goto goto) -> Array[Action::Goto]
504
+ def successor_dependencies(goto)
505
+ return @successor_dependencies[goto] if @successor_dependencies[goto]
404
506
 
405
- @successor_dependencies[[shift, next_state]] =
406
- next_state.nterm_transitions
407
- .select {|next_shift, _| next_shift.next_sym.nullable }
408
- .map {|transition| [next_state, *transition] }
507
+ @successor_dependencies[goto] = goto.to_state.nterm_transitions.select {|next_goto| next_goto.next_sym.nullable }
409
508
  end
410
509
 
411
- def predecessor_dependencies(shift, next_state)
510
+ # Definition 3.9 (Goto Follows Predecessor Relation)
511
+ #
512
+ # @rbs (Action::Goto goto) -> Array[Action::Goto]
513
+ def predecessor_dependencies(goto)
412
514
  state_items = []
413
515
  @kernels.select {|kernel|
414
- kernel.next_sym == shift.next_sym && kernel.symbols_after_transition.all?(&:nullable)
516
+ kernel.next_sym == goto.next_sym && kernel.symbols_after_transition.all?(&:nullable)
415
517
  }.each do |item|
416
518
  queue = predecessors_with_item(item)
417
519
  until queue.empty?
@@ -425,8 +527,7 @@ module Lrama
425
527
  end
426
528
 
427
529
  state_items.map {|state, item|
428
- sh, next_st = state.nterm_transitions.find {|shi, _| shi.next_sym == item.lhs }
429
- [state, sh, next_st]
530
+ state.nterm_transitions.find {|goto2| goto2.next_sym == item.lhs }
430
531
  }
431
532
  end
432
533
  end