parsanol 1.3.5-aarch64-linux → 1.3.7-aarch64-linux

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +48 -48
  3. data/lib/parsanol/ast_visitor.rb +1 -1
  4. data/lib/parsanol/atoms/alternative.rb +3 -2
  5. data/lib/parsanol/atoms/base.rb +12 -6
  6. data/lib/parsanol/atoms/can_flatten.rb +8 -8
  7. data/lib/parsanol/atoms/context.rb +23 -16
  8. data/lib/parsanol/atoms/custom.rb +2 -2
  9. data/lib/parsanol/atoms/dynamic.rb +1 -1
  10. data/lib/parsanol/atoms/infix.rb +10 -5
  11. data/lib/parsanol/atoms/lookahead.rb +7 -4
  12. data/lib/parsanol/atoms/re.rb +1 -1
  13. data/lib/parsanol/atoms/repetition.rb +29 -11
  14. data/lib/parsanol/atoms/sequence.rb +3 -2
  15. data/lib/parsanol/atoms/str.rb +9 -3
  16. data/lib/parsanol/atoms.rb +20 -20
  17. data/lib/parsanol/builder_callbacks.rb +2 -2
  18. data/lib/parsanol/cause.rb +2 -2
  19. data/lib/parsanol/context.rb +2 -2
  20. data/lib/parsanol/error_reporter.rb +5 -5
  21. data/lib/parsanol/expression/treetop.rb +17 -17
  22. data/lib/parsanol/expression.rb +1 -1
  23. data/lib/parsanol/fast_mode.rb +50 -12
  24. data/lib/parsanol/first_set.rb +1 -1
  25. data/lib/parsanol/grammar_builder.rb +10 -8
  26. data/lib/parsanol/incremental_parser.rb +13 -8
  27. data/lib/parsanol/interval_tree.rb +12 -3
  28. data/lib/parsanol/lazy_result.rb +2 -2
  29. data/lib/parsanol/mermaid.rb +12 -9
  30. data/lib/parsanol/native/batch_decoder.rb +13 -9
  31. data/lib/parsanol/native/dynamic.rb +7 -6
  32. data/lib/parsanol/native/parser.rb +7 -5
  33. data/lib/parsanol/native/serializer.rb +42 -42
  34. data/lib/parsanol/native/transformer.rb +55 -28
  35. data/lib/parsanol/native/types.rb +3 -3
  36. data/lib/parsanol/native.rb +26 -20
  37. data/lib/parsanol/optimizer.rb +6 -6
  38. data/lib/parsanol/optimizers/choice_optimizer.rb +1 -1
  39. data/lib/parsanol/optimizers/cut_inserter.rb +5 -2
  40. data/lib/parsanol/optimizers/lookahead_optimizer.rb +9 -3
  41. data/lib/parsanol/optimizers/quantifier_optimizer.rb +5 -5
  42. data/lib/parsanol/optimizers/sequence_optimizer.rb +1 -1
  43. data/lib/parsanol/options/zero_copy.rb +1 -1
  44. data/lib/parsanol/options.rb +1 -1
  45. data/lib/parsanol/parallel.rb +4 -3
  46. data/lib/parsanol/parser.rb +18 -16
  47. data/lib/parsanol/parslet.rb +7 -7
  48. data/lib/parsanol/pattern/binding.rb +1 -1
  49. data/lib/parsanol/pattern.rb +4 -1
  50. data/lib/parsanol/pool.rb +3 -3
  51. data/lib/parsanol/pools/buffer_pool.rb +2 -2
  52. data/lib/parsanol/pools/position_pool.rb +2 -2
  53. data/lib/parsanol/position.rb +1 -1
  54. data/lib/parsanol/result_builder.rb +4 -4
  55. data/lib/parsanol/result_stream.rb +10 -5
  56. data/lib/parsanol/slice.rb +11 -8
  57. data/lib/parsanol/source.rb +14 -9
  58. data/lib/parsanol/source_location.rb +1 -1
  59. data/lib/parsanol/streaming_parser.rb +3 -3
  60. data/lib/parsanol/string_view.rb +4 -1
  61. data/lib/parsanol/transform.rb +2 -2
  62. data/lib/parsanol/version.rb +1 -1
  63. data/lib/parsanol/wasm_parser.rb +1 -1
  64. data/lib/parsanol.rb +37 -39
  65. data/parsanol.gemspec +30 -30
  66. metadata +1 -1
