parsanol 1.3.5 → 1.3.7

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +48 -48
  3. data/ext/parsanol_native/extconf.rb +4 -4
  4. data/lib/parsanol/ast_visitor.rb +1 -1
  5. data/lib/parsanol/atoms/alternative.rb +3 -2
  6. data/lib/parsanol/atoms/base.rb +12 -6
  7. data/lib/parsanol/atoms/can_flatten.rb +8 -8
  8. data/lib/parsanol/atoms/context.rb +23 -16
  9. data/lib/parsanol/atoms/custom.rb +2 -2
  10. data/lib/parsanol/atoms/dynamic.rb +1 -1
  11. data/lib/parsanol/atoms/infix.rb +10 -5
  12. data/lib/parsanol/atoms/lookahead.rb +7 -4
  13. data/lib/parsanol/atoms/re.rb +1 -1
  14. data/lib/parsanol/atoms/repetition.rb +29 -11
  15. data/lib/parsanol/atoms/sequence.rb +3 -2
  16. data/lib/parsanol/atoms/str.rb +9 -3
  17. data/lib/parsanol/atoms.rb +20 -20
  18. data/lib/parsanol/builder_callbacks.rb +2 -2
  19. data/lib/parsanol/cause.rb +2 -2
  20. data/lib/parsanol/context.rb +2 -2
  21. data/lib/parsanol/error_reporter.rb +5 -5
  22. data/lib/parsanol/expression/treetop.rb +17 -17
  23. data/lib/parsanol/expression.rb +1 -1
  24. data/lib/parsanol/fast_mode.rb +50 -12
  25. data/lib/parsanol/first_set.rb +1 -1
  26. data/lib/parsanol/grammar_builder.rb +10 -8
  27. data/lib/parsanol/incremental_parser.rb +13 -8
  28. data/lib/parsanol/interval_tree.rb +12 -3
  29. data/lib/parsanol/lazy_result.rb +2 -2
  30. data/lib/parsanol/mermaid.rb +12 -9
  31. data/lib/parsanol/native/batch_decoder.rb +13 -9
  32. data/lib/parsanol/native/dynamic.rb +7 -6
  33. data/lib/parsanol/native/parser.rb +7 -5
  34. data/lib/parsanol/native/serializer.rb +42 -42
  35. data/lib/parsanol/native/transformer.rb +55 -28
  36. data/lib/parsanol/native/types.rb +3 -3
  37. data/lib/parsanol/native.rb +26 -20
  38. data/lib/parsanol/optimizer.rb +6 -6
  39. data/lib/parsanol/optimizers/choice_optimizer.rb +1 -1
  40. data/lib/parsanol/optimizers/cut_inserter.rb +5 -2
  41. data/lib/parsanol/optimizers/lookahead_optimizer.rb +9 -3
  42. data/lib/parsanol/optimizers/quantifier_optimizer.rb +5 -5
  43. data/lib/parsanol/optimizers/sequence_optimizer.rb +1 -1
  44. data/lib/parsanol/options/zero_copy.rb +1 -1
  45. data/lib/parsanol/options.rb +1 -1
  46. data/lib/parsanol/parallel.rb +4 -3
  47. data/lib/parsanol/parser.rb +18 -16
  48. data/lib/parsanol/parslet.rb +7 -7
  49. data/lib/parsanol/pattern/binding.rb +1 -1
  50. data/lib/parsanol/pattern.rb +4 -1
  51. data/lib/parsanol/pool.rb +3 -3
  52. data/lib/parsanol/pools/buffer_pool.rb +2 -2
  53. data/lib/parsanol/pools/position_pool.rb +2 -2
  54. data/lib/parsanol/position.rb +1 -1
  55. data/lib/parsanol/result_builder.rb +4 -4
  56. data/lib/parsanol/result_stream.rb +10 -5
  57. data/lib/parsanol/slice.rb +11 -8
  58. data/lib/parsanol/source.rb +14 -9
  59. data/lib/parsanol/source_location.rb +1 -1
  60. data/lib/parsanol/streaming_parser.rb +3 -3
  61. data/lib/parsanol/string_view.rb +4 -1
  62. data/lib/parsanol/transform.rb +2 -2
  63. data/lib/parsanol/version.rb +1 -1
  64. data/lib/parsanol/wasm_parser.rb +1 -1
  65. data/lib/parsanol.rb +37 -39
  66. data/parsanol.gemspec +30 -30
  67. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7dcef7aebbd4f89f81ed82f1f162e4f168e8cc824150b610e434e3cd709219a1
