lrama 0.6.11 → 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 (274) 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 +45 -0
  5. data/.github/workflows/test.yaml +57 -18
  6. data/.gitignore +1 -0
  7. data/.rdoc_options +2 -0
  8. data/Gemfile +6 -3
  9. data/NEWS.md +427 -32
  10. data/README.md +43 -95
  11. data/Rakefile +14 -1
  12. data/Steepfile +12 -4
  13. data/doc/Index.md +58 -0
  14. data/doc/development/compressed_state_table/parser.rb +2 -0
  15. data/doc/development/profiling.md +44 -0
  16. data/exe/lrama +1 -1
  17. data/lib/lrama/bitmap.rb +19 -3
  18. data/lib/lrama/command.rb +96 -43
  19. data/lib/lrama/context.rb +22 -24
  20. data/lib/lrama/counterexamples/derivation.rb +14 -4
  21. data/lib/lrama/counterexamples/example.rb +47 -22
  22. data/lib/lrama/counterexamples/node.rb +30 -0
  23. data/lib/lrama/counterexamples/path.rb +12 -14
  24. data/lib/lrama/counterexamples/state_item.rb +24 -1
  25. data/lib/lrama/counterexamples/triple.rb +27 -9
  26. data/lib/lrama/counterexamples.rb +216 -88
  27. data/lib/lrama/diagram.rb +77 -0
  28. data/lib/lrama/digraph.rb +52 -1
  29. data/lib/lrama/erb.rb +29 -0
  30. data/lib/lrama/grammar/auxiliary.rb +6 -1
  31. data/lib/lrama/grammar/binding.rb +60 -16
  32. data/lib/lrama/grammar/code/destructor_code.rb +11 -0
  33. data/lib/lrama/grammar/code/initial_action_code.rb +3 -0
  34. data/lib/lrama/grammar/code/no_reference_code.rb +3 -0
  35. data/lib/lrama/grammar/code/printer_code.rb +11 -0
  36. data/lib/lrama/grammar/code/rule_action.rb +17 -0
  37. data/lib/lrama/grammar/code.rb +16 -1
  38. data/lib/lrama/grammar/counter.rb +10 -0
  39. data/lib/lrama/grammar/destructor.rb +14 -1
  40. data/lib/lrama/grammar/error_token.rb +14 -1
  41. data/lib/lrama/grammar/inline/resolver.rb +80 -0
  42. data/lib/lrama/grammar/inline.rb +3 -0
  43. data/lib/lrama/grammar/{parameterizing_rule → parameterized}/resolver.rb +19 -8
  44. data/lib/lrama/grammar/{parameterizing_rule → parameterized}/rhs.rb +7 -2
  45. data/lib/lrama/grammar/parameterized/rule.rb +36 -0
  46. data/lib/lrama/grammar/parameterized.rb +5 -0
  47. data/lib/lrama/grammar/percent_code.rb +12 -1
  48. data/lib/lrama/grammar/precedence.rb +43 -1
  49. data/lib/lrama/grammar/printer.rb +9 -0
  50. data/lib/lrama/grammar/reference.rb +13 -0
  51. data/lib/lrama/grammar/rule.rb +69 -1
  52. data/lib/lrama/grammar/rule_builder.rb +84 -81
  53. data/lib/lrama/grammar/stdlib.y +68 -48
  54. data/lib/lrama/grammar/symbol.rb +63 -19
  55. data/lib/lrama/grammar/symbols/resolver.rb +64 -3
  56. data/lib/lrama/grammar/type.rb +13 -1
  57. data/lib/lrama/grammar/union.rb +12 -1
  58. data/lib/lrama/grammar.rb +236 -35
  59. data/lib/lrama/lexer/grammar_file.rb +8 -1
  60. data/lib/lrama/lexer/location.rb +42 -9
  61. data/lib/lrama/lexer/token/base.rb +73 -0
  62. data/lib/lrama/lexer/token/char.rb +16 -2
  63. data/lib/lrama/lexer/token/empty.rb +14 -0
  64. data/lib/lrama/lexer/token/ident.rb +3 -2
  65. data/lib/lrama/lexer/token/instantiate_rule.rb +8 -3
  66. data/lib/lrama/lexer/token/int.rb +14 -0
  67. data/lib/lrama/lexer/token/str.rb +11 -0
  68. data/lib/lrama/lexer/token/tag.rb +5 -3
  69. data/lib/lrama/lexer/token/token.rb +11 -0
  70. data/lib/lrama/lexer/token/user_code.rb +68 -38
  71. data/lib/lrama/lexer/token.rb +7 -45
  72. data/lib/lrama/lexer.rb +55 -28
  73. data/lib/lrama/logger.rb +16 -2
  74. data/lib/lrama/option_parser.rb +71 -15
  75. data/lib/lrama/options.rb +26 -7
  76. data/lib/lrama/output.rb +4 -11
  77. data/lib/lrama/parser.rb +858 -721
  78. data/lib/lrama/reporter/conflicts.rb +44 -0
  79. data/lib/lrama/reporter/grammar.rb +39 -0
  80. data/lib/lrama/reporter/precedences.rb +54 -0
  81. data/lib/lrama/reporter/profile/call_stack.rb +45 -0
  82. data/lib/lrama/reporter/profile/memory.rb +44 -0
  83. data/lib/lrama/reporter/profile.rb +4 -0
  84. data/lib/lrama/reporter/rules.rb +43 -0
  85. data/lib/lrama/reporter/states.rb +387 -0
  86. data/lib/lrama/reporter/terms.rb +44 -0
  87. data/lib/lrama/reporter.rb +39 -0
  88. data/lib/lrama/state/action/goto.rb +33 -0
  89. data/lib/lrama/state/action/reduce.rb +71 -0
  90. data/lib/lrama/state/action/shift.rb +39 -0
  91. data/lib/lrama/state/action.rb +5 -0
  92. data/lib/lrama/state/inadequacy_annotation.rb +140 -0
  93. data/lib/lrama/{states → state}/item.rb +40 -3
  94. data/lib/lrama/state/reduce_reduce_conflict.rb +14 -1
  95. data/lib/lrama/state/resolved_conflict.rb +38 -4
  96. data/lib/lrama/state/shift_reduce_conflict.rb +14 -1
  97. data/lib/lrama/state.rb +416 -28
  98. data/lib/lrama/states.rb +483 -144
  99. data/lib/lrama/tracer/actions.rb +22 -0
  100. data/lib/lrama/tracer/closure.rb +30 -0
  101. data/lib/lrama/tracer/duration.rb +38 -0
  102. data/lib/lrama/tracer/only_explicit_rules.rb +24 -0
  103. data/lib/lrama/tracer/rules.rb +23 -0
  104. data/lib/lrama/tracer/state.rb +33 -0
  105. data/lib/lrama/tracer.rb +51 -0
  106. data/lib/lrama/version.rb +2 -1
  107. data/lib/lrama/warnings/conflicts.rb +27 -0
  108. data/lib/lrama/warnings/implicit_empty.rb +29 -0
  109. data/lib/lrama/warnings/name_conflicts.rb +63 -0
  110. data/lib/lrama/warnings/redefined_rules.rb +23 -0
  111. data/lib/lrama/warnings/required.rb +23 -0
  112. data/lib/lrama/warnings/useless_precedence.rb +25 -0
  113. data/lib/lrama/warnings.rb +33 -0
  114. data/lib/lrama.rb +5 -5
  115. data/lrama.gemspec +1 -1
  116. data/parser.y +496 -404
  117. data/rbs_collection.lock.yaml +27 -3
  118. data/rbs_collection.yaml +2 -0
  119. data/sig/generated/lrama/bitmap.rbs +19 -0
  120. data/sig/generated/lrama/counterexamples/derivation.rbs +36 -0
  121. data/sig/generated/lrama/counterexamples/example.rbs +58 -0
  122. data/sig/generated/lrama/counterexamples/node.rbs +18 -0
  123. data/sig/generated/lrama/counterexamples/path.rbs +23 -0
  124. data/sig/generated/lrama/counterexamples/state_item.rbs +19 -0
  125. data/sig/generated/lrama/counterexamples/triple.rbs +32 -0
  126. data/sig/generated/lrama/counterexamples.rbs +98 -0
  127. data/sig/generated/lrama/diagram.rbs +34 -0
  128. data/sig/generated/lrama/digraph.rbs +59 -0
  129. data/sig/generated/lrama/erb.rbs +14 -0
  130. data/sig/generated/lrama/grammar/auxiliary.rbs +16 -0
  131. data/sig/generated/lrama/grammar/binding.rbs +40 -0
  132. data/sig/generated/lrama/grammar/code/destructor_code.rbs +26 -0
  133. data/sig/{lrama → generated/lrama}/grammar/code/initial_action_code.rbs +6 -0
  134. data/sig/{lrama → generated/lrama}/grammar/code/no_reference_code.rbs +6 -0
  135. data/sig/generated/lrama/grammar/code/printer_code.rbs +26 -0
  136. data/sig/generated/lrama/grammar/code/rule_action.rbs +63 -0
  137. data/sig/generated/lrama/grammar/code.rbs +38 -0
  138. data/sig/{lrama → generated/lrama}/grammar/counter.rbs +4 -0
  139. data/sig/generated/lrama/grammar/destructor.rbs +19 -0
  140. data/sig/generated/lrama/grammar/error_token.rbs +19 -0
  141. data/sig/generated/lrama/grammar/inline/resolver.rbs +26 -0
  142. data/sig/generated/lrama/grammar/parameterized/resolver.rbs +42 -0
  143. data/sig/generated/lrama/grammar/parameterized/rhs.rbs +21 -0
  144. data/sig/generated/lrama/grammar/parameterized/rule.rbs +28 -0
  145. data/sig/{lrama → generated/lrama}/grammar/percent_code.rbs +8 -0
  146. data/sig/generated/lrama/grammar/precedence.rbs +45 -0
  147. data/sig/{lrama/grammar/error_token.rbs → generated/lrama/grammar/printer.rbs} +8 -3
  148. data/sig/generated/lrama/grammar/reference.rbs +31 -0
  149. data/sig/generated/lrama/grammar/rule.rbs +83 -0
  150. data/sig/generated/lrama/grammar/rule_builder.rbs +91 -0
  151. data/sig/generated/lrama/grammar/symbol.rbs +89 -0
  152. data/sig/generated/lrama/grammar/symbols/resolver.rbs +131 -0
  153. data/sig/generated/lrama/grammar/type.rbs +21 -0
  154. data/sig/generated/lrama/grammar/union.rbs +17 -0
  155. data/sig/generated/lrama/grammar.rbs +289 -0
  156. data/sig/generated/lrama/lexer/grammar_file.rbs +28 -0
  157. data/sig/generated/lrama/lexer/location.rbs +61 -0
  158. data/sig/generated/lrama/lexer/token/base.rbs +53 -0
  159. data/sig/generated/lrama/lexer/token/char.rbs +17 -0
  160. data/sig/generated/lrama/lexer/token/empty.rbs +11 -0
  161. data/sig/generated/lrama/lexer/token/ident.rbs +10 -0
  162. data/sig/generated/lrama/lexer/token/instantiate_rule.rbs +22 -0
  163. data/sig/generated/lrama/lexer/token/int.rbs +13 -0
  164. data/sig/generated/lrama/lexer/token/str.rbs +10 -0
  165. data/sig/generated/lrama/lexer/token/tag.rbs +12 -0
  166. data/sig/generated/lrama/lexer/token/token.rbs +10 -0
  167. data/sig/{lrama → generated/lrama}/lexer/token/user_code.rbs +8 -3
  168. data/sig/generated/lrama/lexer/token.rbs +8 -0
  169. data/sig/generated/lrama/lexer.rbs +54 -0
  170. data/sig/generated/lrama/logger.rbs +20 -0
  171. data/sig/generated/lrama/option_parser.rbs +52 -0
  172. data/sig/{lrama → generated/lrama}/options.rbs +27 -2
  173. data/sig/generated/lrama/reporter/conflicts.rbs +18 -0
  174. data/sig/generated/lrama/reporter/grammar.rbs +13 -0
  175. data/sig/generated/lrama/reporter/precedences.rbs +15 -0
  176. data/sig/generated/lrama/reporter/profile/call_stack.rbs +19 -0
  177. data/sig/generated/lrama/reporter/profile/memory.rbs +19 -0
  178. data/sig/generated/lrama/reporter/rules.rbs +13 -0
  179. data/sig/generated/lrama/reporter/states.rbs +69 -0
  180. data/sig/generated/lrama/reporter/terms.rbs +13 -0
  181. data/sig/generated/lrama/reporter.rbs +13 -0
  182. data/sig/generated/lrama/state/action/goto.rbs +28 -0
  183. data/sig/generated/lrama/state/action/reduce.rbs +49 -0
  184. data/sig/generated/lrama/state/action/shift.rbs +33 -0
  185. data/sig/generated/lrama/state/inadequacy_annotation.rbs +45 -0
  186. data/sig/generated/lrama/state/item.rbs +75 -0
  187. data/sig/generated/lrama/state/reduce_reduce_conflict.rbs +19 -0
  188. data/sig/generated/lrama/state/resolved_conflict.rbs +38 -0
  189. data/sig/generated/lrama/state/shift_reduce_conflict.rbs +19 -0
  190. data/sig/generated/lrama/state.rbs +231 -0
  191. data/sig/generated/lrama/states.rbs +215 -0
  192. data/sig/generated/lrama/tracer/actions.rbs +13 -0
  193. data/sig/generated/lrama/tracer/closure.rbs +13 -0
  194. data/sig/generated/lrama/tracer/duration.rbs +18 -0
  195. data/sig/generated/lrama/tracer/only_explicit_rules.rbs +13 -0
  196. data/sig/generated/lrama/tracer/rules.rbs +13 -0
  197. data/sig/generated/lrama/tracer/state.rbs +16 -0
  198. data/sig/generated/lrama/tracer.rbs +23 -0
  199. data/sig/generated/lrama/version.rbs +5 -0
  200. data/sig/generated/lrama/warnings/conflicts.rbs +13 -0
  201. data/sig/generated/lrama/warnings/implicit_empty.rbs +17 -0
  202. data/sig/generated/lrama/warnings/name_conflicts.rbs +31 -0
  203. data/sig/generated/lrama/warnings/redefined_rules.rbs +13 -0
  204. data/sig/generated/lrama/warnings/required.rbs +13 -0
  205. data/sig/generated/lrama/warnings/useless_precedence.rbs +13 -0
  206. data/sig/generated/lrama/warnings.rbs +11 -0
  207. data/sig/railroad_diagrams/railroad_diagrams.rbs +16 -0
  208. data/template/bison/_yacc.h +8 -0
  209. data/template/diagram/diagram.html +102 -0
  210. metadata +142 -77
  211. data/lib/lrama/counterexamples/production_path.rb +0 -19
  212. data/lib/lrama/counterexamples/start_path.rb +0 -23
  213. data/lib/lrama/counterexamples/transition_path.rb +0 -19
  214. data/lib/lrama/diagnostics.rb +0 -36
  215. data/lib/lrama/grammar/parameterizing_rule/rule.rb +0 -24
  216. data/lib/lrama/grammar/parameterizing_rule.rb +0 -5
  217. data/lib/lrama/grammar_validator.rb +0 -37
  218. data/lib/lrama/report/duration.rb +0 -27
  219. data/lib/lrama/report/profile.rb +0 -16
  220. data/lib/lrama/report.rb +0 -4
  221. data/lib/lrama/state/reduce.rb +0 -37
  222. data/lib/lrama/state/shift.rb +0 -15
  223. data/lib/lrama/states_reporter.rb +0 -362
  224. data/lib/lrama/trace_reporter.rb +0 -30
  225. data/sig/lrama/bitmap.rbs +0 -7
  226. data/sig/lrama/counterexamples/derivation.rbs +0 -33
  227. data/sig/lrama/counterexamples/example.rbs +0 -45
  228. data/sig/lrama/counterexamples/path.rbs +0 -21
  229. data/sig/lrama/counterexamples/production_path.rbs +0 -11
  230. data/sig/lrama/counterexamples/start_path.rbs +0 -13
  231. data/sig/lrama/counterexamples/state_item.rbs +0 -10
  232. data/sig/lrama/counterexamples/transition_path.rbs +0 -11
  233. data/sig/lrama/counterexamples/triple.rbs +0 -20
  234. data/sig/lrama/counterexamples.rbs +0 -29
  235. data/sig/lrama/digraph.rbs +0 -23
  236. data/sig/lrama/grammar/auxiliary.rbs +0 -10
  237. data/sig/lrama/grammar/binding.rbs +0 -19
  238. data/sig/lrama/grammar/code/destructor_code.rbs +0 -14
  239. data/sig/lrama/grammar/code/printer_code.rbs +0 -14
  240. data/sig/lrama/grammar/code/rule_action.rbs +0 -19
  241. data/sig/lrama/grammar/code.rbs +0 -24
  242. data/sig/lrama/grammar/destructor.rbs +0 -13
  243. data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +0 -24
  244. data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +0 -14
  245. data/sig/lrama/grammar/parameterizing_rule/rule.rbs +0 -16
  246. data/sig/lrama/grammar/parameterizing_rule.rbs +0 -6
  247. data/sig/lrama/grammar/precedence.rbs +0 -13
  248. data/sig/lrama/grammar/printer.rbs +0 -13
  249. data/sig/lrama/grammar/reference.rbs +0 -22
  250. data/sig/lrama/grammar/rule.rbs +0 -45
  251. data/sig/lrama/grammar/rule_builder.rbs +0 -48
  252. data/sig/lrama/grammar/symbol.rbs +0 -38
  253. data/sig/lrama/grammar/symbols/resolver.rbs +0 -60
  254. data/sig/lrama/grammar/type.rbs +0 -11
  255. data/sig/lrama/grammar/union.rbs +0 -12
  256. data/sig/lrama/grammar.rbs +0 -108
  257. data/sig/lrama/lexer/grammar_file.rbs +0 -17
  258. data/sig/lrama/lexer/location.rbs +0 -26
  259. data/sig/lrama/lexer/token/char.rbs +0 -8
  260. data/sig/lrama/lexer/token/ident.rbs +0 -8
  261. data/sig/lrama/lexer/token/instantiate_rule.rbs +0 -14
  262. data/sig/lrama/lexer/token/tag.rbs +0 -9
  263. data/sig/lrama/lexer/token.rbs +0 -23
  264. data/sig/lrama/report/duration.rbs +0 -11
  265. data/sig/lrama/report/profile.rbs +0 -7
  266. data/sig/lrama/state/reduce.rbs +0 -20
  267. data/sig/lrama/state/reduce_reduce_conflict.rbs +0 -13
  268. data/sig/lrama/state/resolved_conflict.rbs +0 -14
  269. data/sig/lrama/state/shift.rbs +0 -14
  270. data/sig/lrama/state/shift_reduce_conflict.rbs +0 -13
  271. data/sig/lrama/state.rbs +0 -79
  272. data/sig/lrama/states/item.rbs +0 -30
  273. data/sig/lrama/states.rbs +0 -101
  274. 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
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]]
14
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
@@ -23,47 +68,77 @@ module Lrama
23
68
  @conflicts = []
