lrama 0.6.10 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gh-pages.yml +46 -0
  3. data/.github/workflows/test.yaml +40 -8
  4. data/.gitignore +1 -0
  5. data/.rdoc_options +2 -0
  6. data/Gemfile +4 -2
  7. data/NEWS.md +125 -30
  8. data/README.md +44 -15
  9. data/Rakefile +13 -1
  10. data/Steepfile +5 -0
  11. data/doc/Index.md +58 -0
  12. data/doc/development/compressed_state_table/main.md +635 -0
  13. data/doc/development/compressed_state_table/parse.output +174 -0
  14. data/doc/development/compressed_state_table/parse.y +22 -0
  15. data/doc/development/compressed_state_table/parser.rb +282 -0
  16. data/lib/lrama/bitmap.rb +4 -1
  17. data/lib/lrama/command.rb +2 -1
  18. data/lib/lrama/context.rb +3 -3
  19. data/lib/lrama/counterexamples/derivation.rb +6 -5
  20. data/lib/lrama/counterexamples/example.rb +7 -4
  21. data/lib/lrama/counterexamples/path.rb +4 -0
  22. data/lib/lrama/counterexamples.rb +19 -9
  23. data/lib/lrama/digraph.rb +30 -0
  24. data/lib/lrama/grammar/binding.rb +47 -15
  25. data/lib/lrama/grammar/parameterizing_rule/rhs.rb +1 -1
  26. data/lib/lrama/grammar/rule.rb +8 -0
  27. data/lib/lrama/grammar/rule_builder.rb +4 -16
  28. data/lib/lrama/grammar/symbols/resolver.rb +4 -0
  29. data/lib/lrama/grammar.rb +10 -5
  30. data/lib/lrama/lexer/grammar_file.rb +8 -1
  31. data/lib/lrama/lexer/location.rb +17 -1
  32. data/lib/lrama/lexer/token/char.rb +1 -0
  33. data/lib/lrama/lexer/token/ident.rb +1 -0
  34. data/lib/lrama/lexer/token/instantiate_rule.rb +6 -1
  35. data/lib/lrama/lexer/token/tag.rb +3 -1
  36. data/lib/lrama/lexer/token/user_code.rb +6 -2
  37. data/lib/lrama/lexer/token.rb +14 -2
  38. data/lib/lrama/lexer.rb +5 -5
  39. data/lib/lrama/logger.rb +4 -0
  40. data/lib/lrama/option_parser.rb +10 -8
  41. data/lib/lrama/options.rb +2 -1
  42. data/lib/lrama/parser.rb +529 -490
  43. data/lib/lrama/state/reduce.rb +2 -3
  44. data/lib/lrama/state.rb +288 -1
  45. data/lib/lrama/states/item.rb +8 -0
  46. data/lib/lrama/states.rb +69 -2
  47. data/lib/lrama/trace_reporter.rb +17 -2
  48. data/lib/lrama/version.rb +1 -1
  49. data/lrama.gemspec +1 -1
  50. data/parser.y +42 -30
  51. data/rbs_collection.lock.yaml +10 -2
  52. data/sig/generated/lrama/bitmap.rbs +11 -0
  53. data/sig/generated/lrama/digraph.rbs +39 -0
  54. data/sig/generated/lrama/grammar/binding.rbs +34 -0
  55. data/sig/generated/lrama/lexer/grammar_file.rbs +28 -0
  56. data/sig/generated/lrama/lexer/location.rbs +52 -0
  57. data/sig/{lrama → generated/lrama}/lexer/token/char.rbs +2 -0
  58. data/sig/{lrama → generated/lrama}/lexer/token/ident.rbs +2 -0
  59. data/sig/{lrama → generated/lrama}/lexer/token/instantiate_rule.rbs +8 -0
  60. data/sig/{lrama → generated/lrama}/lexer/token/tag.rbs +3 -0
  61. data/sig/{lrama → generated/lrama}/lexer/token/user_code.rbs +6 -1
  62. data/sig/{lrama → generated/lrama}/lexer/token.rbs +26 -3
  63. data/sig/generated/lrama/logger.rbs +14 -0
  64. data/sig/generated/lrama/trace_reporter.rbs +25 -0
  65. data/sig/lrama/counterexamples/derivation.rbs +33 -0
  66. data/sig/lrama/counterexamples/example.rbs +45 -0
  67. data/sig/lrama/counterexamples/path.rbs +21 -0
  68. data/sig/lrama/counterexamples/production_path.rbs +11 -0
  69. data/sig/lrama/counterexamples/start_path.rbs +13 -0
  70. data/sig/lrama/counterexamples/state_item.rbs +10 -0
  71. data/sig/lrama/counterexamples/transition_path.rbs +11 -0
  72. data/sig/lrama/counterexamples/triple.rbs +20 -0
  73. data/sig/lrama/counterexamples.rbs +29 -0
  74. data/sig/lrama/grammar/rule_builder.rbs +0 -1
  75. data/sig/lrama/grammar/symbol.rbs +1 -1
  76. data/sig/lrama/grammar/symbols/resolver.rbs +3 -3
  77. data/sig/lrama/grammar.rbs +13 -0
  78. data/sig/lrama/options.rbs +1 -0
  79. data/sig/lrama/state/reduce_reduce_conflict.rbs +2 -2
  80. data/sig/lrama/state.rbs +79 -0
  81. data/sig/lrama/states.rbs +101 -0
  82. metadata +34 -14
  83. data/sig/lrama/bitmap.rbs +0 -7
  84. data/sig/lrama/digraph.rbs +0 -23
  85. data/sig/lrama/grammar/binding.rbs +0 -19
  86. data/sig/lrama/lexer/grammar_file.rbs +0 -17
  87. data/sig/lrama/lexer/location.rbs +0 -26