4
- data.tar.gz: 71f39107f54e66fa5c6fa58dc23a7bfa2287212454caa446c2a7444d506d6a7e
3
+ metadata.gz: 39ce7a8554166a92125c5336c0f7e7f3c9011791cd0c366c037f74d6d9b73a6e
4
+ data.tar.gz: b33ecab1a711628c5fc4135705a5d21e7af53e48b5472fb60925664e15ce9688
5
5
  SHA512:
6
- metadata.gz: 398f9bdc287b03f8114568fd061299434bd479556f7163145f7269a18507be521f30f582ad02881d88c5479d794e4dea68c2a5e02b36093e33d9f1efa6130c3c
7
- data.tar.gz: 1460303b64cb6ae52a04db7b26a9e156895d2acaed5f7634eefe2c530a8662815b03ff4b8fe77c6cb8481c0c4fa8452565228c4428346c6f3ffd4804239a5eb1
6
+ metadata.gz: da8b989aba1451e3bcbe5a922eef7a481614e098a5e1095a5f9a8d8d6f6d8ac46fbcf7e6fe727fc06c40753d80df1fb2731d54bdf66f96d5441aaf284eb6d2bd
7
+ data.tar.gz: bbab802f416f69dfb61bd856549a3755b87923fb0944d9fcc06b96466ebe8cad8ac51515086b5bd40b7eb04bc3c8f813a7f6c109a9931952fc9d70c21f0304d8
data/Rakefile CHANGED
@@ -1,53 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/gem_tasks'
3
+ require "bundler/gem_tasks"
4
4
 
5
5
  begin
6
- require 'rspec/core/rake_task'
6
+ require "rspec/core/rake_task"
7
7
  rescue LoadError
8
8
  # RSpec not available in this environment
9
9
  end
10
10
 
11
- require 'rdoc/task'
12
- require 'rubygems/package_task'
11
+ require "rdoc/task"
12
+ require "rubygems/package_task"
13
13
 
14
14
  begin
15
- require 'opal/rspec/rake_task'
15
+ require "opal/rspec/rake_task"
16
16
  rescue LoadError, NoMethodError
17
17
  # Opal not available or incompatible with current Ruby version
18
18
  end
19
19
 
20
- GEMSPEC = Gem::Specification.load('parsanol.gemspec')
20
+ GEMSPEC = Gem::Specification.load("parsanol.gemspec")
21
21
 
22
22
  # Load rake tasks from rakelib/
23
- Dir.glob('rakelib/*.rake').each { |r| load r }
23
+ Dir.glob("rakelib/*.rake").each { |r| load r }
24
24
 
25
- desc 'Run all tests'
25
+ desc "Run all tests"
26
26
  RSpec::Core::RakeTask.new(:spec)
27
27
 
28
28
  namespace :spec do
29
- desc 'Run unit tests only'
29
+ desc "Run unit tests only"
30
30
  RSpec::Core::RakeTask.new(:unit) do |task|
31
- task.pattern = 'spec/parsanol/**/*_spec.rb'
31
+ task.pattern = "spec/parsanol/**/*_spec.rb"
32
32
  end
33
33
 
34
34
  if defined?(Opal::RSpec::RakeTask)
35
- desc 'Run Opal (JavaScript) tests'
35
+ desc "Run Opal (JavaScript) tests"
36
36
  Opal::RSpec::RakeTask.new(:opal) do |task|
37
- task.append_path 'lib'
37
+ task.append_path "lib"
38
38
  end
39
39
  end
40
40
  end
41
41
 
42
42
  RDoc::Task.new do |rdoc|
43
- rdoc.rdoc_dir = 'rdoc'
44
- rdoc.title = 'Parsanol'
45
- rdoc.options << '--line-numbers'
46
- rdoc.rdoc_files.include('README.adoc')
47
- rdoc.rdoc_files.include('lib/**/*.rb')
43
+ rdoc.rdoc_dir = "rdoc"
44
+ rdoc.title = "Parsanol"
45
+ rdoc.options << "--line-numbers"
46
+ rdoc.rdoc_files.include("README.adoc")
47
+ rdoc.rdoc_files.include("lib/**/*.rb")
48
48
  end
