lrama 0.6.11 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gh-pages.yml +46 -0
  3. data/.github/workflows/test.yaml +35 -7
  4. data/.gitignore +1 -0
  5. data/.rdoc_options +2 -0
  6. data/Gemfile +4 -2
  7. data/NEWS.md +60 -0
  8. data/README.md +44 -15
  9. data/Rakefile +13 -1
  10. data/Steepfile +2 -0
  11. data/doc/Index.md +58 -0
  12. data/lib/lrama/bitmap.rb +3 -0
  13. data/lib/lrama/command.rb +2 -1
  14. data/lib/lrama/digraph.rb +30 -0
  15. data/lib/lrama/grammar/binding.rb +47 -15
  16. data/lib/lrama/grammar/rule.rb +8 -0
  17. data/lib/lrama/grammar/rule_builder.rb +3 -15
  18. data/lib/lrama/grammar.rb +8 -3
  19. data/lib/lrama/lexer/grammar_file.rb +8 -1
  20. data/lib/lrama/lexer/location.rb +17 -1
  21. data/lib/lrama/lexer/token/char.rb +1 -0
  22. data/lib/lrama/lexer/token/ident.rb +1 -0
  23. data/lib/lrama/lexer/token/instantiate_rule.rb +6 -1
  24. data/lib/lrama/lexer/token/tag.rb +3 -1
  25. data/lib/lrama/lexer/token/user_code.rb +5 -1
  26. data/lib/lrama/lexer/token.rb +14 -2
  27. data/lib/lrama/lexer.rb +4 -5
  28. data/lib/lrama/logger.rb +4 -0
  29. data/lib/lrama/option_parser.rb +10 -8
  30. data/lib/lrama/options.rb +2 -1
  31. data/lib/lrama/parser.rb +10 -4
  32. data/lib/lrama/state.rb +288 -1
  33. data/lib/lrama/states/item.rb +8 -0
  34. data/lib/lrama/states.rb +69 -2
  35. data/lib/lrama/trace_reporter.rb +17 -2
  36. data/lib/lrama/version.rb +1 -1
  37. data/lrama.gemspec +1 -1
  38. data/parser.y +4 -3
  39. data/rbs_collection.lock.yaml +3 -3
  40. data/sig/generated/lrama/bitmap.rbs +11 -0
  41. data/sig/generated/lrama/digraph.rbs +39 -0
  42. data/sig/generated/lrama/grammar/binding.rbs +34 -0
  43. data/sig/generated/lrama/lexer/grammar_file.rbs +28 -0
  44. data/sig/generated/lrama/lexer/location.rbs +52 -0
  45. data/sig/{lrama → generated/lrama}/lexer/token/char.rbs +2 -0
  46. data/sig/{lrama → generated/lrama}/lexer/token/ident.rbs +2 -0
  47. data/sig/{lrama → generated/lrama}/lexer/token/instantiate_rule.rbs +8 -0
  48. data/sig/{lrama → generated/lrama}/lexer/token/tag.rbs +3 -0
  49. data/sig/{lrama → generated/lrama}/lexer/token/user_code.rbs +6 -1
  50. data/sig/{lrama → generated/lrama}/lexer/token.rbs +26 -3
  51. data/sig/generated/lrama/logger.rbs +14 -0
  52. data/sig/generated/lrama/trace_reporter.rbs +25 -0
  53. data/sig/lrama/grammar/rule_builder.rbs +0 -1
  54. data/sig/lrama/options.rbs +1 -0
  55. metadata +19 -14
  56. data/sig/lrama/bitmap.rbs +0 -7
  57. data/sig/lrama/digraph.rbs +0 -23
  58. data/sig/lrama/grammar/binding.rbs +0 -19
  59. data/sig/lrama/lexer/grammar_file.rbs +0 -17
  60. data/sig/lrama/lexer/location.rbs +0 -26
data/lib/lrama/state.rb CHANGED
@@ -10,7 +10,7 @@ module Lrama
10
10
  class State
11
11
  attr_reader :id, :accessing_symbol, :kernels, :conflicts, :resolved_conflicts,
12
12
  :default_reduction_rule, :closure, :items