@@ -32,8 +32,10 @@ module Lrama
32
32
  conflict_state.conflicts.flat_map do |conflict|
33
33
  case conflict.type
34
34
  when :shift_reduce
35
+ # @type var conflict: State::ShiftReduceConflict
35
36
  shift_reduce_example(conflict_state, conflict)
36
37
  when :reduce_reduce
38
+ # @type var conflict: State::ReduceReduceConflict
37
39
  reduce_reduce_examples(conflict_state, conflict)
38
40
  end
39
41
  end.compact
@@ -48,7 +50,7 @@ module Lrama
48
50
  @reverse_transitions = {}
49
51
 
50
52
  @states.states.each do |src_state|
51
- trans = {}
53
+ trans = {} #: Hash[Grammar::Symbol, State]
52
54
 
53
55
  src_state.transitions.each do |shift, next_state|
54
56
  trans[shift.next_sym] = next_state
@@ -66,6 +68,7 @@ module Lrama
66
68
 
67
69
  @transitions[[src_state_item, sym]] = dest_state_item
68
70
 
71
+ # @type var key: [StateItem, Grammar::Symbol]
69
72
  key = [dest_state_item, sym]
70
73
  @reverse_transitions[key] ||= Set.new
71
74
  @reverse_transitions[key] << src_state_item
@@ -82,7 +85,7 @@ module Lrama
82
85
 
83
86
  @states.states.each do |state|
84
87
  # LHS => Set(Item)
85
- h = {}
88
+ h = {} #: Hash[Grammar::Symbol, Set[States::Item]]
86
89
 
87
90
  state.closure.each do |item|
88
91
  sym = item.lhs
@@ -97,6 +100,7 @@ module Lrama
97
100
 
98
101
  sym = item.next_sym
99
102
  state_item = StateItem.new(state, item)
103
+ # @type var key: [State, Grammar::Symbol]
100
104
  key = [state, sym]
101
105
 
102
106
  @productions[state_item] = h[sym]
@@ -109,6 +113,7 @@ module Lrama
109
113
 
110
114
  def shift_reduce_example(conflict_state, conflict)