49
49
 
50
- desc 'Print LOC statistics'
50
+ desc "Print LOC statistics"
51
51
  task :stat do
52
52
  %w[lib spec example].each do |dir|
53
53
  next unless Dir.exist?(dir)
@@ -59,82 +59,82 @@ end
59
59
 
60
60
  # ===== Native Gem Building =====
61
61
  namespace :gem do
62
- desc 'Build source gem (compile on install)'
63
- task 'native:any' do
64
- sh 'rake gem:platform:any gem'
62
+ desc "Build source gem (compile on install)"
63
+ task "native:any" do
64
+ sh "rake gem:platform:any gem"
65
65
  end
66
66
 
67
- desc 'Define the gem task to build on any platform (compile on install)'
68
- task 'platform:any' do
69
- spec = Gem::Specification.load('parsanol.gemspec').dup
67
+ desc "Define the gem task to build on any platform (compile on install)"
68
+ task "platform:any" do
69
+ spec = Gem::Specification.load("parsanol.gemspec").dup
70
70
  task = Gem::PackageTask.new(spec)
71
71
  task.define
72
72
  end
73
73
  end
74
74
 
75
75
  namespace :benchmark do
76
- desc 'Run comprehensive benchmark suite'
76
+ desc "Run comprehensive benchmark suite"
77
77
  task :all do
78
- ruby 'benchmark/benchmark_suite.rb'
78
+ ruby "benchmark/benchmark_suite.rb"
79
79
  end
80
80
 
81
- desc 'Run example-focused benchmarks'
81
+ desc "Run example-focused benchmarks"
82
82
  task :examples do
83
- ruby 'benchmark/example_benchmarks.rb'
83
+ ruby "benchmark/example_benchmarks.rb"
84
84
  end
85
85
 
86
- desc 'Run benchmarks and export results to JSON/YAML'
86
+ desc "Run benchmarks and export results to JSON/YAML"
87
87
  task :export do
88
- ruby 'benchmark/benchmark_runner.rb'
88
+ ruby "benchmark/benchmark_runner.rb"
89
89
  end
90
90
 
91
- desc 'Run quick benchmark (examples only)'
91
+ desc "Run quick benchmark (examples only)"
92
92
  task quick: :examples
93
93
  end
94
94
 
95
95
  # Load comparative benchmark tasks
96
- Dir.glob('benchmark/tasks/*.rake').each { |r| load r }
96
+ Dir.glob("benchmark/tasks/*.rake").each { |r| load r }
97
97
 
98
- desc 'Run quick benchmarks'
99
- task benchmark: 'benchmark:quick'
98
+ desc "Run quick benchmarks"
99
+ task benchmark: "benchmark:quick"
100
100
 
101
101
  # ===== Parslet Compatibility Tests =====
102
102
  namespace :compat do
103
- desc 'Run imported Parslet tests with original Parslet (baseline)'
103
+ desc "Run imported Parslet tests with original Parslet (baseline)"
104
104
  task :parslet do
105
- ENV['PARSANOL_BACKEND'] = 'parslet'
106
- sh 'bundle exec rspec spec/parslet_imported/ --format documentation'
105
+ ENV["PARSANOL_BACKEND"] = "parslet"
106
+ sh "bundle exec rspec spec/parslet_imported/ --format documentation"
107
107
  end
108
108
 
109
- desc 'Run imported Parslet tests with Parsanol compatibility layer'
109
+ desc "Run imported Parslet tests with Parsanol compatibility layer"
110
110
  task :parsanol do
111
- ENV['PARSANOL_BACKEND'] = 'parsanol'
112
- sh 'bundle exec rspec spec/parslet_imported/ --format documentation'
111
+ ENV["PARSANOL_BACKEND"] = "parsanol"
112
+ sh "bundle exec rspec spec/parslet_imported/ --format documentation"
113
113
  end
114
114
 
115
- desc 'Run both and save results for comparison'
115
+ desc "Run both and save results for comparison"
116
116
  task :compare do
117
- require 'fileutils'
117
+ require "fileutils"
118
118
 
119
- results_dir = 'tmp/compat_results'
119
+ results_dir = "tmp/compat_results"
120
120
  FileUtils.mkdir_p(results_dir)
121
121
 