@@ -63,7 +63,8 @@ module Parsanol
63
63
  when 2
64
64
  match_pair(components[0], components[1], source, context, consume_all)
65
65
  when 3
66
- match_triple(components[0], components[1], components[2], source, context, consume_all)
66
+ match_triple(components[0], components[1], components[2], source,
67
+ context, consume_all)
67
68
  else
68
69
  match_general(components, source, context, consume_all)
69
70
  end
@@ -76,7 +77,7 @@ module Parsanol
76
77
  # @param prec [Integer] precedence
77
78
  # @return [String]
78
79
  def to_s_inner(prec)
79
- @parslets.map { |p| p.to_s(prec) }.join(' ')
80
+ @parslets.map { |p| p.to_s(prec) }.join(" ")
80
81
  end
81
82
 
82
83
  # FIRST set is first element's FIRST set (with epsilon propagation).
@@ -21,7 +21,7 @@ module Parsanol
21
21
  @char_count = @str.length
22
22
 
23
23
  # Pre-built error messages (frozen)
24
- @early_eof_msg = 'Unexpected end of input'
24
+ @early_eof_msg = "Unexpected end of input"
25
25
  @mismatch_msg = "Expected #{@str.inspect}, but got "
26
26
 
27
27
  # Optimization: single-char fast path
@@ -75,7 +75,10 @@ module Parsanol
75
75
 
76
76
  # Fast path for single-character strings.
77
77
  def single_char_match(source, context)
78
- return context.err(self, source, @early_eof_msg) if source.chars_left < 1
78
+ if source.chars_left < 1
79
+ return context.err(self, source,
80
+ @early_eof_msg)
81
+ end
79
82
 
80
83
  pos = source.pos
81
84
  slice = source.consume(1)
@@ -88,7 +91,10 @@ module Parsanol
88
91
 
89
92
  # Standard path for multi-character strings.
90
93
  def multi_char_match(source, context)
91
- return context.err(self, source, @early_eof_msg) if source.chars_left < @char_count
94
+ if source.chars_left < @char_count
95
+ return context.err(self, source,
96
+ @early_eof_msg)
97
+ end
92
98
 
93
99
  pos = source.pos
94
100
  slice = source.consume(@char_count)
@@ -21,26 +21,26 @@ module Parsanol
21
21
  end
22
22
 
23
23
  # Load atom implementations
24
- require 'parsanol/atoms/can_flatten'
25
- require 'parsanol/atoms/context'
26
- require 'parsanol/atoms/dsl'
27
- require 'parsanol/atoms/base'
28
- require 'parsanol/atoms/custom'
29
- require 'parsanol/atoms/ignored'
30
- require 'parsanol/atoms/named'
31
- require 'parsanol/atoms/lookahead'
32
- require 'parsanol/atoms/cut'
33
- require 'parsanol/atoms/alternative'
34
- require 'parsanol/atoms/sequence'
35
- require 'parsanol/atoms/repetition'
36
- require 'parsanol/atoms/re'
37
- require 'parsanol/atoms/str'
38
- require 'parsanol/atoms/entity'
39
- require 'parsanol/atoms/capture'
40
- require 'parsanol/atoms/dynamic'
41
- require 'parsanol/atoms/scope'
42
- require 'parsanol/atoms/infix'
24
+ require "parsanol/atoms/can_flatten"
25
+ require "parsanol/atoms/context"
26
+ require "parsanol/atoms/dsl"
27
+ require "parsanol/atoms/base"
28
+ require "parsanol/atoms/custom"
29
+ require "parsanol/atoms/ignored"
30
+ require "parsanol/atoms/named"
31
+ require "parsanol/atoms/lookahead"
32
+ require "parsanol/atoms/cut"
33
+ require "parsanol/atoms/alternative"
34
+ require "parsanol/atoms/sequence"
35
+ require "parsanol/atoms/repetition"
36
+ require "parsanol/atoms/re"
37
+ require "parsanol/atoms/str"
38
+ require "parsanol/atoms/entity"
39
+ require "parsanol/atoms/capture"
40
+ require "parsanol/atoms/dynamic"
41
+ require "parsanol/atoms/scope"
42
+ require "parsanol/atoms/infix"
43
43
  # Load visitor pattern (must be after all atom classes)