111
115
  conflict_symbol = conflict.symbols.first
116
+ # @type var shift_conflict_item: ::Lrama::States::Item
112
117
  shift_conflict_item = conflict_state.items.find { |item| item.next_sym == conflict_symbol }
113
118
  path2 = shortest_path(conflict_state, conflict.reduce.item, conflict_symbol)
114
119
  path1 = find_shift_conflict_shortest_path(path2, conflict_state, shift_conflict_item)
@@ -153,12 +158,14 @@ module Lrama
153
158
  prev_state_item = prev_path&.to
154
159
 
155
160
  if target_state_item == state_item || target_state_item.item.start_item?
156
- result.concat(reversed_reduce_path[_j..-1].map(&:to))
161
+ result.concat(
162
+ reversed_reduce_path[_j..-1] #: Array[StartPath|TransitionPath|ProductionPath]
163
+ .map(&:to))
157
164
  break
158
165
  end
159
166
 
160
167
  if target_state_item.item.beginning_of_rule?
161
- queue = []
168
+ queue = [] #: Array[Array[StateItem]]
162
169
  queue << [target_state_item]
163
170
 
164
171
  # Find reverse production
@@ -174,15 +181,17 @@ module Lrama
174
181
  end
175
182
 
176
183
  if si.item.beginning_of_rule?
184
+ # @type var key: [State, Grammar::Symbol]
177
185
  key = [si.state, si.item.lhs]
178
186
  @reverse_productions[key].each do |item|
179
187
  state_item = StateItem.new(si.state, item)
180
188
  queue << (sis + [state_item])
181
189
  end
182
190
  else
191
+ # @type var key: [StateItem, Grammar::Symbol]
183
192
  key = [si, si.item.previous_sym]
184
193
  @reverse_transitions[key].each do |prev_target_state_item|
185
- next if prev_target_state_item.state != prev_state_item.state
194
+ next if prev_target_state_item.state != prev_state_item&.state
186
195
  sis.shift
187
196
  result.concat(sis)
188
197
  result << prev_target_state_item
@@ -195,9 +204,10 @@ module Lrama
195
204
  end
196
205
  else
197
206
  # Find reverse transition
207
+ # @type var key: [StateItem, Grammar::Symbol]
198
208
  key = [target_state_item, target_state_item.item.previous_sym]
199
209
  @reverse_transitions[key].each do |prev_target_state_item|
200
- next if prev_target_state_item.state != prev_state_item.state
210
+ next if prev_target_state_item.state != prev_state_item&.state
201
211
  result << prev_target_state_item
202
212
  target_state_item = prev_target_state_item
203
213
  i = j
@@ -224,9 +234,9 @@ module Lrama
224
234
 
225
235
  def shortest_path(conflict_state, conflict_reduce_item, conflict_term)
226
236
  # queue: is an array of [Triple, [Path]]
227
- queue = []
228
- visited = {}
229
- start_state = @states.states.first
237
+ queue = [] #: Array[[Triple, Array[StartPath|TransitionPath|ProductionPath]]]
238
+ visited = {} #: Hash[Triple, true]
239
+ start_state = @states.states.first #: Lrama::State
230
240
  raise "BUG: Start state should be just one kernel." if start_state.kernels.count != 1
231
241
 
232
242
  start = Triple.new(start_state, start_state.kernels.first, Set.new([@states.eof_symbol]))
data/lib/lrama/digraph.rb CHANGED
@@ -1,23 +1,52 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  # Algorithm Digraph of https://dl.acm.org/doi/pdf/10.1145/69622.357187 (P. 625)
6
+ #
7
+ # @rbs generic X < Object -- Type of a member of `sets`
8
+ # @rbs generic Y < _Or -- Type of sets assigned to a member of `sets`
5
9
  class Digraph