122
- puts '=== Running with original Parslet ==='
123
- ENV['PARSANOL_BACKEND'] = 'parslet'
122
+ puts "=== Running with original Parslet ==="
123
+ ENV["PARSANOL_BACKEND"] = "parslet"
124
124
  sh "bundle exec rspec spec/parslet_imported/ --format documentation > #{results_dir}/parslet.txt 2>&1"
125
125
 
126
126
  puts "\n=== Running with Parsanol::Parslet ==="
127
- ENV['PARSANOL_BACKEND'] = 'parsanol'
127
+ ENV["PARSANOL_BACKEND"] = "parsanol"
128
128
  sh "bundle exec rspec spec/parslet_imported/ --format documentation > #{results_dir}/parsanol.txt 2>&1"
129
129
 
130
130
  puts "\n=== Comparing results ==="
131
- puts 'Results saved to:'
131
+ puts "Results saved to:"
132
132
  puts " - #{results_dir}/parslet.txt"
133
133
  puts " - #{results_dir}/parsanol.txt"
134
134
  puts "\nTo compare: diff #{results_dir}/parslet.txt #{results_dir}/parsanol.txt"
135
135
  end
136
136
 
137
- desc 'Run imported Parslet tests (default: with Parsanol)'
137
+ desc "Run imported Parslet tests (default: with Parsanol)"
138
138
  task run: :parsanol
139
139
  end
140
140
 
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mkmf'
4
- require 'rb_sys/mkmf'
3
+ require "mkmf"
4
+ require "rb_sys/mkmf"
5
5
 
6
- create_rust_makefile('parsanol/parsanol_native') do |r|
6
+ create_rust_makefile("parsanol/parsanol_native") do |r|
7
7
  # Create debug builds in dev, release in production
8
- r.profile = ENV.fetch('RB_SYS_CARGO_PROFILE', :dev).to_sym
8
+ r.profile = ENV.fetch("RB_SYS_CARGO_PROFILE", :dev).to_sym
9
9
 
10
10
  # Enable stable API compiled fallback for ruby-head and older Ruby versions
11
11
  r.use_stable_api_compiled_fallback = true
@@ -72,7 +72,7 @@ module Parsanol
72
72
  new_parslet,
73
73
  parslet.min,
74
74
  parslet.max,
75
- parslet.instance_variable_get(:@tag)
75
+ parslet.instance_variable_get(:@tag),
76
76
  )
77
77
  end
78
78
  end
@@ -51,7 +51,8 @@ module Parsanol
51
51
  when 2
52
52
  try_two(options[0], options[1], source, context, consume_all)
53
53
  when 3
54
- try_three(options[0], options[1], options[2], source, context, consume_all)
54
+ try_three(options[0], options[1], options[2], source, context,
55
+ consume_all)
55
56
  else
56
57
  try_many(options, source, context, consume_all)
57
58
  end
@@ -64,7 +65,7 @@ module Parsanol
64
65
  # @param prec [Integer] precedence
65
66
  # @return [String]
66
67
  def to_s_inner(prec)
67
- @alternatives.map { |a| a.to_s(prec) }.join(' / ')
68
+ @alternatives.map { |a| a.to_s(prec) }.join(" / ")
68
69
  end
69
70
 
70
71
  # FIRST set is union of all alternatives' FIRST sets.
@@ -38,7 +38,8 @@ module Parsanol
38
38
  return finalize_result(value) if success
39
39
 
40
40
  # Reparse with error reporting for diagnostics
41
- report_detailed_error(input, must_consume_all, options[:reporter], value)
41
+ report_detailed_error(input, must_consume_all, options[:reporter],
42
+ value)
42
43
  end
43
44
 
44
45
  # Creates a new parsing context and executes the atom.
@@ -49,7 +50,8 @@ module Parsanol
49
50
  # @return [Array(Boolean, Object)] outcome tuple
50
51
  def run_with_context(input, reporter, consume_all)
51
52
  parser_class = detect_parser_class
52
- context = Parsanol::Atoms::Context.new(reporter, parser_class: parser_class)
53
+ context = Parsanol::Atoms::Context.new(reporter,
54
+ parser_class: parser_class)
53
55
  apply(input, context, consume_all)
54
56
  end
55
57
 
@@ -69,7 +71,10 @@ module Parsanol
69
71
  context.succ(input)
70
72
 
71
73
  # Verify full consumption when required