44
- require 'parsanol/atoms/visitor'
44
+ require "parsanol/atoms/visitor"
45
45
  end
46
46
  end
@@ -204,7 +204,7 @@ module Parsanol
204
204
  end
205
205
 
206
206
  def on_success
207
- @events << 'success'
207
+ @events << "success"
208
208
  end
209
209
 
210
210
  def on_error(message)
@@ -228,7 +228,7 @@ module Parsanol
228
228
  end
229
229
 
230
230
  def on_nil
231
- @events << 'nil'
231
+ @events << "nil"
232
232
  end
233
233
 
234
234
  def on_hash_start(size = nil)
@@ -113,10 +113,10 @@ module Parsanol
113
113
  return if prefix_flags.size < 2
114
114
 
115
115
  prefix_flags[1..-2].each do |is_last|
116
- stream.print is_last ? ' ' : '| '
116
+ stream.print is_last ? " " : "| "
117
117
  end
118
118
 
119
- stream.print prefix_flags.last ? '`- ' : '|- '
119
+ stream.print prefix_flags.last ? "`- " : "|- "
120
120
  end
121
121
  end
122
122
  end
@@ -32,8 +32,8 @@ module Parsanol
32
32
  #
33
33
  # @param name [Symbol, String] method name
34
34
  # @yield block to execute when method is called
35
- def define_singleton_method(name, &body)
36
- singleton_class.define_method(name, &body)
35
+ def define_singleton_method(name, &)
36
+ singleton_class.define_method(name, &)
37
37
  end
38
38
  end
39
39
  end
@@ -50,7 +50,7 @@ module Parsanol
50
50
  #
51
51
  def err(atom, source, message, children = nil)
52
52
  raise NotImplementedError,
53
- 'Error reporters must implement #err(atom, source, message, children)'
53
+ "Error reporters must implement #err(atom, source, message, children)"
54
54
  end
55
55
 
56
56
  # Report an error at a specific position.
@@ -66,7 +66,7 @@ module Parsanol
66
66
  #
67
67
  def err_at(atom, source, message, pos, children = nil)
68
68
  raise NotImplementedError,
69
- 'Error reporters must implement #err_at(atom, source, message, pos, children)'
69
+ "Error reporters must implement #err_at(atom, source, message, pos, children)"
70
70
  end
71
71
 
72
72
  # Called when an expression successfully parses.
@@ -95,6 +95,6 @@ module Parsanol
95
95
  end
96
96
  end
97
97
 
98
- require 'parsanol/error_reporter/tree'
99
- require 'parsanol/error_reporter/deepest'
100
- require 'parsanol/error_reporter/contextual'
98
+ require "parsanol/error_reporter/tree"
99
+ require "parsanol/error_reporter/deepest"
100
+ require "parsanol/error_reporter/contextual"
@@ -44,7 +44,7 @@ module Parsanol
44
44
 
45
45
  # Alternative: 'a' / 'b'
46
46
  rule(:alternatives) do
47
- (simple >> (spaced('/') >> simple).repeat).as(:alt)
47
+ (simple >> (spaced("/") >> simple).repeat).as(:alt)
48
48
  end
49
49
 
50
50
  # Sequence by concatenation: 'a' 'b'
@@ -52,15 +52,15 @@ module Parsanol
52
52
 
53
53
  # Occurrence modifiers: ?, *, +, {min,max}