10
+ # TODO: rbs-inline 0.10.0 doesn't support instance variables.
11
+ # Move these type declarations above instance variable definitions, once it's supported.
12
+ #
13
+ # @rbs!
14
+ # interface _Or
15
+ # def |: (self) -> self
16
+ # end
17
+ # @sets: Array[X]
18
+ # @relation: Hash[X, Array[X]]
19
+ # @base_function: Hash[X, Y]
20
+ # @stack: Array[X]
21
+ # @h: Hash[X, (Integer|Float)?]
22
+ # @result: Hash[X, Y]
23
+
24
+ # @rbs sets: Array[X]
25
+ # @rbs relation: Hash[X, Array[X]]
26
+ # @rbs base_function: Hash[X, Y]
27
+ # @rbs return: void
6
28
  def initialize(sets, relation, base_function)
29
+
7
30
  # X in the paper
8
31
  @sets = sets
32
+
9
33
  # R in the paper
10
34
  @relation = relation
35
+
11
36
  # F' in the paper
12
37
  @base_function = base_function
38
+
13
39
  # S in the paper
14
40
  @stack = []
41
+
15
42
  # N in the paper
16
43
  @h = Hash.new(0)
44
+
17
45
  # F in the paper
18
46
  @result = {}
19
47
  end
20
48
 
49
+ # @rbs () -> Hash[X, Y]
21
50
  def compute
22
51
  @sets.each do |x|
23
52
  next if @h[x] != 0
@@ -29,6 +58,7 @@ module Lrama
29
58
 
30
59
  private
31
60
 
61
+ # @rbs (X x) -> void
32
62
  def traverse(x)
33
63
  @stack.push(x)
34
64
  d = @stack.count
@@ -1,34 +1,66 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  class Grammar
5
6
  class Binding
6
- attr_reader :actual_args, :count
7
+ # @rbs @actual_args: Array[Lexer::Token]
8
+ # @rbs @param_to_arg: Hash[String, Lexer::Token]
7
9
 
8
- def initialize(parameterizing_rule, actual_args)
9
- @parameters = parameterizing_rule.parameters
10
+ # @rbs (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> void
11
+ def initialize(params, actual_args)
10
12
  @actual_args = actual_args
11
- @parameter_to_arg = @parameters.zip(actual_args).map do |param, arg|
12
- [param.s_value, arg]
13
- end.to_h
13
+ @param_to_arg = map_params_to_args(params, @actual_args)
14
14
  end
15
15
 
16
- def resolve_symbol(symbol)
17
- if symbol.is_a?(Lexer::Token::InstantiateRule)
18
- resolved_args = symbol.args.map { |arg| resolve_symbol(arg) }
19
- Lrama::Lexer::Token::InstantiateRule.new(s_value: symbol.s_value, location: symbol.location, args: resolved_args, lhs_tag: symbol.lhs_tag)
16
+ # @rbs (Lexer::Token sym) -> Lexer::Token
17
+ def resolve_symbol(sym)
18
+ if sym.is_a?(Lexer::Token::InstantiateRule)
19
+ Lrama::Lexer::Token::InstantiateRule.new(
20
+ s_value: sym.s_value, location: sym.location, args: resolved_args(sym), lhs_tag: sym.lhs_tag
21
+ )
20
22
  else
21
- parameter_to_arg(symbol) || symbol
23
+ param_to_arg(sym)
22
24
  end
23
25
  end
24
26
 
27
+ # @rbs (Lexer::Token::InstantiateRule token) -> String
28
+ def concatenated_args_str(token)
29
+ "#{token.rule_name}_#{token_to_args_s_values(token).join('_')}"
30
+ end
31
+
25
32
  private
26
33
 