72
- return unconsumed_error(input, context, position_before) if consume_all && input.chars_left.positive?
74
+ if consume_all && input.chars_left.positive?
75
+ return unconsumed_error(input, context,
76
+ position_before)
77
+ end
73
78
 
74
79
  outcome
75
80
  end
@@ -83,7 +88,7 @@ module Parsanol
83
88
  # @raise [NotImplementedError] if not overridden
84
89
  def try(input, context, consume_all)
85
90
  raise NotImplementedError,
86
- 'Atom must implement #try(source, context, consume_all)'
91
+ "Atom must implement #try(source, context, consume_all)"
87
92
  end
88
93
 
89
94
  # Whether packrat caching benefits this atom.
@@ -178,7 +183,8 @@ module Parsanol
178
183
  excess_pos = input.bytepos
179
184
  preview = input.consume(10)
180
185
  input.bytepos = saved_pos
181
- context.err_at(self, input, UNCONSUMED_INPUT_MSG + preview.to_s.inspect, excess_pos)
186
+ context.err_at(self, input,
187
+ UNCONSUMED_INPUT_MSG + preview.to_s.inspect, excess_pos)
182
188
  end
183
189
 
184
190
  # Reports detailed error by reparsing with reporter.
@@ -188,7 +194,7 @@ module Parsanol
188
194
  success, cause = run_with_context(input, error_reporter, consume_all)
189
195
 
190
196
  # Second parse should also fail
191
- raise 'Invariant violation: parse succeeded during error reporting' if success
197
+ raise "Invariant violation: parse succeeded during error reporting" if success
192
198
 
193
199
  cause.raise
194
200
  end
@@ -39,7 +39,7 @@ module Parsanol
39
39
  when :sequence
40
40
  return flattened
41
41
  when :maybe
42
- return named ? flattened : (flattened || '')
42
+ return named ? flattened : (flattened || "")
43
43
  when :repetition
44
44
  return flatten_repetition([flattened], named)
45
45
  end
@@ -57,7 +57,7 @@ module Parsanol
57
57
  when :sequence
58
58
  return flatten_sequence(result)
59
59
  when :maybe
60
- return named ? result.first : result.first || ''
60
+ return named ? result.first : result.first || ""
61
61
  when :repetition
62
62
  return flatten_repetition(result, named)
63
63
  end
@@ -68,15 +68,15 @@ module Parsanol
68
68
  # Lisp style fold left where the first element builds the basis for
69
69
  # an inject. Optimized with early return and reduced method calls.
70
70
  #
71
- def foldl(list, &block)
71
+ def foldl(list)
72
72
  len = list.size
73
- return '' if len.zero?
73
+ return "" if len.zero?
74
74
  return list[0] if len == 1 # Fast path for single element
75
75
 
76
76
  result = list[0]
77
77
  i = 1
78
78
  while i < len
79
- result = block.call(result, list[i])
79
+ result = yield(result, list[i])
80
80
  i += 1
81
81
  end
82
82
  result
@@ -120,7 +120,7 @@ module Parsanol
120
120
  return r if r_is_slice
121
121
  return l if l_is_slice
122
122
 
123
- raise 'NOTREACHED: What other stringlike classes are there?'
123
+ raise "NOTREACHED: What other stringlike classes are there?"
124
124
  end
125
125
 
126
126
  # special case: If one of them is a string/slice, the other is more important
@@ -168,8 +168,8 @@ module Parsanol
168
168
  # If any arrays are nested in this array, flatten all arrays to this
169
169
  # level.
170
170
  return list
171
- .select { |e| e.instance_of?(Array) }
172
- .flatten(1)
171
+ .select { |e| e.instance_of?(Array) }
172
+ .flatten(1)
173
173
  end
174
174
 
175
175
  # Consistent handling of empty lists, when we act on a named result
@@ -21,11 +21,11 @@ module Parsanol
21
21
  # Per-parser cache size thresholds based on profiling different grammar types
22
22
  # Different grammars benefit from caching at different input sizes
23
23
  PARSER_CACHE_LIMITS = {
24
- 'JsonParser' => 10_000, # JSON needs large inputs to benefit
25
- 'ErbParser' => 800, # ERB benefits earlier
26
- 'CalcParser' => 2000, # Calculator has low repetition
27
- 'SentenceParser' => 5000, # Linear grammar, minimal benefit
28
- :default => 1000
24
+ "JsonParser" => 10_000, # JSON needs large inputs to benefit
25
+ "ErbParser" => 800, # ERB benefits earlier
26
+ "CalcParser" => 2000, # Calculator has low repetition
27
+ "SentenceParser" => 5000, # Linear grammar, minimal benefit
28
+ :default => 1000,
29
29
  }.freeze