13
- attr_accessor :shifts, :reduces
13
+ attr_accessor :shifts, :reduces, :ielr_isocores, :lalr_isocore
14
14
 
15
15
  def initialize(id, accessing_symbol, kernels)
16
16
  @id = id
@@ -23,6 +23,12 @@ module Lrama
23
23
  @conflicts = []
24
24
  @resolved_conflicts = []
25
25
  @default_reduction_rule = nil
26
+ @predecessors = []
27
+ @lalr_isocore = self
28
+ @ielr_isocores = [self]
29
+ @internal_dependencies = {}
30
+ @successor_dependencies = {}
31
+ @always_follows = {}
26
32
  end
27
33
 
28
34
  def closure=(closure)
@@ -84,6 +90,18 @@ module Lrama
84
90
  @transitions ||= shifts.map {|shift| [shift, @items_to_state[shift.next_items]] }
85
91
  end
86
92
 
93
+ def update_transition(shift, next_state)
94
+ set_items_to_state(shift.next_items, next_state)
95
+ next_state.append_predecessor(self)
96
+ clear_transitions_cache
97
+ end
98
+
99
+ def clear_transitions_cache
100
+ @nterm_transitions = nil
101
+ @term_transitions = nil
102
+ @transitions = nil
103
+ end
104
+
87
105
  def selected_term_transitions
88
106
  term_transitions.reject do |shift, next_state|
89
107
  shift.not_selected
@@ -142,5 +160,274 @@ module Lrama
142
160
  conflict.type == :reduce_reduce
143
161
  end
144
162
  end
163
+
164
+ def propagate_lookaheads(next_state)
165
+ next_state.kernels.map {|item|
166
+ 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) }
171
+ item_lookahead_set[kernel]
172
+ end
173
+
174
+ [item, lookahead_sets & next_state.lookahead_set_filters[item]]
175
+ }.to_h
176
+ end
177
+
178
+ def lookaheads_recomputed
179
+ !@item_lookahead_set.nil?
180
+ end
181
+
182
+ def compatible_lookahead?(filtered_lookahead)
183
+ !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)
187
+ a.nil? || b.nil? || a == b
188
+ }
189
+ end
190
+
191
+ 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
+ ]
200
+ }.to_h
201
+ end
202
+
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
+
217
+ def inadequacy_list
218
+ return @inadequacy_list if @inadequacy_list
219
+
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
+ }
230
+
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
+ }
257
+ end
258
+
259
+ def annotate_manifestation
260
+ inadequacy_list.transform_values {|actions|
261
+ actions.map {|action|
262
+ if action.is_a?(Shift)
263
+ [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
271
+ end
272
+ }.to_h
273
+ }
274
+ end
275
+
276
+ 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
286
+ 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
+ }]
294
+ }.to_h
295
+ end
296
+ }
297
+ }
298
+ end
299
+
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
307
+ end
308
+
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 }
315
+ end
316
+ false
317
+ end
318
+
319
+ def item_lookahead_set
320
+ return @item_lookahead_set if @item_lookahead_set
321
+
322
+ kernels.map {|item|
323
+ value =
324
+ if item.lhs.accept_symbol?
325
+ []
326
+ elsif item.position > 1
327
+ prev_items = predecessors_with_item(item)
328
+ 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)
333
+ end
334
+ [item, value]
335
+ }.to_h
336
+ end
337
+
338
+ def item_lookahead_set=(k)
339
+ @item_lookahead_set = k
340
+ end
341
+
342
+ def predecessors_with_item(item)
343
+ result = []
344
+ @predecessors.each do |pre|
345
+ pre.items.each do |i|
346
+ result << [pre, i] if i.predecessor_item_of?(item)
347
+ end
348
+ end
349
+ result
350
+ end
351
+
352
+ def append_predecessor(prev_state)
353
+ @predecessors << prev_state
354
+ @predecessors.uniq!
355
+ end
356
+
357
+ def goto_follow_set(nterm_token)
358
+ return [] if nterm_token.accept_symbol?
359
+ shift, next_state = @lalr_isocore.nterm_transitions.find {|sh, _| sh.next_sym == nterm_token }
360
+
361
+ @kernels
362
+ .select {|kernel| follow_kernel_items(shift, next_state, kernel) }
363
+ .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
391
+ end
392
+
393
+ def internal_dependencies(shift, next_state)
394
+ return @internal_dependencies[[shift, next_state]] if @internal_dependencies[[shift, next_state]]
395
+
396
+ syms = @items.select {|i|
397
+ i.next_sym == shift.next_sym && i.symbols_after_transition.all?(&:nullable) && i.position == 0
398
+ }.map(&:lhs).uniq
399
+ @internal_dependencies[[shift, next_state]] = nterm_transitions.select {|sh, _| syms.include?(sh.next_sym) }.map {|goto| [self, *goto] }
400
+ end
401
+
402
+ def successor_dependencies(shift, next_state)
403
+ return @successor_dependencies[[shift, next_state]] if @successor_dependencies[[shift, next_state]]
404
+
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] }
409
+ end
410
+
411
+ def predecessor_dependencies(shift, next_state)
412
+ state_items = []
413
+ @kernels.select {|kernel|
414
+ kernel.next_sym == shift.next_sym && kernel.symbols_after_transition.all?(&:nullable)
415
+ }.each do |item|
416
+ queue = predecessors_with_item(item)
417
+ until queue.empty?
418
+ st, i = queue.pop
419
+ if i.position == 0
420
+ state_items << [st, i]
421
+ else
422
+ st.predecessors_with_item(i).each {|v| queue << v }
423
+ end
424
+ end
425
+ end
426
+
427
+ state_items.map {|state, item|
428
+ sh, next_st = state.nterm_transitions.find {|shi, _| shi.next_sym == item.lhs }
429
+ [state, sh, next_st]
430
+ }
431
+ end
145
432
  end