24
69
  @resolved_conflicts = []
25
70
  @default_reduction_rule = nil
71
+ @predecessors = []
72
+ @lalr_isocore = self
73
+ @ielr_isocores = [self]
74
+ @internal_dependencies = {}
75
+ @successor_dependencies = {}
76
+ @annotation_list = []
77
+ @lookaheads_recomputed = false
78
+ @follow_kernel_items = {}
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
26
88
  end
27
89
 
90
+ # @rbs (Array[Item] closure) -> void
28
91
  def closure=(closure)
29
92
  @closure = closure
30
93
  @items = @kernels + @closure
31
94
  end
32
95
 
96
+ # @rbs () -> Array[Action::Reduce]
33
97
  def non_default_reduces
34
98
  reduces.reject do |reduce|
35
99
  reduce.rule == @default_reduction_rule
36
100
  end
37
101
  end
38
102
 
39
- def compute_shifts_reduces
40
- _shifts = {}
103
+ # @rbs () -> void
104
+ def compute_transitions_and_reduces
105
+ _transitions = {}
106
+ @_lane_items ||= {}
41
107
  reduces = []
42
108
  items.each do |item|
43
109
  # TODO: Consider what should be pushed
44
110
  if item.end_of_rule?
45
- reduces << Reduce.new(item)
111
+ reduces << Action::Reduce.new(item)
46
112
  else