54
54
  rule(:occurrence) do
55
- (atom.as(:repetition) >> spaced('*').as(:sign)) |
56
- (atom.as(:repetition) >> spaced('+').as(:sign)) |
55
+ (atom.as(:repetition) >> spaced("*").as(:sign)) |
56
+ (atom.as(:repetition) >> spaced("+").as(:sign)) |
57
57
  (atom.as(:repetition) >> repetition_spec) |
58
- (atom.as(:maybe) >> spaced('?')) |
58
+ (atom.as(:maybe) >> spaced("?")) |
59
59
  atom
60
60
  end
61
61
 
62
62
  rule(:atom) do
63
- (spaced('(') >> expression.as(:unwrap) >> spaced(')')) |
63
+ (spaced("(") >> expression.as(:unwrap) >> spaced(")")) |
64
64
  dot |
65
65
  string |
66
66
  char_class
@@ -68,30 +68,30 @@ module Parsanol
68
68
 
69
69
  # Character class: [a-z], [0-9], etc.
70
70
  rule(:char_class) do
71
- (str('[') >>
72
- ((str('\\') >> any) | (str(']').absent? >> any)).repeat(1) >>
73
- str(']')).as(:match) >> space?
71
+ (str("[") >>
72
+ ((str("\\") >> any) | (str("]").absent? >> any)).repeat(1) >>
73
+ str("]")).as(:match) >> space?
74
74
  end
75
75
 
76
76
  # Any character: .
77
- rule(:dot) { spaced('.').as(:any) }
77
+ rule(:dot) { spaced(".").as(:any) }
78
78
 
79
79
  # String literal: 'hello'
80
80
  rule(:string) do
81
81
  str("'") >>
82
- ((str('\\') >> any) | (str("'").absent? >> any)).repeat.as(:string) >>
82
+ ((str("\\") >> any) | (str("'").absent? >> any)).repeat.as(:string) >>
83
83
  str("'") >> space?
84
84
  end
85
85
 
86
86
  # Repetition specification: {1,3}, {2,}, {,5}
87
87
  rule(:repetition_spec) do
88
- spaced('{') >>
89
- integer.maybe.as(:min) >> spaced(',') >>
90
- integer.maybe.as(:max) >> spaced('}')
88
+ spaced("{") >>
89
+ integer.maybe.as(:min) >> spaced(",") >>
90
+ integer.maybe.as(:max) >> spaced("}")
91
91
  end
92
92
 
93
93
  rule(:integer) do
94
- match['0-9'].repeat(1)
94
+ match["0-9"].repeat(1)
95
95
  end
96
96
 
97
97
  # Whitespace handling
@@ -115,7 +115,7 @@ module Parsanol
115
115
  class Transform < Parsanol::Transform
116
116
  # Repetition with sign: * (zero+) or + (one+)
117
117
  rule(repetition: simple(:rep), sign: simple(:sign)) do
118
- min = sign == '+' ? 1 : 0
118
+ min = sign == "+" ? 1 : 0
119
119
  Parsanol::Atoms::Repetition.new(rep, min, nil)
120
120
  end
121
121
 
@@ -124,7 +124,7 @@ module Parsanol
124
124
  Parsanol::Atoms::Repetition.new(
125
125
  rep,
126
126
  Integer(min || 0),
127
- (max && Integer(max)) || nil
127
+ (max && Integer(max)) || nil,
128
128
  )
129
129
  end
130
130
 
@@ -147,7 +147,7 @@ module Parsanol
147
147
  rule(match: simple(:m)) { Parsanol::Atoms::Re.new("[#{m}]") }
148
148
 
149
149
  # Any character: .
150
- rule(any: simple(:_a)) { Parsanol::Atoms::Re.new('.') }
150
+ rule(any: simple(:_a)) { Parsanol::Atoms::Re.new(".") }
151
151
  end
152
152
  end
153
153
  end
@@ -56,7 +56,7 @@ module Parsanol
56
56
  class Expression
57
57
  include Parsanol
58
58
 