27
- def parameter_to_arg(symbol)
28
- if (arg = @parameter_to_arg[symbol.s_value].dup)
29
- arg.alias_name = symbol.alias_name
34
+ # @rbs (Array[Lexer::Token] params, Array[Lexer::Token] actual_args) -> Hash[String, Lexer::Token]
35
+ def map_params_to_args(params, actual_args)
36
+ params.zip(actual_args).map do |param, arg|
37
+ [param.s_value, arg]
38
+ end.to_h
39
+ end
40
+
41
+ # @rbs (Lexer::Token::InstantiateRule sym) -> Array[Lexer::Token]
42
+ def resolved_args(sym)
43
+ sym.args.map { |arg| resolve_symbol(arg) }
44
+ end
45
+
46
+ # @rbs (Lexer::Token sym) -> Lexer::Token
47
+ def param_to_arg(sym)
48
+ if (arg = @param_to_arg[sym.s_value].dup)
49
+ arg.alias_name = sym.alias_name
50
+ end
51
+ arg || sym
52
+ end
53
+
54
+ # @rbs (Lexer::Token::InstantiateRule token) -> Array[String]
55
+ def token_to_args_s_values(token)
56
+ token.args.flat_map do |arg|
57
+ resolved = resolve_symbol(arg)
58
+ if resolved.is_a?(Lexer::Token::InstantiateRule)
59
+ [resolved.s_value] + resolved.args.map(&:s_value)
60
+ else
61
+ [resolved.s_value]
62
+ end
30
63
  end
31
- arg
32
64
  end
33
65
  end
34
66
  end
@@ -16,7 +16,7 @@ module Lrama
16
16
  return unless user_code
17
17
 
18
18
  resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
19
- var_to_arg = {}
19
+ var_to_arg = {} #: Hash[String, String]
20
20
  symbols.each do |sym|
21
21
  resolved_sym = bindings.resolve_symbol(sym)
22
22
  if resolved_sym != sym
@@ -21,6 +21,14 @@ module Lrama
21
21
  def display_name
22
22
  l = lhs.id.s_value
23
23
  r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(" ")
24
+ "#{l} -> #{r}"
25
+ end
26
+
27
+ def display_name_without_action
28
+ l = lhs.id.s_value
29
+ r = empty_rule? ? "ε" : rhs.map do |r|
30
+ r.id.s_value if r.first_set.any?
31
+ end.compact.join(" ")
24
32
 
25
33
  "#{l} -> #{r}"
26
34
  end
@@ -67,13 +67,13 @@ module Lrama
67
67
  end
68
68
 
69
69
  def resolve_inline_rules
70
- resolved_builders = []
70
+ resolved_builders = [] #: Array[RuleBuilder]
71
71
  rhs.each_with_index do |token, i|
72
72
  if (inline_rule = @parameterizing_rule_resolver.find_inline(token))
73
73
  inline_rule.rhs_list.each do |inline_rhs|
74
74
  rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: lhs_tag)
75
75
  if token.is_a?(Lexer::Token::InstantiateRule)
76
- resolve_inline_rhs(rule_builder, inline_rhs, i, Binding.new(inline_rule, token.args))
76
+ resolve_inline_rhs(rule_builder, inline_rhs, i, Binding.new(inline_rule.parameters, token.args))
77
77
  else
78
78
  resolve_inline_rhs(rule_builder, inline_rhs, i)
79
79
  end
@@ -135,8 +135,8 @@ module Lrama
135
135
  parameterizing_rule = @parameterizing_rule_resolver.find_rule(token)
136
136
  raise "Unexpected token. #{token}" unless parameterizing_rule
137
137
 
138
- bindings = Binding.new(parameterizing_rule, token.args)
139
- lhs_s_value = lhs_s_value(token, bindings)
138
+ bindings = Binding.new(parameterizing_rule.parameters, token.args)
139
+ lhs_s_value = bindings.concatenated_args_str(token)
140
140
  if (created_lhs = @parameterizing_rule_resolver.created_lhs(lhs_s_value))
141
141
  @replaced_rhs << created_lhs
142
142
  else
@@ -174,18 +174,6 @@ module Lrama
174
174
  end
175
175
  end
176
176
 