30
30
 
31
31
  # Creates a new parsing context.
@@ -66,8 +66,8 @@ module Parsanol
66
66
  # Optional GPeg-style interval caching
67
67
  @use_intervals = interval_cache
68
68
  if @use_intervals
69
- require 'parsanol/interval_tree'
70
- require 'parsanol/edit_tracker'
69
+ require "parsanol/interval_tree"
70
+ require "parsanol/edit_tracker"
71
71
  @interval_trees = Hash.new { |h, k| h[k] = Parsanol::IntervalTree.new }
72
72
  @edits = Parsanol::EditTracker.new
73
73
  end
@@ -78,7 +78,7 @@ module Parsanol
78
78
  # Determine adaptive cache threshold
79
79
  threshold = adaptive_cache_threshold
80
80
  if threshold.nil? && parser_class
81
- name = parser_class.name&.split('::')&.last
81
+ name = parser_class.name&.split("::")&.last
82
82
  threshold = PARSER_CACHE_LIMITS[name] || PARSER_CACHE_LIMITS[:default]
83
83
  end
84
84
  threshold ||= PARSER_CACHE_LIMITS[:default]
@@ -143,7 +143,11 @@ module Parsanol
143
143
 
144
144
  # Only cache if beneficial (heuristic)
145
145
  attempts = @hit_stats[key] + @miss_stats[key]
146
- @memo[pos][key] = [outcome, delta] if attempts <= @min_hits_for_cache || @hit_stats[key].positive?
146
+ if attempts <= @min_hits_for_cache || @hit_stats[key].positive?
147
+ @memo[pos][key] =
148
+ [outcome,
149
+ delta]
150
+ end
147
151
 
148
152
  outcome
149
153
  end
@@ -175,7 +179,10 @@ module Parsanol
175
179
  end_pos = pos + delta
176
180
 
177
181
  attempts = @hit_stats[key] + @miss_stats[key]
178
- tree.insert(pos, end_pos, [outcome, delta]) if attempts <= @min_hits_for_cache || @hit_stats[key].positive?
182
+ if attempts <= @min_hits_for_cache || @hit_stats[key].positive?
183
+ tree.insert(pos, end_pos,
184
+ [outcome, delta])
185
+ end
179
186
 
180
187
  outcome
181
188
  end
@@ -188,8 +195,8 @@ module Parsanol
188
195
  #
189
196
  # @return [Array(Boolean, Object)] error result tuple
190
197
  #
191
- def err_at(*args)
192
- return [false, @reporter.err_at(*args)] if @reporter
198
+ def err_at(*)
199
+ return [false, @reporter.err_at(*)] if @reporter
193
200
 
194
201
  ERROR_RESULT
195
202
  end
@@ -198,8 +205,8 @@ module Parsanol
198
205
  #
199
206
  # @return [Array(Boolean, Object)] error result tuple
200
207
  #
201
- def err(*args)
202
- return [false, @reporter.err(*args)] if @reporter
208
+ def err(*)
209
+ return [false, @reporter.err(*)] if @reporter
203
210
 
204
211
  ERROR_RESULT
205
212
  end
@@ -208,10 +215,10 @@ module Parsanol
208
215
  #
209
216
  # @return [Array(Boolean, Object)] success result tuple
210
217
  #
211
- def succ(*args)
218
+ def succ(*)
212
219
  return SUCCESS_RESULT unless @reporter
213
220
 
214
- val = @reporter.succ(*args)
221
+ val = @reporter.succ(*)
215
222
  return SUCCESS_RESULT if val.nil?
216
223
 
217
224
  [true, val]
@@ -54,7 +54,7 @@ module Parsanol
54
54
  #
55
55
  def try_match(source, context, consume_all)
56
56
  raise NotImplementedError,
57
- 'Custom atoms must implement #try_match(source, context, consume_all)'
57
+ "Custom atoms must implement #try_match(source, context, consume_all)"
58
58
  end
59
59
 
60
60
  # Override of Base#try that delegates to try_match