59
- autoload :Treetop, 'parsanol/expression/treetop'
59
+ autoload :Treetop, "parsanol/expression/treetop"
60
60
 
61
61
  # Creates a parser atom from a treetop-style expression string.
62
62
  #
@@ -25,7 +25,10 @@ module Parsanol
25
25
  unless (entry = @cache[beg]&.[](obj.object_id))
26
26
  result = obj.try(source, self, consume_all)
27
27
 
28
- (@cache[beg] ||= {})[obj.object_id] = [result, source.bytepos - beg] if obj.cached?
28
+ if obj.cached?
29
+ (@cache[beg] ||= {})[obj.object_id] =
30
+ [result, source.bytepos - beg]
31
+ end
29
32
 
30
33
  return result
31
34
  end
@@ -45,13 +48,24 @@ module Parsanol
45
48
  case parslets.size
46
49
  when 1
47
50
  success, value = parslets[0].apply(source, context, consume_all)
48
- success ? succ([:sequence, value]) : context.err(self, source, @error_msg, [value])
51
+ if success
52
+ succ([:sequence,
53
+ value])
54
+ else
55
+ context.err(self, source, @error_msg,
56
+ [value])
57
+ end
49
58
  when 2
50
59
  success, v1 = parslets[0].apply(source, context, false)
51
60
  return context.err(self, source, @error_msg, [v1]) unless success
52
61
 
53
62
  success, v2 = parslets[1].apply(source, context, consume_all)
54
- success ? succ([:sequence, v1, v2]) : context.err(self, source, @error_msg, [v2])
63
+ if success
64
+ succ([:sequence, v1,
65
+ v2])
66
+ else
67
+ context.err(self, source, @error_msg, [v2])
68
+ end
55
69
  when 3
56
70
  success, v1 = parslets[0].apply(source, context, false)
57
71
  return context.err(self, source, @error_msg, [v1]) unless success
@@ -60,13 +74,19 @@ module Parsanol
60
74
  return context.err(self, source, @error_msg, [v2]) unless success
61
75
 
62
76
  success, v3 = parslets[2].apply(source, context, consume_all)
63
- success ? succ([:sequence, v1, v2, v3]) : context.err(self, source, @error_msg, [v3])
77
+ if success
78
+ succ([:sequence, v1, v2,
79
+ v3])
80
+ else
81
+ context.err(self, source, @error_msg, [v3])
82
+ end
64
83
  else
65
84
  result = [:sequence]
66
85
  last_idx = parslets.size - 1
67
86
  i = 0
68
87
  while i <= last_idx
69
- success, value = parslets[i].apply(source, context, consume_all && i == last_idx)
88
+ success, value = parslets[i].apply(source, context,
89
+ consume_all && i == last_idx)
70
90
  return context.err(self, source, @error_msg, [value]) unless success
71
91
 
72
92
  result << value
@@ -100,22 +120,37 @@ module Parsanol
100
120
  case max
101
121
  when 1
102
122
  success, value = parslet.apply(source, context, consume_all)
103
- return success ? succ([tag, value]) : context.err_at(self, source, @error_msg, source.bytepos, [value])
123
+ return success ? succ([tag,
124
+ value]) : context.err_at(self, source,
125
+ @error_msg, source.bytepos, [value])
104
126
  when 2
105
127
  success, v1 = parslet.apply(source, context, false)
106
- return context.err_at(self, source, @error_msg, source.bytepos, [v1]) unless success
128
+ unless success
129
+ return context.err_at(self, source, @error_msg, source.bytepos,
130
+ [v1])
131
+ end
107
132
 
108
133
  success, v2 = parslet.apply(source, context, consume_all)
109
- return success ? succ([tag, v1, v2]) : context.err_at(self, source, @error_msg, source.bytepos, [v2])
134
+ return success ? succ([tag, v1,
135
+ v2]) : context.err_at(self, source,
136
+ @error_msg, source.bytepos, [v2])
110
137
  when 3
111
138
  success, v1 = parslet.apply(source, context, false)