146
433
  end
@@ -64,6 +64,10 @@ module Lrama
64
64
  rhs[position..-1]
65
65
  end
66
66
 
67
+ def symbols_after_transition
68
+ rhs[position+1..-1]
69
+ end
70
+
67
71
  def to_s
68
72
  "#{lhs.id.s_value}: #{display_name}"
69
73
  end
@@ -78,6 +82,10 @@ module Lrama
78
82
  r = symbols_after_dot.map(&:display_name).join(" ")
79
83
  ". #{r} (rule #{rule_id})"
80
84
  end
85
+
86
+ def predecessor_item_of?(other_item)
87
+ rule == other_item.rule && position == other_item.position - 1
88
+ end
81
89
  end
82
90
  end
83
91
  end
data/lib/lrama/states.rb CHANGED
@@ -41,6 +41,8 @@ module Lrama
41
41
  # value is array of [state.id, nterm.token_id].
42
42
  @reads_relation = {}
43
43
 
44
+ # `Read(p, A) =s DR(p, A) ∪ ∪{Read(r, C) | (p, A) reads (r, C)}`
45
+ #
44
46
  # `@read_sets` is a hash whose
45
47
  # key is [state.id, nterm.token_id],
46
48
  # value is bitmap of term.
@@ -62,6 +64,8 @@ module Lrama
62
64
  # value is array of [state.id, nterm.token_id].
63
65
  @lookback_relation = {}
64
66
 
67
+ # `Follow(p, A) =s Read(p, A) ∪ ∪{Follow(p', B) | (p, A) includes (p', B)}`
68
+ #
65
69
  # `@follow_sets` is a hash whose
66
70
  # key is [state.id, rule.id],
67
71
  # value is bitmap of term.
@@ -92,6 +96,20 @@ module Lrama
92
96
  report_duration(:compute_default_reduction) { compute_default_reduction }
93
97
  end
94
98
 
99
+ def compute_ielr
100
+ report_duration(:split_states) { split_states }
101
+ report_duration(:compute_direct_read_sets) { compute_direct_read_sets }
102
+ report_duration(:compute_reads_relation) { compute_reads_relation }
103
+ report_duration(:compute_read_sets) { compute_read_sets }
104
+ report_duration(:compute_includes_relation) { compute_includes_relation }
105
+ report_duration(:compute_lookback_relation) { compute_lookback_relation }
106
+ report_duration(:compute_follow_sets) { compute_follow_sets }
107
+ report_duration(:compute_look_ahead_sets) { compute_look_ahead_sets }
108
+ report_duration(:compute_conflicts) { compute_conflicts }
109
+
110
+ report_duration(:compute_default_reduction) { compute_default_reduction }
111
+ end
112
+
95
113
  def reporter