47
113
  key = item.next_sym
48
- _shifts[key] ||= []
49
- _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]
50
119
  end
51
120
  end
52
121
 
53
122
  # It seems Bison 3.8.2 iterates transitions order by symbol number
54
- shifts = _shifts.sort_by do |next_sym, new_items|
123
+ transitions = _transitions.sort_by do |next_sym, to_items|
55
124
  next_sym.number
56
- end.map do |next_sym, new_items|
57
- Shift.new(next_sym, new_items.flatten)
58
125
  end
59
- self.shifts = shifts.freeze
126
+
127
+ self._transitions = transitions.freeze
60
128
  self.reduces = reduces.freeze
61
129
  end
62
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
63
137
  def set_items_to_state(items, next_state)
64
138
  @items_to_state[items] = next_state
65
139
  end
66
140
 
141
+ # @rbs (Grammar::Rule rule, Array[Grammar::Symbol] look_ahead) -> void
67
142
  def set_look_ahead(rule, look_ahead)
68
143
  reduce = reduces.find do |r|
69
144
  r.rule == rule
@@ -72,38 +147,78 @@ module Lrama
72
147
  reduce.look_ahead = look_ahead
73
148
  end
74
149
 
75
- def nterm_transitions
76
- @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) }
77
162
  end
78
163
 