112
- return context.err_at(self, source, @error_msg, source.bytepos, [v1]) unless success
139
+ unless success
140
+ return context.err_at(self, source, @error_msg, source.bytepos,
141
+ [v1])
142
+ end
113
143
 
114
144
  success, v2 = parslet.apply(source, context, false)
115
- return context.err_at(self, source, @error_msg, source.bytepos, [v2]) unless success
145
+ unless success
146
+ return context.err_at(self, source, @error_msg, source.bytepos,
147
+ [v2])
148
+ end
116
149
 
117
150
  success, v3 = parslet.apply(source, context, consume_all)
118
- return success ? succ([tag, v1, v2, v3]) : context.err_at(self, source, @error_msg, source.bytepos, [v3])
151
+ return success ? succ([tag, v1, v2,
152
+ v3]) : context.err_at(self, source,
153
+ @error_msg, source.bytepos, [v3])
119
154
  end
120
155
  end
121
156
 
@@ -140,7 +175,10 @@ module Parsanol
140
175
  return context.err_at(self, source, @error_msg, start_pos, [break_on])
141
176
  end
142
177
 
143
- return context.err(self, source, @unconsumed_msg, [break_on]) if consume_all && source.chars_left.positive?
178
+ if consume_all && source.chars_left.positive?
179
+ return context.err(self, source, @unconsumed_msg,
180
+ [break_on])
181
+ end
144
182
 
145
183
  succ(result)
146
184
  end
@@ -58,7 +58,7 @@ module Parsanol
58
58
  return true if real_set1.empty? || real_set2.empty?
59
59
 
60
60
  # Check if intersection is empty (using to_a for Opal compatibility)
61
- (real_set1.to_a & real_set2.to_a).empty?
61
+ !real_set1.to_a.intersect?(real_set2.to_a)
62
62
  end
63
63
 
64
64
  # Check if all FIRST sets in a collection are mutually disjoint
@@ -72,7 +72,8 @@ module Parsanol
72
72
  when Hash
73
73
  grammar
74
74
  else
75
- raise ArgumentError, "Expected GrammarBuilder or Hash, got #{grammar.class}"
75
+ raise ArgumentError,
76
+ "Expected GrammarBuilder or Hash, got #{grammar.class}"
76
77
  end
77
78
 
78
79
  @imports << { grammar: grammar_data, prefix: prefix }
@@ -92,7 +93,8 @@ module Parsanol
92
93
  when Hash
93
94
  grammar
94
95
  else
95
- raise ArgumentError, "Expected GrammarBuilder or Hash, got #{grammar.class}"
96
+ raise ArgumentError,
97
+ "Expected GrammarBuilder or Hash, got #{grammar.class}"
96
98
  end
97
99
 
98
100
  @imports << { grammar: grammar_data, prefix: prefix, rules: rules }
@@ -106,7 +108,7 @@ module Parsanol
106
108
  {
107
109
  rules: @rules,
108
110
  root: @root,
109
- imports: @imports
111
+ imports: @imports,
110
112
  }
111
113
  end
112
114
 
@@ -140,7 +142,7 @@ module Parsanol
140
142
  if grammar_name
141
143
  ref("#{grammar_name}:root")
142
144
  else
143
- ref('root')
145
+ ref("root")
144
146
  end
145
147
  end
146
148
 
@@ -149,9 +151,9 @@ module Parsanol
149
151
  #
150
152
  # @yield [GrammarBuilder] Builder to configure
151
153
  # @return [Hash] Built grammar
152
- def build(&block)
154
+ def build(&)
153
155
  builder = new
154
- builder.instance_eval(&block)
156
+ builder.instance_eval(&)
155
157
  builder.build
156
158
  end
157
159
 
@@ -170,8 +172,8 @@ module Parsanol
170
172
  # Create a new grammar builder
171
173
  #
172
174
  # @return [GrammarBuilder] New builder
173
- def grammar(&block)
174
- GrammarBuilder.build(&block)
175
+ def grammar(&)
176
+ GrammarBuilder.build(&)
175
177
  end