177
- def lhs_s_value(token, bindings)
178
- s_values = token.args.map do |arg|
179
- resolved = bindings.resolve_symbol(arg)
180
- if resolved.is_a?(Lexer::Token::InstantiateRule)
181
- [resolved.s_value, resolved.args.map(&:s_value)]
182
- else
183
- resolved.s_value
184
- end
185
- end
186
- "#{token.rule_name}_#{s_values.join('_')}"
187
- end
188
-
189
177
  def resolve_inline_rhs(rule_builder, inline_rhs, index, bindings = nil)
190
178
  rhs.each_with_index do |token, i|
191
179
  if index == i
@@ -57,6 +57,10 @@ module Lrama
57
57
  nterm
58
58
  end
59
59
 
60
+ def find_term_by_s_value(s_value)
61
+ terms.find { |s| s.id.s_value == s_value }
62
+ end
63
+
60
64
  def find_symbol_by_s_value(s_value)
61
65
  symbols.find { |s| s.id.s_value == s_value }
62
66
  end
data/lib/lrama/grammar.rb CHANGED
@@ -28,14 +28,14 @@ module Lrama
28
28
  attr_reader :percent_codes, :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol, :aux, :parameterizing_rule_resolver
29
29
  attr_accessor :union, :expect, :printers, :error_tokens, :lex_param, :parse_param, :initial_action,
30
30
  :after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack,
31
- :symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib, :locations
31
+ :symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib, :locations, :define
32
32
 
33
- def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
33
+ def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term, :find_term_by_s_value,
34
34
  :find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
35
35
  :find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
36
36
  :fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!
37
37
 
38
- def initialize(rule_counter)
38
+ def initialize(rule_counter, define = {})
39
39
  @rule_counter = rule_counter
40
40
 
41
41
  # Code defined by "%code"
@@ -57,6 +57,7 @@ module Lrama
57
57
  @aux = Auxiliary.new
58
58
  @no_stdlib = false
59
59
  @locations = false
60
+ @define = define.map {|d| d.split('=') }.to_h
60
61
 
61
62
  append_special_symbols
62
63
  end
@@ -171,6 +172,10 @@ module Lrama
171
172
  @sym_to_rules[sym.number]
172
173
  end
173
174
 
175
+ def ielr_defined?
176
+ @define.key?('lr.type') && @define['lr.type'] == 'ielr'
177
+ end
178
+
174
179
  private
175
180
 
176
181
  def compute_nullable
@@ -294,7 +299,7 @@ module Lrama
294
299
  end
295
300
 
296
301
  def resolve_inline_rules
297
- while @rule_builders.any? {|r| r.has_inline_rules? } do
302
+ while @rule_builders.any?(&:has_inline_rules?) do
298
303
  @rule_builders = @rule_builders.flat_map do |builder|
299
304
  if builder.has_inline_rules?
300
305
  builder.resolve_inline_rules
@@ -382,7 +387,7 @@ module Lrama
382
387
  end
383
388
 
384
389
  def validate_rule_lhs_is_nterm!
385
- errors = []
390
+ errors = [] #: Array[String]
386
391
 
387
392
  rules.each do |rule|
388
393
  next if rule.lhs.nterm?
@@ -1,30 +1,37 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  class Lexer
5
6
  class GrammarFile
6
7
  class Text < String
8
+ # @rbs () -> String
7
9
  def inspect
8
10
  length <= 50 ? super : "#{self[0..47]}...".inspect
9
11
  end
10
12
  end
11
13
 
12
- attr_reader :path, :text
14
+ attr_reader :path #: String
15
+ attr_reader :text #: String
13
16
 
17
+ # @rbs (String path, String text) -> void
14
18
  def initialize(path, text)
15
19
  @path = path
16
20
  @text = Text.new(text).freeze
17
21
  end
18
22
 
23
+ # @rbs () -> String
19
24
  def inspect
20
25
  "<#{self.class}: @path=#{path}, @text=#{text.inspect}>"
21
26
  end
22
27
 
28
+ # @rbs (GrammarFile other) -> bool
23
29
  def ==(other)
24
30
  self.class == other.class &&
25
31
  self.path == other.path