96
114
  StatesReporter.new(self)
97
115
  end
@@ -235,7 +253,7 @@ module Lrama
235
253
  # Trace
236
254
  previous = state.kernels.first.previous_sym
237
255
  trace_state do |out|
238
- out << sprintf("state_list_append (state = %d, symbol = %d (%s))",
256
+ out << sprintf("state_list_append (state = %d, symbol = %d (%s))\n",
239
257
  @states.count, previous.number, previous.display_name)
240
258
  end
241
259
 
@@ -265,7 +283,10 @@ module Lrama
265
283
  state.shifts.each do |shift|
266
284
  new_state, created = create_state(shift.next_sym, shift.next_items, states_created)
267
285
  state.set_items_to_state(shift.next_items, new_state)
268
- enqueue_state(states, new_state) if created
286
+ if created
287
+ enqueue_state(states, new_state)
288
+ new_state.append_predecessor(state)
289
+ end
269
290
  end
270
291
  end
271
292
  end
@@ -524,5 +545,51 @@ module Lrama
524
545
  end.first
525
546
  end
526
547
  end
548
+
549
+ def split_states
550
+ @states.each do |state|
551
+ state.transitions.each do |shift, next_state|
552
+ compute_state(state, shift, next_state)
553
+ end
554
+ end
555
+ end
556
+
557
+ def merge_lookaheads(state, filtered_lookaheads)
558
+ return if state.kernels.all? {|item| (filtered_lookaheads[item] - state.item_lookahead_set[item]).empty? }
559
+
560
+ state.item_lookahead_set = state.item_lookahead_set.merge {|_, v1, v2| v1 | v2 }
561
+ state.transitions.each do |shift, next_state|
562
+ next if next_state.lookaheads_recomputed
563
+ compute_state(state, shift, next_state)
564
+ end
565
+ end
566
+
567
+ def compute_state(state, shift, next_state)
568
+ filtered_lookaheads = state.propagate_lookaheads(next_state)
569
+ s = next_state.ielr_isocores.find {|st| st.compatible_lookahead?(filtered_lookaheads) }
570
+
571
+ if s.nil?
572
+ s = next_state.ielr_isocores.last
573
+ new_state = State.new(@states.count, s.accessing_symbol, s.kernels)
574
+ new_state.closure = s.closure
575
+ new_state.compute_shifts_reduces
576
+ s.transitions.each do |sh, next_state|
577
+ new_state.set_items_to_state(sh.next_items, next_state)
578
+ end
579
+ @states << new_state
580
+ new_state.lalr_isocore = s
581
+ s.ielr_isocores << new_state
582
+ s.ielr_isocores.each do |st|
583
+ st.ielr_isocores = s.ielr_isocores
584
+ end
585
+ new_state.item_lookahead_set = filtered_lookaheads
586
+ state.update_transition(shift, new_state)
587
+ elsif(!s.lookaheads_recomputed)
588
+ s.item_lookahead_set = filtered_lookaheads
589
+ else
590
+ state.update_transition(shift, s)
591
+ merge_lookaheads(s, filtered_lookaheads)
592
+ end
593
+ end
527
594
  end
528
595
  end
@@ -1,27 +1,42 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  class TraceReporter
6
+ # @rbs (Lrama::Grammar grammar) -> void
5
7
  def initialize(grammar)
6
8
  @grammar = grammar
7
9
  end
8
10
 
11
+ # @rbs (**Hash[Symbol, bool] options) -> void
9
12
  def report(**options)
10
13
  _report(**options)
11
14
  end
12
15
 
13
16
  private
14
17
 
15
- def _report(rules: false, actions: false, **_)
16
- report_rules if rules
18
+ # @rbs rules: (bool rules, bool actions, bool only_explicit_rules, **untyped _) -> void
19
+ def _report(rules: false, actions: false, only_explicit_rules: false, **_)
20
+ report_rules if rules && !only_explicit_rules
21
+ report_only_explicit_rules if only_explicit_rules
17
22
  report_actions if actions
18
23
  end
19
24
 
25
+ # @rbs () -> void
20
26
  def report_rules
21
27
  puts "Grammar rules:"
22
28
  @grammar.rules.each { |rule| puts rule.display_name }
23
29
  end
24
30
 
31
+ # @rbs () -> void
32
+ def report_only_explicit_rules
33
+ puts "Grammar rules:"
34
+ @grammar.rules.each do |rule|
35
+ puts rule.display_name_without_action if rule.lhs.first_set.any?
36
+ end
37
+ end
38
+
39
+ # @rbs () -> void
25
40
  def report_actions
26
41
  puts "Grammar rules with actions:"
27
42
  @grammar.rules.each { |rule| puts rule.with_actions }
data/lib/lrama/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lrama
4
- VERSION = "0.6.11".freeze
4
+ VERSION = "0.7.0".freeze
5
5
  end
data/lrama.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.metadata["homepage_uri"] = spec.homepage
23
23
  spec.metadata["source_code_uri"] = spec.homepage
24
- spec.metadata["documentation_uri"] = spec.homepage
24
+ spec.metadata["documentation_uri"] = "https://ruby.github.io/lrama/"
25
25
  spec.metadata["changelog_uri"] = "#{spec.homepage}/releases"
26
26
  spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
27
27
 
data/parser.y CHANGED
@@ -25,7 +25,7 @@ rule
25
25
 
26
26
  bison_declaration: grammar_declaration
27
27
  | "%expect" INTEGER { @grammar.expect = val[1] }
28
- | "%define" variable value
28
+ | "%define" variable value { @grammar.define[val[1].s_value] = val[2]&.s_value }
29
29
  | "%param" param+
30
30
  | "%lex-param" param+
31
31
  {
@@ -428,17 +428,18 @@ end
428
428
 
429
429
  include Lrama::Report::Duration
430
430
 
431
- def initialize(text, path, debug = false)
431
+ def initialize(text, path, debug = false, define = {})
432
432
  @grammar_file = Lrama::Lexer::GrammarFile.new(path, text)
433
433
  @yydebug = debug
434
434
  @rule_counter = Lrama::Grammar::Counter.new(0)
435
435
  @midrule_action_counter = Lrama::Grammar::Counter.new(1)
436
+ @define = define
436
437
  end
437
438
 
438
439
  def parse
439
440
  report_duration(:parse) do
440
441
  @lexer = Lrama::Lexer.new(@grammar_file)
441
- @grammar = Lrama::Grammar.new(@rule_counter)
442
+ @grammar = Lrama::Grammar.new(@rule_counter, @define)
442
443
  @precedence_number = 0
443
444
  reset_precs
444
445
  do_parse
@@ -6,7 +6,7 @@ gems:
6
6
  source:
7
7
  type: git
8
8
  name: ruby/gem_rbs_collection
9
- revision: 71fb7ae83789ae150bdee1cd8a7cd3035b5d79e2
9
+ revision: 7651e7b92c15bd5b4bc11fd3dd455be0ea571fd0
10
10
  remote: https://github.com/ruby/gem_rbs_collection.git
11
11
  repo_dir: gems
12
12
  - name: erb
@@ -26,7 +26,7 @@ gems:
26
26
  source:
27
27
  type: git
28
28
  name: ruby/gem_rbs_collection
29
- revision: 71fb7ae83789ae150bdee1cd8a7cd3035b5d79e2
29
+ revision: 7651e7b92c15bd5b4bc11fd3dd455be0ea571fd0
30
30
  remote: https://github.com/ruby/gem_rbs_collection.git
31
31
  repo_dir: gems
32
32
  - name: stackprof
@@ -34,7 +34,7 @@ gems:
34
34
  source:
35
35
  type: git
36
36
  name: ruby/gem_rbs_collection
37
- revision: 71fb7ae83789ae150bdee1cd8a7cd3035b5d79e2
37
+ revision: 7651e7b92c15bd5b4bc11fd3dd455be0ea571fd0
38
38
  remote: https://github.com/ruby/gem_rbs_collection.git
39
39
  repo_dir: gems
40
40
  - name: strscan
@@ -0,0 +1,11 @@
1
+ # Generated from lib/lrama/bitmap.rb with RBS::Inline
2
+
3
+ module Lrama
4
+ module Bitmap
5
+ # @rbs (Array[Integer] ary) -> Integer
6
+ def self.from_array: (Array[Integer] ary) -> Integer
7
+
8
+ # @rbs (Integer int) -> Array[Integer]
9
+ def self.to_array: (Integer int) -> Array[Integer]
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ # Generated from lib/lrama/digraph.rb with RBS::Inline
2
+
3
+ module Lrama
4
+ # Algorithm Digraph of https://dl.acm.org/doi/pdf/10.1145/69622.357187 (P. 625)
5
+ #
6
+ # @rbs generic X < Object -- Type of a member of `sets`
7
+ # @rbs generic Y < _Or -- Type of sets assigned to a member of `sets`
8
+ class Digraph[X < Object, Y < _Or]
9
+ interface _Or
10
+ def |: (self) -> self
11
+ end
12
+
13
+ @sets: Array[X]
14
+
15
+ @relation: Hash[X, Array[X]]
16
+
17
+ @base_function: Hash[X, Y]
18
+
19
+ @stack: Array[X]
20
+
21
+ @h: Hash[X, (Integer | Float)?]
22
+
23
+ @result: Hash[X, Y]
24
+
25
+ # @rbs sets: Array[X]
26
+ # @rbs relation: Hash[X, Array[X]]
27
+ # @rbs base_function: Hash[X, Y]
28
+ # @rbs return: void
29
+ def initialize: (Array[X] sets, Hash[X, Array[X]] relation, Hash[X, Y] base_function) -> void
30
+
31
+ # @rbs () -> Hash[X, Y]
32
+ def compute: () -> Hash[X, Y]
33
+
34
+ private
35
+
36
+ # @rbs (X x) -> void
37
+ def traverse: (X x) -> void
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ # Generated from lib/lrama/grammar/binding.rb with RBS::Inline
2
+
3
+ module Lrama
4
+ class Grammar
5
+ class Binding
6
+ @actual_args: Array[Lexer::Token]
7
+
8
+ @param_to_arg: Hash[String, Lexer::Token]
9
+
10
+ # @rbs (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> void
11
+ def initialize: (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> void
12
+
13
+ # @rbs (Lexer::Token sym) -> Lexer::Token
14
+ def resolve_symbol: (Lexer::Token sym) -> Lexer::Token
15
+
16
+ # @rbs (Lexer::Token::InstantiateRule token) -> String
17
+ def concatenated_args_str: (Lexer::Token::InstantiateRule token) -> String
18
+
19
+ private
20
+
21
+ # @rbs (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> Hash[String, Lexer::Token]
22
+ def map_params_to_args: (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> Hash[String, Lexer::Token]
23
+
24
+ # @rbs (Lexer::Token::InstantiateRule sym) -> Array[Lexer::Token]
25
+ def resolved_args: (Lexer::Token::InstantiateRule sym) -> Array[Lexer::Token]
26
+
27
+ # @rbs (Lexer::Token sym) -> Lexer::Token
28
+ def param_to_arg: (Lexer::Token sym) -> Lexer::Token
29
+
30
+ # @rbs (Lexer::Token::InstantiateRule token) -> Array[String]
31
+ def token_to_args_s_values: (Lexer::Token::InstantiateRule token) -> Array[String]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # Generated from lib/lrama/lexer/grammar_file.rb with RBS::Inline
2
+
3
+ module Lrama
4
+ class Lexer
5
+ class GrammarFile
6
+ class Text < String
7
+ # @rbs () -> String
8
+ def inspect: () -> String
9
+ end
10
+
11
+ attr_reader path: String
12
+
13
+ attr_reader text: String
14
+
15
+ # @rbs (String path, String text) -> void
16
+ def initialize: (String path, String text) -> void
17
+
18
+ # @rbs () -> String
19
+ def inspect: () -> String
20
+
21
+ # @rbs (GrammarFile other) -> bool
22
+ def ==: (GrammarFile other) -> bool
23
+
24
+ # @rbs () -> Array[String]
25
+ def lines: () -> Array[String]
26
+ end
27
+ end
28
+ end