176
178
  end
177
179
  end
@@ -19,7 +19,7 @@ module Parsanol
19
19
  class Edit
20
20
  attr_reader :start, :deleted, :inserted
21
21
 
22
- def initialize(start:, deleted:, inserted: '')
22
+ def initialize(start:, deleted:, inserted: "")
23
23
  @start = start
24
24
  @deleted = deleted
25
25
  @inserted = inserted
@@ -61,13 +61,14 @@ module Parsanol
61
61
  #
62
62
  # @param grammar [Parsanol::Parser, Parsanol::Atoms::Base] Grammar to use
63
63
  # @param initial_input [String] Initial input string
64
- def initialize(grammar, initial_input = '')
64
+ def initialize(grammar, initial_input = "")
65
65
  @grammar = grammar
66
66
  @input = initial_input
67
67
 
68
68
  if Parsanol::Native.available?
69
69
  grammar_json = Parsanol::Native.serialize_grammar(grammar.root)
70
- @native_parser = Parsanol::Native.incremental_parser_new(grammar_json, initial_input)
70
+ @native_parser = Parsanol::Native.incremental_parser_new(grammar_json,
71
+ initial_input)
71
72
  else
72
73
  @native_parser = nil
73
74
  end
@@ -81,7 +82,7 @@ module Parsanol
81
82
  # @param start [Integer] Start position of edit
82
83
  # @param deleted [Integer] Number of characters deleted
83
84
  # @param inserted [String] Text to insert
84
- def apply_edit(start:, deleted:, inserted: '')
85
+ def apply_edit(start:, deleted:, inserted: "")
85
86
  edit = Edit.new(start: start, deleted: deleted, inserted: inserted)
86
87
  @edits << edit
87
88
 
@@ -93,7 +94,8 @@ module Parsanol
93
94
 
94
95
  return unless @native_parser
95
96
 
96
- Parsanol::Native.incremental_parser_apply_edit(@native_parser, start, deleted, inserted)
97
+ Parsanol::Native.incremental_parser_apply_edit(@native_parser, start,
98
+ deleted, inserted)
97
99
  end
98
100
 
99
101
  # Convenience method to apply multiple edits
@@ -119,7 +121,9 @@ module Parsanol
119
121
  return @cached_result if @cached_result
120
122
 
121
123
  if @native_parser
122
- @cached_result = Parsanol::Native.incremental_parser_reparse(@native_parser, @input)
124
+ @cached_result = Parsanol::Native.incremental_parser_reparse(
125
+ @native_parser, @input
126
+ )
123
127
  else
124
128
  # Pure Ruby fallback - reparse from scratch
125
129
  root = @grammar.root
@@ -164,14 +168,15 @@ module Parsanol
164
168
  #
165
169
  # @param new_input [String, nil] Optional new initial input
166
170
  def reset(new_input = nil)
167
- @input = new_input || ''
171
+ @input = new_input || ""
168
172
  @edits.clear
169
173
  @cached_result = nil
170
174
 
171
175
  return unless @native_parser && new_input
172
176
 
173
177
  grammar_json = Parsanol::Native.serialize_grammar(@grammar.root)
174
- @native_parser = Parsanol::Native.incremental_parser_new(grammar_json, @input)
178
+ @native_parser = Parsanol::Native.incremental_parser_new(grammar_json,
179
+ @input)
175
180
  end
176
181
  end
177
182
  end
@@ -132,7 +132,10 @@ module Parsanol
132
132
 
133
133
  # Check right subtree
134
134
  # Only search right if intervals starting there could overlap
135
- query_recursive(node.right, low, high, results) if node.right && node.low < high
135
+ if node.right && node.low < high
136
+ query_recursive(node.right, low, high,
137
+ results)
138
+ end
136
139
  end
137
140
 
138
141
  # Find exact interval match
@@ -154,10 +157,16 @@ module Parsanol
154
157
  return nil if node.nil?
155
158
 
156
159
  # Recursively delete from left subtree