26
32
  end
27
33
 
34
+ # @rbs () -> Array[String]
28
35
  def lines
29
36
  @lines ||= text.split("\n")
30
37
  end
@@ -1,10 +1,16 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  class Lexer
5
6
  class Location
6
- attr_reader :grammar_file, :first_line, :first_column, :last_line, :last_column
7
+ attr_reader :grammar_file #: GrammarFile
8
+ attr_reader :first_line #: Integer
9
+ attr_reader :first_column #: Integer
10
+ attr_reader :last_line #: Integer
11
+ attr_reader :last_column #: Integer
7
12
 
13
+ # @rbs (grammar_file: GrammarFile, first_line: Integer, first_column: Integer, last_line: Integer, last_column: Integer) -> void
8
14
  def initialize(grammar_file:, first_line:, first_column:, last_line:, last_column:)
9
15
  @grammar_file = grammar_file
10
16
  @first_line = first_line
@@ -13,6 +19,7 @@ module Lrama
13
19
  @last_column = last_column
14
20
  end
15
21
 
22
+ # @rbs (Location other) -> bool
16
23
  def ==(other)
17
24
  self.class == other.class &&
18
25
  self.grammar_file == other.grammar_file &&
@@ -22,6 +29,7 @@ module Lrama
22
29
  self.last_column == other.last_column
23
30
  end
24
31
 
32
+ # @rbs (Integer left, Integer right) -> Location
25
33
  def partial_location(left, right)
26
34
  offset = -first_column
27
35
  new_first_line = -1
@@ -52,10 +60,12 @@ module Lrama
52
60
  )
53
61
  end
54
62
 
63
+ # @rbs () -> String
55
64
  def to_s
56
65
  "#{path} (#{first_line},#{first_column})-(#{last_line},#{last_column})"
57
66
  end
58
67
 
68
+ # @rbs (String error_message) -> String
59
69
  def generate_error_message(error_message)
60
70
  <<~ERROR.chomp
61
71
  #{path}:#{first_line}:#{first_column}: #{error_message}
@@ -63,6 +73,7 @@ module Lrama
63
73
  ERROR
64
74
  end
65
75
 
76
+ # @rbs () -> String
66
77
  def line_with_carets
67
78
  <<~TEXT
68
79
  #{text}
@@ -72,22 +83,27 @@ module Lrama
72
83
 
73
84
  private
74
85
 
86
+ # @rbs () -> String
75
87
  def path
76
88
  grammar_file.path
77
89
  end
78
90
 
91
+ # @rbs () -> String
79
92
  def blanks
80
93
  (text[0...first_column] or raise "#{first_column} is invalid").gsub(/[^\t]/, ' ')
81
94
  end
82
95
 
96
+ # @rbs () -> String
83
97
  def carets
84
98
  blanks + '^' * (last_column - first_column)
85
99
  end
86
100
 
101
+ # @rbs () -> String
87
102
  def text
88
103
  @text ||= _text.join("\n")
89
104
  end
90
105
 
106
+ # @rbs () -> Array[String]
91
107
  def _text
92
108
  @_text ||=begin
93
109
  range = (first_line - 1)...last_line
@@ -1,3 +1,4 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
@@ -1,3 +1,4 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
@@ -1,21 +1,26 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  class Lexer
5
6
  class Token
6
7
  class InstantiateRule < Token
7
- attr_reader :args, :lhs_tag
8
+ attr_reader :args #: Array[Lexer::Token]
9
+ attr_reader :lhs_tag #: Lexer::Token::Tag?
8
10
 
11
+ # @rbs (s_value: String, ?alias_name: String, ?location: Location, ?args: Array[Lexer::Token], ?lhs_tag: Lexer::Token::Tag?) -> void
9
12
  def initialize(s_value:, alias_name: nil, location: nil, args: [], lhs_tag: nil)
10
13
  super s_value: s_value, alias_name: alias_name, location: location
11
14
  @args = args
12
15
  @lhs_tag = lhs_tag