@@ -71,7 +71,7 @@ module Parsanol
71
71
  context.err(
72
72
  self,
73
73
  source,
74
- "Failed to match custom atom: #{self.class.name}"
74
+ "Failed to match custom atom: #{self.class.name}",
75
75
  )
76
76
  end
77
77
  end
@@ -32,7 +32,7 @@ module Parsanol
32
32
  end
33
33
 
34
34
  def to_s_inner(_prec)
35
- 'dynamic { ... }'
35
+ "dynamic { ... }"
36
36
  end
37
37
  end
38
38
  end
@@ -74,7 +74,8 @@ module Parsanol
74
74
  right_operand = build_result_tree(right_operand)
75
75
  end
76
76
 
77
- accumulator = combiner.call(accumulator, operator_token, right_operand)
77
+ accumulator = combiner.call(accumulator, operator_token,
78
+ right_operand)
78
79
  end
79
80
 
80
81
  accumulator
@@ -96,7 +97,8 @@ module Parsanol
96
97
  ok, first_value = element_parser.apply(source, context, false)
97
98
  unless ok
98
99
  throw :parse_error,
99
- context.err(self, source, "Expected #{element_parser.inspect}", [first_value])
100
+ context.err(self, source, "Expected #{element_parser.inspect}",
101
+ [first_value])
100
102
  end
101
103
 
102
104
  expression_parts << flatten(first_value, true)
@@ -104,7 +106,9 @@ module Parsanol
104
106
  # Continue while operators match
105
107
  loop do
106
108
  saved_position = source.bytepos
107
- operator_match, precedence, associativity = try_match_operator(source, context, false)
109
+ operator_match, precedence, associativity = try_match_operator(
110
+ source, context, false
111
+ )
108
112
 
109
113
  # No operator found - done with this level
110
114
  break unless operator_match
@@ -114,7 +118,8 @@ module Parsanol
114
118
  next_min = associativity == :left ? precedence + 1 : precedence
115
119
 
116
120
  expression_parts << operator_match
117
- expression_parts << climb_precedence(source, context, consume_all, next_min)
121
+ expression_parts << climb_precedence(source, context, consume_all,
122
+ next_min)
118
123
  else
119
124
  # Operator has lower precedence - backtrack and return
120
125
  source.bytepos = saved_position
@@ -154,7 +159,7 @@ module Parsanol
154
159
 
155
160
  # Returns string representation for debugging
156
161
  def to_s_inner(_precedence)
157
- op_list = @operator_table.map { |op, _, _| op.inspect }.join(', ')
162
+ op_list = @operator_table.map { |op, _, _| op.inspect }.join(", ")
158
163
  "infix_expression(#{@base_element.inspect}, [#{op_list}])"
159
164
  end
160
165
  end
@@ -28,8 +28,8 @@ module Parsanol
28
28
  @bound_parslet = parser
29
29
 
30
30
  # Pre-built error components
31
- @should_start = ['Input should start with ', parser].freeze
32
- @should_not_start = ['Input should not start with ', parser].freeze
31
+ @should_start = ["Input should start with ", parser].freeze
32
+ @should_not_start = ["Input should not start with ", parser].freeze
33
33
  end
34
34
 
35
35
  # Tests lookahead without consuming input.
@@ -54,7 +54,10 @@ module Parsanol
54
54
  context.err_at(self, source, @should_start, source.bytepos)
55
55
  else
56
56
  # Negative: succeed if not matched
57
- return context.err_at(self, source, @should_not_start, source.bytepos) if matched
57
+ if matched
58
+ return context.err_at(self, source, @should_not_start,
59
+ source.bytepos)
60
+ end
58
61
 
59
62
  ok(nil)
60
63
  end
@@ -67,7 +70,7 @@ module Parsanol
67
70
  # @param prec [Integer] precedence
68
71
  # @return [String]
69
72
  def to_s_inner(prec)
70
- symbol = @positive ? '&' : '!'
73
+ symbol = @positive ? "&" : "!"
71
74
  "#{symbol}#{@bound_parslet.to_s(prec)}"
72
75
  end
73
76
 
@@ -29,7 +29,7 @@ module Parsanol
29
29
  @display = @match.inspect[1..-2] || @match
30
30
 
31
31
  # Pre-built error messages
32
- @eof_error = 'Unexpected end of input'
32
+ @eof_error = "Unexpected end of input"
33
33
  @no_match_error = "Failed to match #{@display}"
34
34
  end
35
35