157
- node.left = delete_overlapping_recursive(node.left, low, high, deleted) if node.left
160
+ if node.left
161
+ node.left = delete_overlapping_recursive(node.left, low, high,
162
+ deleted)
163
+ end
158
164
 
159
165
  # Recursively delete from right subtree
160
- node.right = delete_overlapping_recursive(node.right, low, high, deleted) if node.right
166
+ if node.right
167
+ node.right = delete_overlapping_recursive(node.right, low, high,
168
+ deleted)
169
+ end
161
170
 
162
171
  # Check if current node overlaps
163
172
  if node.low < high && low < node.high
@@ -85,10 +85,10 @@ module Parsanol
85
85
  # @yield [element] Each element
86
86
  # @return [Enumerator, self] Enumerator if no block, self otherwise
87
87
  #
88
- def each(&block)
88
+ def each(&)
89
89
  return to_enum(:each) unless block_given?
90
90
 
91
- to_a.each(&block)
91
+ to_a.each(&)
92
92
  self
93
93
  end
94
94
 
@@ -16,7 +16,7 @@ module Parsanol
16
16
  # Generates Mermaid diagram syntax from parser atoms.
17
17
  class MermaidBuilder
18
18
  def initialize
19
- @lines = ['graph TD']
19
+ @lines = ["graph TD"]
20
20
  @node_counter = 0
21
21
  @connections = []
22
22
  @seen_rules = Set.new
@@ -24,8 +24,8 @@ module Parsanol
24
24
 
25
25
  # Entry point for parser visualization
26
26
  def visit_parser(root_atom)
27
- add_node('Parser', 'root')
28
- traverse(root_atom, 'Parser')
27
+ add_node("Parser", "root")
28
+ traverse(root_atom, "Parser")
29
29
  finalize
30
30
  end
31
31
 
@@ -35,7 +35,7 @@ module Parsanol
35
35
 
36
36
  @seen_rules << rule_name
37
37
 
38
- node_id = add_node(rule_name.to_s.upcase, 'rule')
38
+ node_id = add_node(rule_name.to_s.upcase, "rule")
39
39
  connect(current_parent, node_id)
40
40
  traverse(rule_block.call, node_id)
41
41
  end
@@ -67,18 +67,18 @@ module Parsanol
67
67
 
68
68
  # Leaf nodes
69
69
  def visit_re(regexp)
70
- add_node("match(#{regexp.inspect})", 'terminal', style: 'ellipse')
70
+ add_node("match(#{regexp.inspect})", "terminal", style: "ellipse")
71
71
  end
72
72
 
73
73
  def visit_str(string)
74
- add_node("'#{string}'", 'terminal', style: 'ellipse')
74
+ add_node("'#{string}'", "terminal", style: "ellipse")
75
75
  end
76
76
 
77
77
  private
78
78
 
79
79
  attr_reader :current_parent
80
80
 
81
- def add_node(label, _shape_type = 'rect', _style = nil)
81
+ def add_node(label, _shape_type = "rect", _style = nil)
82
82
  @node_counter += 1
83
83
  node_id = "node_#{@node_counter}"
84
84
  @lines << " #{node_id}[\"#{escape_mermaid(label)}\"]"
@@ -97,7 +97,7 @@ module Parsanol
97
97
  @connections.each do |from, to|
98
98
  @lines << " #{from} --> #{to}"
99
99
  end
100
- @lines << ''
100
+ @lines << ""
101
101
  @lines.join("\n")
102
102
  end
103
103
 
@@ -125,7 +125,10 @@ module Parsanol
125
125
  def mermaid_for_rule(rule_name)
126
126
  builder = MermaidBuilder.new
127
127
  rule_method = method(rule_name)
128
- raise NotImplementedError, "Rule '#{rule_name}' not found" unless rule_method
128
+ unless rule_method
129
+ raise NotImplementedError,
130
+ "Rule '#{rule_name}' not found"
131
+ end
129
132
 
130
133
  rule_method.call.accept(builder)
131
134
  builder.output