79
- def term_transitions
80
- @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) }
81
167
  end
82
168
 
169
+ # @rbs () -> Array[transition]
83
170
  def transitions
84
- @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
178
+ end
179
+
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)
183
+ next_state.append_predecessor(self)
184
+ update_transitions_caches(transition)
185
+ end
186
+
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
198
+ @nterm_transitions = nil
199
+ @term_transitions = nil
200
+
201
+ @follow_kernel_items[new_transition] = @follow_kernel_items.delete(transition)
202
+ @always_follows[new_transition] = @always_follows.delete(transition)
85
203
  end
86
204
 
205
+ # @rbs () -> Array[Action::Shift]
87
206
  def selected_term_transitions
88
- term_transitions.reject do |shift, next_state|
207
+ term_transitions.reject do |shift|
89
208
  shift.not_selected
90
209
  end
91
210
  end
92
211
 
93
212
  # Move to next state by sym
213
+ #
214
+ # @rbs (Grammar::Symbol sym) -> State
94
215
  def transition(sym)
95
216
  result = nil
96
217
 
97
218
  if sym.term?
98
- term_transitions.each do |shift, next_state|
99
- term = shift.next_sym
100
- result = next_state if term == sym
101
- end
219
+ result = term_transitions.find {|shift| shift.next_sym == sym }.to_state
102
220
  else