13
16
  end
14
17
 
18
+ # @rbs () -> String
15
19
  def rule_name
16
20
  s_value
17
21
  end
18
22
 
23
+ # @rbs () -> Integer
19
24
  def args_count
20
25
  args.count
21
26
  end
@@ -1,11 +1,13 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Lrama
4
5
  class Lexer
5
6
  class Token
6
7
  class Tag < Token
7
- # Omit "<>"
8
+ # @rbs () -> String
8
9
  def member
10
+ # Omit "<>"
9
11
  s_value[1..-2] or raise "Unexpected Tag format (#{s_value})"
10
12
  end
11
13
  end
@@ -1,3 +1,4 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "strscan"
@@ -6,17 +7,19 @@ module Lrama
6
7
  class Lexer
7
8
  class Token
8
9
  class UserCode < Token
9
- attr_accessor :tag
10
+ attr_accessor :tag #: Lexer::Token::Tag
10
11
 
12
+ # @rbs () -> Array[Lrama::Grammar::Reference]
11
13
  def references
12
14
  @references ||= _references
13
15
  end
14
16
 
15
17
  private
16
18
 
19
+ # @rbs () -> Array[Lrama::Grammar::Reference]
17
20
  def _references
18
21
  scanner = StringScanner.new(s_value)
19
- references = []
22
+ references = [] #: Array[Grammar::Reference]
20
23
 
21
24
  until scanner.eos? do
22
25
  case
@@ -32,6 +35,7 @@ module Lrama
32
35
  references
33
36
  end
34
37
 
38
+ # @rbs (StringScanner scanner) -> Lrama::Grammar::Reference?
35
39
  def scan_reference(scanner)
36
40
  start = scanner.pos
37
41
  case
@@ -1,3 +1,4 @@
1
+ # rbs_inline: enabled
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative 'token/char'
@@ -9,9 +10,12 @@ require_relative 'token/user_code'
9
10
  module Lrama
10
11
  class Lexer
11
12
  class Token
12
- attr_reader :s_value, :location
13
- attr_accessor :alias_name, :referred
13
+ attr_reader :s_value #: String
14
+ attr_reader :location #: Location
15
+ attr_accessor :alias_name #: String
16
+ attr_accessor :referred #: bool
14
17
 
18
+ # @rbs (s_value: String, ?alias_name: String, ?location: Location) -> void
15
19
  def initialize(s_value:, alias_name: nil, location: nil)
16
20
  s_value.freeze
17
21
  @s_value = s_value
@@ -19,36 +23,44 @@ module Lrama
19
23
  @location = location
20
24
  end
21
25
 
26
+ # @rbs () -> String
22
27
  def to_s
23
28
  "value: `#{s_value}`, location: #{location}"
24
29
  end
25
30
 
31
+ # @rbs (String string) -> bool
26
32
  def referred_by?(string)
27
33
  [self.s_value, self.alias_name].compact.include?(string)
28
34
  end
29
35
 
36
+ # @rbs (Token other) -> bool
30
37
  def ==(other)
31
38
  self.class == other.class && self.s_value == other.s_value
32
39
  end
33
40
 
41
+ # @rbs () -> Integer
34
42
  def first_line
35
43
  location.first_line
36
44
  end
37
45
  alias :line :first_line
38
46
 
47
+ # @rbs () -> Integer
39
48
  def first_column
40
49
  location.first_column
41
50
  end
42
51
  alias :column :first_column
43
52
 
53
+ # @rbs () -> Integer
44
54
  def last_line
45
55
  location.last_line
46
56
  end
47
57
 
58
+ # @rbs () -> Integer
48
59
  def last_column
49
60
  location.last_column
50
61
  end
51
62
 
63
+ # @rbs (Lrama::Grammar::Reference ref, String message) -> bot
52
64
  def invalid_ref(ref, message)
53
65
  location = self.location.partial_location(ref.first_column, ref.last_column)
54
66
  raise location.generate_error_message(message)