103
- nterm_transitions.each do |shift, next_state|
104
- nterm = shift.next_sym
105
- result = next_state if nterm == sym
106
- end
221
+ result = nterm_transitions.find {|goto| goto.next_sym == sym }.to_state
107
222
  end
108
223
 
109
224
  raise "Can not transit by #{sym} #{self}" if result.nil?
@@ -111,12 +226,14 @@ module Lrama
111
226
  result
112
227
  end
113
228
 
229
+ # @rbs (Item item) -> Action::Reduce
114
230
  def find_reduce_by_item!(item)
115
231
  reduces.find do |r|
116
232
  r.item == item
117
233
  end || (raise "reduce is not found. #{item}")
118
234
  end
119
235
 
236
+ # @rbs (Grammar::Rule default_reduction_rule) -> void
120
237
  def default_reduction_rule=(default_reduction_rule)
121
238
  @default_reduction_rule = default_reduction_rule
122
239
 
@@ -127,20 +244,291 @@ module Lrama
127
244
  end
128
245
  end
129
246
 
247
+ # @rbs () -> bool
130
248
  def has_conflicts?
131
249
  !@conflicts.empty?
132
250
  end
133
251
 
252
+ # @rbs () -> Array[conflict]
134
253
  def sr_conflicts
135
254
  @conflicts.select do |conflict|
136
255
  conflict.type == :shift_reduce
137
256
  end
138
257
  end
139
258
 
259
+ # @rbs () -> Array[conflict]
140
260
  def rr_conflicts
141
261
  @conflicts.select do |conflict|
142
262
  conflict.type == :reduce_reduce
143
263
  end
144
264
  end
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
290
+ def propagate_lookaheads(next_state)
291
+ next_state.kernels.map {|next_kernel|
292
+ lookahead_sets =
293
+ if next_kernel.position > 1
294
+ kernel = kernels.find {|k| k.predecessor_item_of?(next_kernel) }
295
+ item_lookahead_set[kernel]
296
+ else
297
+ goto_follow_set(next_kernel.lhs)
298
+ end
299
+
300
+ [next_kernel, lookahead_sets & next_state.lookahead_set_filters[next_kernel]]
301
+ }.to_h
302
+ end
303
+
304
+ # Definition 3.43 (is_compatible)
305
+ #
306
+ # @rbs (lookahead_set filtered_lookahead) -> bool
307
+ def is_compatible?(filtered_lookahead)
308
+ !lookaheads_recomputed ||
309
+ @lalr_isocore.annotation_list.all? {|annotation|
310
+ a = annotation.dominant_contribution(item_lookahead_set)
311
+ b = annotation.dominant_contribution(filtered_lookahead)
312
+ a.nil? || b.nil? || a == b
313
+ }
314
+ end
315
+
316
+ # Definition 3.38 (lookahead_set_filters)
317
+ #
318
+ # @rbs () -> lookahead_set
319
+ def lookahead_set_filters
320
+ @lookahead_set_filters ||= kernels.map {|kernel|
321
+ [kernel, @lalr_isocore.annotation_list.select {|annotation| annotation.contributed?(kernel) }.map(&:token)]
322
+ }.to_h
323
+ end
324
+
325
+ # Definition 3.27 (inadequacy_lists)
326
+ #
327
+ # @rbs () -> Hash[Grammar::Symbol, Array[Action::Shift | Action::Reduce]]
328
+ def inadequacy_list
329
+ return @inadequacy_list if @inadequacy_list
330
+
331
+ inadequacy_list = {}
332
+
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 }
347
+ end
348
+
349
+ # Definition 3.30 (annotate_manifestation)
350
+ #
351
+ # @rbs () -> void
352
+ def annotate_manifestation
353
+ inadequacy_list.each {|token, actions|
354
+ contribution_matrix = actions.map {|action|
355
+ if action.is_a?(Action::Shift)
356
+ [action, nil]
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]
359
+ end
360
+ }.to_h
361
+ @annotation_list << InadequacyAnnotation.new(self, token, actions, contribution_matrix)
362
+ }
363
+ end
364
+
365
+ # Definition 3.32 (annotate_predecessor)
366
+ #
367
+ # @rbs (State predecessor) -> void
368
+ def annotate_predecessor(predecessor)
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]
375
+ else
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]
382
+ }.to_h
383
+ [action, cs]
384
+ end
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)
397
+ end
398
+
399
+ # @rbs () -> Array[Item]
400
+ def first_kernels
401
+ @first_kernels ||= kernels.select {|kernel| kernel.position == 1 }
402
+ end
403
+
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
410
+ end
411
+
412
+ @annotation_list += propagating_list
413
+ end
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
434
+ def item_lookahead_set
435
+ return @item_lookahead_set if @item_lookahead_set
436
+
437
+ @item_lookahead_set = kernels.map {|k| [k, []] }.to_h
438
+ @item_lookahead_set = kernels.map {|kernel|
439
+ value =
440
+ if kernel.lhs.accept_symbol?
441
+ []
442
+ elsif kernel.position > 1
443
+ prev_items = predecessors_with_item(kernel)
444
+ prev_items.map {|st, i| st.item_lookahead_set[i] }.reduce([]) {|acc, syms| acc |= syms }
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]
449
+ end
450
+ [kernel, value]
451
+ }.to_h
452
+ end
453
+
454
+ # @rbs (lookahead_set k) -> void
455
+ def item_lookahead_set=(k)
456
+ @item_lookahead_set = k
457
+ end
458
+
459
+ # @rbs (Item item) -> Array[[State, Item]]
460
+ def predecessors_with_item(item)
461
+ result = []
462
+ @predecessors.each do |pre|
463
+ pre.items.each do |i|
464
+ result << [pre, i] if i.predecessor_item_of?(item)
465
+ end
466
+ end
467
+ result
468
+ end
469
+
470
+ # @rbs (State prev_state) -> void
471
+ def append_predecessor(prev_state)
472
+ @predecessors << prev_state
473
+ @predecessors.uniq!
474
+ end
475
+
476
+ # Definition 3.39 (compute_goto_follow_set)
477
+ #
478
+ # @rbs (Grammar::Symbol nterm_token) -> Array[Grammar::Symbol]
479
+ def goto_follow_set(nterm_token)
480
+ return [] if nterm_token.accept_symbol?
481
+ goto = @lalr_isocore.nterm_transitions.find {|g| g.next_sym == nterm_token }
482
+
483
+ @kernels
484
+ .select {|kernel| @lalr_isocore.follow_kernel_items[goto][kernel] }
485
+ .map {|kernel| item_lookahead_set[kernel] }
486
+ .reduce(@lalr_isocore.always_follows[goto]) {|result, terms| result |= terms }
487
+ end
488
+
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]
494
+
495
+ syms = @items.select {|i|
496
+ i.next_sym == goto.next_sym && i.symbols_after_transition.all?(&:nullable) && i.position == 0
497
+ }.map(&:lhs).uniq
498
+ @internal_dependencies[goto] = nterm_transitions.select {|goto2| syms.include?(goto2.next_sym) }
499
+ end
500
+
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]
506
+
507
+ @successor_dependencies[goto] = goto.to_state.nterm_transitions.select {|next_goto| next_goto.next_sym.nullable }
508
+ end
509
+
510
+ # Definition 3.9 (Goto Follows Predecessor Relation)
511
+ #
512
+ # @rbs (Action::Goto goto) -> Array[Action::Goto]
513
+ def predecessor_dependencies(goto)
514
+ state_items = []
515
+ @kernels.select {|kernel|
516
+ kernel.next_sym == goto.next_sym && kernel.symbols_after_transition.all?(&:nullable)
517
+ }.each do |item|
518
+ queue = predecessors_with_item(item)
519
+ until queue.empty?
520
+ st, i = queue.pop
521
+ if i.position == 0
522
+ state_items << [st, i]
523
+ else
524
+ st.predecessors_with_item(i).each {|v| queue << v }
525
+ end
526
+ end
527
+ end
528
+
529
+ state_items.map {|state, item|
530
+ state.nterm_transitions.find {|goto2| goto2.next_sym == item.lhs }
531
+ }
532
+ end
145
533
  end
146
534
  end