packcr 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/packcr/generated/context.rb +8 -13
  4. data/lib/packcr/generated/node/action_node.rb +4 -6
  5. data/lib/packcr/generated/node/alternate_node.rb +11 -17
  6. data/lib/packcr/generated/node/capture_node.rb +1 -1
  7. data/lib/packcr/generated/node/charclass_node.rb +8 -8
  8. data/lib/packcr/generated/node/eof_node.rb +1 -1
  9. data/lib/packcr/generated/node/error_node.rb +1 -1
  10. data/lib/packcr/generated/node/expand_node.rb +1 -1
  11. data/lib/packcr/generated/node/predicate_node.rb +9 -7
  12. data/lib/packcr/generated/node/quantity_node.rb +16 -16
  13. data/lib/packcr/generated/node/reference_node.rb +3 -8
  14. data/lib/packcr/generated/node/rule_node.rb +6 -6
  15. data/lib/packcr/generated/node/sequence_node.rb +1 -1
  16. data/lib/packcr/generated/node/string_node.rb +28 -4
  17. data/lib/packcr/generator.rb +4 -3
  18. data/lib/packcr/node/action_node.rb +2 -2
  19. data/lib/packcr/node/alternate_node.rb +2 -2
  20. data/lib/packcr/node/capture_node.rb +2 -2
  21. data/lib/packcr/node/charclass_node.rb +15 -15
  22. data/lib/packcr/node/eof_node.rb +2 -2
  23. data/lib/packcr/node/error_node.rb +2 -2
  24. data/lib/packcr/node/expand_node.rb +2 -2
  25. data/lib/packcr/node/predicate_node.rb +3 -3
  26. data/lib/packcr/node/quantity_node.rb +4 -4
  27. data/lib/packcr/node/reference_node.rb +4 -4
  28. data/lib/packcr/node/rule_node.rb +2 -2
  29. data/lib/packcr/node/sequence_node.rb +2 -2
  30. data/lib/packcr/node/string_node.rb +17 -3
  31. data/lib/packcr/parser.rb +1 -1
  32. data/lib/packcr/templates/context/source.rs.erb +93 -91
  33. data/lib/packcr/templates/node/action.rs.erb +5 -5
  34. data/lib/packcr/templates/node/alternate.rs.erb +28 -29
  35. data/lib/packcr/templates/node/charclass_utf8.rs.erb +3 -3
  36. data/lib/packcr/templates/node/predicate_neg.rs.erb +6 -6
  37. data/lib/packcr/templates/node/quantity_many.rs.erb +55 -28
  38. data/lib/packcr/templates/node/reference.rs.erb +2 -2
  39. data/lib/packcr/templates/node/rule.rs.erb +20 -11
  40. data/lib/packcr/templates/node/string_many.rs.erb +4 -4
  41. data/lib/packcr/templates/node/string_many_reverse.rs.erb +7 -0
  42. data/lib/packcr/templates/node/string_one.rs.erb +3 -3
  43. data/lib/packcr/templates/node/string_one_reverse.rs.erb +6 -0
  44. data/lib/packcr/version.rb +1 -1
  45. metadata +6 -4
@@ -33,8 +33,8 @@ class Packcr
33
33
  end
34
34
  end
35
35
 
36
- def generate_code(gen, onfail, indent, bare, oncut: nil)
37
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
36
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
37
+ get_code(gen, onfail, indent, unwrap, oncut)
38
38
  end
39
39
 
40
40
  def reachability
@@ -27,8 +27,8 @@ class Packcr
27
27
  m
28
28
  end
29
29
 
30
- def generate_code(gen, onfail, indent, bare, oncut: nil)
31
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
30
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
31
+ get_code(gen, onfail, indent, unwrap, oncut)
32
32
  end
33
33
 
34
34
  def reachability
@@ -15,8 +15,8 @@ class Packcr
15
15
  $stdout.print "#{" " * indent}}\n"
16
16
  end
17
17
 
18
- def generate_code(gen, onfail, indent, bare, oncut: nil)
19
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent)
18
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
19
+ get_code(gen, onfail, indent, unwrap, oncut)
20
20
  end
21
21
 
22
22
  def reachability
@@ -17,16 +17,16 @@ class Packcr
17
17
  gen.lang == :rb && !gen.ascii
18
18
  end
19
19
 
20
- def generate_code(gen, onfail, indent, bare, oncut: nil)
21
- return generate_ascii_code(gen, onfail, indent, bare) if gen.ascii
20
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
21
+ return generate_ascii_code(gen, onfail, indent, unwrap) if gen.ascii
22
22
 
23
- generate_utf8_charclass_code(gen, onfail, indent, bare)
23
+ generate_utf8_charclass_code(gen, onfail, indent, unwrap)
24
24
  end
25
25
 
26
- def generate_reverse_code(gen, onsuccess, indent, bare, oncut: nil)
26
+ def generate_reverse_code(gen, onsuccess, indent, unwrap, oncut: nil)
27
27
  raise "unexpected" if gen.ascii
28
28
 
29
- generate_utf8_charclass_reverse_code(gen, onsuccess, indent, bare)
29
+ generate_utf8_charclass_reverse_code(gen, onsuccess, indent, unwrap)
30
30
  end
31
31
 
32
32
  def reachability
@@ -39,20 +39,20 @@ class Packcr
39
39
 
40
40
  private
41
41
 
42
- def generate_utf8_charclass_code(gen, onfail, indent, bare)
42
+ def generate_utf8_charclass_code(gen, onfail, indent, unwrap)
43
43
  charclass = value
44
44
  if charclass && charclass.encoding != Encoding::UTF_8
45
45
  charclass = charclass.dup.force_encoding(Encoding::UTF_8)
46
46
  end
47
47
  n = charclass&.length || 0
48
48
  if charclass.nil? || n > 0
49
- gen.write Packcr.format_code(get_utf8_code(gen, onfail, indent, bare, charclass, n), indent: indent, unwrap: bare)
49
+ get_utf8_code(gen, onfail, indent, unwrap, charclass, n)
50
50
  else
51
- gen.write Packcr.format_code(get_fail_code(gen, onfail, indent, bare), indent: indent)
51
+ get_fail_code(gen, onfail, indent, unwrap)
52
52
  end
53
53
  end
54
54
 
55
- def generate_utf8_charclass_reverse_code(gen, onsuccess, indent, bare)
55
+ def generate_utf8_charclass_reverse_code(gen, onsuccess, indent, unwrap)
56
56
  charclass = value
57
57
  if charclass && charclass.encoding != Encoding::UTF_8
58
58
  charclass = charclass.dup.force_encoding(Encoding::UTF_8)
@@ -60,10 +60,10 @@ class Packcr
60
60
  n = charclass&.length || 0
61
61
  return unless charclass.nil? || n > 0
62
62
 
63
- gen.write Packcr.format_code(get_utf8_reverse_code(gen, onsuccess, indent, bare, charclass, n), indent: indent, unwrap: bare)
63
+ get_utf8_reverse_code(gen, onsuccess, indent, unwrap, charclass, n)
64
64
  end
65
65
 
66
- def generate_ascii_code(gen, onfail, indent, bare)
66
+ def generate_ascii_code(gen, onfail, indent, unwrap)
67
67
  charclass = value
68
68
  if charclass
69
69
  n = charclass.length
@@ -74,15 +74,15 @@ class Packcr
74
74
  end
75
75
  if n > 0
76
76
  if n > 1
77
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, charclass, n, a), indent: indent, unwrap: bare)
77
+ get_code(gen, onfail, indent, unwrap, charclass, n, a)
78
78
  else
79
- gen.write Packcr.format_code(get_one_code(gen, onfail, indent, bare, charclass, n, a), indent: indent)
79
+ get_one_code(gen, onfail, indent, unwrap, charclass, n, a)
80
80
  end
81
81
  else
82
- gen.write Packcr.format_code(get_fail_code(gen, onfail, indent, bare), indent: indent)
82
+ get_fail_code(gen, onfail, indent, unwrap)
83
83
  end
84
84
  else
85
- gen.write Packcr.format_code(get_any_code(gen, onfail, indent, bare, charclass), indent: indent)
85
+ get_any_code(gen, onfail, indent, unwrap, charclass)
86
86
  end
87
87
  end
88
88
 
@@ -5,8 +5,8 @@ class Packcr
5
5
  $stdout.print "#{" " * indent}Eof()\n"
6
6
  end
7
7
 
8
- def generate_code(gen, onfail, indent, bare, oncut: nil)
9
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
8
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
9
+ get_code(gen, onfail, indent, unwrap, oncut)
10
10
  end
11
11
 
12
12
  def reachability
@@ -29,8 +29,8 @@ class Packcr
29
29
  $stdout.print "#{" " * indent}}\n"
30
30
  end
31
31
 
32
- def generate_code(gen, onfail, indent, bare, oncut: nil)
33
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
32
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
33
+ get_code(gen, onfail, indent, unwrap, oncut)
34
34
  end
35
35
 
36
36
  def reachability
@@ -15,8 +15,8 @@ class Packcr
15
15
  $stdout.print ")\n"
16
16
  end
17
17
 
18
- def generate_code(gen, onfail, indent, bare, oncut: nil)
19
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
18
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
19
+ get_code(gen, onfail, indent, unwrap, oncut)
20
20
  end
21
21
 
22
22
  def reachability
@@ -15,11 +15,11 @@ class Packcr
15
15
  $stdout.print "#{" " * indent}}\n"
16
16
  end
17
17
 
18
- def generate_code(gen, onfail, indent, bare, oncut: nil)
18
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
19
19
  if neg
20
- gen.write Packcr.format_code(get_neg_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
20
+ get_neg_code(gen, onfail, indent, unwrap, oncut)
21
21
  else
22
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
22
+ get_code(gen, onfail, indent, unwrap, oncut)
23
23
  end
24
24
  end
25
25
 
@@ -16,14 +16,14 @@ class Packcr
16
16
  $stdout.print "#{" " * indent}}\n"
17
17
  end
18
18
 
19
- def generate_code(gen, onfail, indent, bare, oncut: nil)
19
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
20
20
  if max > 1 || max < 0
21
- gen.write Packcr.format_code(get_many_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
21
+ get_many_code(gen, onfail, indent, unwrap, oncut)
22
22
  elsif max == 1
23
23
  if min > 0
24
- gen.write gen.generate_code(expr, onfail, indent, bare, oncut: oncut)
24
+ gen.generate_code(expr, onfail, indent, unwrap, oncut: oncut)
25
25
  else
26
- gen.write Packcr.format_code(get_one_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
26
+ get_one_code(gen, onfail, indent, unwrap, oncut)
27
27
  end
28
28
  end
29
29
  end
@@ -20,12 +20,12 @@ class Packcr
20
20
  gen.lang == :rb
21
21
  end
22
22
 
23
- def generate_code(gen, onfail, indent, bare, oncut: nil)
24
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
23
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
24
+ get_code(gen, onfail, indent, unwrap, oncut)
25
25
  end
26
26
 
27
- def generate_reverse_code(gen, onsuccess, indent, bare, oncut: nil)
28
- gen.write Packcr.format_code(get_reverse_code(gen, onsuccess, indent, bare, oncut), indent: indent)
27
+ def generate_reverse_code(gen, onsuccess, indent, unwrap, oncut: nil)
28
+ get_reverse_code(gen, onsuccess, indent, unwrap, oncut)
29
29
  end
30
30
 
31
31
  def reachability
@@ -22,8 +22,8 @@ class Packcr
22
22
  $stdout.print "#{" " * indent}}\n"
23
23
  end
24
24
 
25
- def generate_code(gen, onfail, indent, bare, oncut: nil)
26
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
25
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
26
+ get_code(gen, onfail, indent, unwrap, oncut)
27
27
  end
28
28
 
29
29
  def reachability
@@ -53,8 +53,8 @@ class Packcr
53
53
  m
54
54
  end
55
55
 
56
- def generate_code(gen, onfail, indent, bare, oncut: nil)
57
- gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent)
56
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
57
+ get_code(gen, onfail, indent, unwrap, oncut)
58
58
  end
59
59
 
60
60
  def reachability
@@ -17,14 +17,28 @@ class Packcr
17
17
  $stdout.print "')\n"
18
18
  end
19
19
 
20
- def generate_code(gen, onfail, indent, bare, oncut: nil)
20
+ def reversible?(gen)
21
+ gen.lang == :rs
22
+ end
23
+
24
+ def generate_code(gen, onfail, indent, unwrap, oncut: nil)
21
25
  n = value&.length || 0
22
26
  return unless n > 0
23
27
 
24
28
  if n > 1
25
- gen.write Packcr.format_code(get_many_code(gen, onfail, indent, bare, oncut, n), indent: indent)
29
+ get_many_code(gen, onfail, indent, unwrap, oncut, n)
30
+ else
31
+ get_one_code(gen, onfail, indent, unwrap, oncut, n)
32
+ end
33
+ end
34
+
35
+ def generate_reverse_code(gen, onsuccess, indent, unwrap, oncut: nil)
36
+ n = value&.length || 0
37
+
38
+ if n > 1
39
+ get_many_reverse_code(gen, onsuccess, indent, unwrap, oncut, n)
26
40
  else
27
- gen.write Packcr.format_code(get_one_code(gen, onfail, indent, bare, oncut, n), indent: indent)
41
+ get_one_reverse_code(gen, onsuccess, indent, unwrap, oncut, n)
28
42
  end
29
43
  end
30
44
 
data/lib/packcr/parser.rb CHANGED
@@ -1,4 +1,4 @@
1
- # A packrat parser generated by PackCR 0.1.0
1
+ # A packrat parser generated by PackCR 0.1.1
2
2
 
3
3
  class Packcr
4
4
  class Parser
@@ -4,7 +4,6 @@ use std::cell::RefCell;
4
4
  use std::collections::{HashMap, HashSet};
5
5
  use std::io::Read;
6
6
  use std::rc::Rc;
7
-
8
7
  <%- if !code(:esource).empty? -%>
9
8
 
10
9
  <%- code(:esource).each do |code| -%>
@@ -35,12 +34,10 @@ impl LrMemoTable {
35
34
  fn get(&mut self, index: usize, rule: Rule) -> &mut LrMemo {
36
35
  self.memos.get_mut(&index).unwrap().get_mut(&rule).unwrap()
37
36
  }
38
- fn has(&mut self, index: usize, rule: Rule) -> bool {
39
- let memo_opt = self.memos.get_mut(&index);
40
- if memo_opt.is_none() {
41
- return false;
42
- }
43
- memo_opt.unwrap().contains_key(&rule)
37
+ fn has(&self, index: usize, rule: Rule) -> bool {
38
+ self.memos
39
+ .get(&index)
40
+ .is_some_and(|memo_map| memo_map.contains_key(&rule))
44
41
  }
45
42
  }
46
43
 
@@ -60,21 +57,20 @@ impl LrMemo {
60
57
  }
61
58
 
62
59
  fn start_grow(&mut self) -> bool {
63
- if self.grow || self.answer.is_some() {
64
- return false;
60
+ if !self.grow && self.answer.is_none() {
61
+ self.grow = true;
62
+ true
63
+ } else {
64
+ false
65
65
  }
66
- self.answer = None;
67
- self.grow = true;
68
- true
69
66
  }
70
67
 
71
- fn start_match(&mut self, answer: Option<ThunkChunk>, offset: usize) {
68
+ fn update(&mut self, answer: Option<ThunkChunk>, offset: usize) {
72
69
  self.answer = answer.map(|c| Rc::new(RefCell::new(c)));
73
70
  self.offset = offset;
74
71
  }
75
72
 
76
- fn answer_as_deref_mut(&mut self) -> Option<Rc<RefCell<ThunkChunk>>> {
77
- self.answer.as_ref()?;
73
+ fn clone_answer(&mut self) -> Option<Rc<RefCell<ThunkChunk>>> {
78
74
  self.answer.as_ref().map(Rc::clone)
79
75
  }
80
76
  }
@@ -128,7 +124,7 @@ enum Thunk {
128
124
  Node(ThunkNode),
129
125
  }
130
126
  impl Thunk {
131
- fn do_action(&self, processor: &ThunkProcessor, value: ValueRef) {
127
+ fn do_action(&self, processor: &ThunkProcessor, value: ValueRef) -> Value {
132
128
  match self {
133
129
  Thunk::Leaf(leaf) => leaf.do_action(processor, value),
134
130
  Thunk::Node(node) => node.do_action(processor),
@@ -159,10 +155,11 @@ impl ThunkLeaf {
159
155
  }
160
156
  }
161
157
 
162
- fn do_action(&self, processor: &ThunkProcessor, mut value: ValueRef) {
158
+ fn do_action(&self, processor: &ThunkProcessor, mut value: ValueRef) -> Value {
163
159
  value.with_mut(|v| {
164
160
  processor.call_action(self.action, self, v);
165
161
  });
162
+ value.get()
166
163
  }
167
164
  <%- if use_value -%>
168
165
 
@@ -177,10 +174,12 @@ struct ThunkNode {
177
174
  value: ValueRef,
178
175
  }
179
176
  impl ThunkNode {
180
- fn do_action(&self, processor: &ThunkProcessor) {
181
- for thunk in self.thunks.borrow().iter() {
182
- thunk.do_action(processor, self.value.clone());
177
+ fn do_action(&self, processor: &ThunkProcessor) -> Value {
178
+ let mut v = 0;
179
+ for thunk in self.thunks.borrow_mut().iter_mut() {
180
+ v = thunk.do_action(processor, self.value.clone());
183
181
  }
182
+ v
184
183
  }
185
184
  }
186
185
 
@@ -241,11 +240,9 @@ impl ValueRef {
241
240
  self.values.with_mut(self.index, f);
242
241
  }
243
242
 
244
- <%- if use_value -%>
245
243
  fn get(&self) -> i32 {
246
244
  *self.values.table.borrow().get(&self.index).unwrap_or(&0)
247
245
  }
248
- <%- end -%>
249
246
  }
250
247
  impl Clone for ValueRef {
251
248
  fn clone(&self) -> Self {
@@ -262,6 +259,7 @@ struct CaptureTable {
262
259
  }
263
260
 
264
261
  type RuleSet = HashSet<Rule>;
262
+ type RuleLimit = Option<RuleSet>;
265
263
 
266
264
  type LrMemoMap = HashMap<Rule, LrMemo>;
267
265
 
@@ -308,6 +306,7 @@ struct Input {
308
306
  start_position: usize,
309
307
  position_offset: usize,
310
308
  buffer: String,
309
+ closed: bool,
311
310
  }
312
311
 
313
312
  impl Input {
@@ -317,6 +316,7 @@ impl Input {
317
316
  start_position: 0,
318
317
  position_offset: 0,
319
318
  buffer: String::new(),
319
+ closed: false,
320
320
  }
321
321
  }
322
322
 
@@ -378,7 +378,20 @@ impl Input {
378
378
 
379
379
  fn back_to(&mut self, memo: &mut LrMemo) -> Option<Rc<RefCell<ThunkChunk>>> {
380
380
  self.position_offset = memo.offset;
381
- memo.answer_as_deref_mut()
381
+ memo.clone_answer()
382
+ }
383
+ }
384
+
385
+ const NOP: Result<usize, usize> = Ok(0);
386
+ const fn throw(label: usize) -> Result<usize, usize> {
387
+ Err(label)
388
+ }
389
+
390
+ fn catch(label: usize, f: impl FnOnce() -> Result<usize, usize>) -> Result<usize, usize> {
391
+ match f() {
392
+ Ok(_) => NOP,
393
+ Err(e) if e == label => NOP,
394
+ Err(e) => throw(e),
382
395
  }
383
396
  }
384
397
 
@@ -397,49 +410,32 @@ impl <%= class_name %> {
397
410
  }
398
411
  }
399
412
 
400
- fn error(&self) -> ! {
401
- eprintln!("Syntax error");
402
- std::process::exit(1);
403
- }
404
-
405
- fn refill_buffer(&mut self, num: usize) -> usize {
406
- self.input.refill_buffer(num)
407
- }
408
-
409
- fn commit_buffer(&mut self) {
410
- self.input.commit_buffer();
411
- self.memos.clear();
412
- }
413
+ fn parse(&mut self) -> Option<Value> {
414
+ if self.input.closed {
415
+ return None;
416
+ }
413
417
 
414
- fn parse(&mut self) -> bool {
415
418
  let mut answer = ThunkChunk::new(0);
416
419
  let pos = self.input.start_position;
417
-
418
420
  <%- if !@root.rules.empty? -%>
419
- let apply_result = self.apply_rule(
420
- Rule::<%= Packcr.camelize(@root.rules[0].name) %>,
421
- &mut answer,
422
- 0,
423
- self.input.position_offset,
424
- None,
425
- );
426
-
427
- if apply_result {
428
- if let Thunk::Node(node) = answer.thunks.borrow_mut().last().unwrap() {
429
- node.do_action(&ThunkProcessor::new(&self.input.buffer));
430
- }
431
- } else {
432
- self.error();
433
- }
434
421
 
422
+ let value = {
423
+ let node = self.rule_thunk_node(
424
+ Rule::<%= Packcr.camelize(@root.rules[0].name) %>,
425
+ &mut answer,
426
+ 0,
427
+ self.input.position_offset,
428
+ &None,
429
+ );
430
+ self.memos.clear();
431
+ node.map(|node| node.do_action(&ThunkProcessor::new(&self.input.buffer)))
432
+ };
433
+ self.input.commit_buffer();
434
+ if pos == self.input.start_position || self.input.refill_buffer(1) < 1 {
435
+ self.input.closed = true;
436
+ }
437
+ value
435
438
  <%- end -%>
436
- self.commit_buffer();
437
- pos != self.input.start_position && self.refill_buffer(1) >= 1
438
- }
439
-
440
- #[allow(dead_code)]
441
- fn get_char_as_utf32(&mut self) -> (i32, usize) {
442
- self.input.get_char_as_utf32()
443
439
  }
444
440
 
445
441
  fn grow_lr(&mut self, rule: Rule, offset: usize) {
@@ -448,16 +444,19 @@ impl <%= class_name %> {
448
444
  self.input.position_offset = offset;
449
445
 
450
446
  let answer = self.call_rule(rule, offset, Some(RuleSet::new()));
451
- if answer.is_none() || self.input.position_offset <= old_offset {
452
- return;
447
+ match answer {
448
+ Some(answer) if self.input.position_offset > old_offset => {
449
+ let memo = self.memos.get(offset, rule);
450
+ memo.update(Some(answer), self.input.position_offset);
451
+ }
452
+ _ => {
453
+ return;
454
+ }
453
455
  }
454
-
455
- let memo = self.memos.get(offset, rule);
456
- memo.start_match(answer, self.input.position_offset);
457
456
  }
458
457
  }
459
458
 
460
- fn rule_answer(&mut self, rule: Rule) -> Option<Rc<RefCell<ThunkChunk>>> {
459
+ fn rule_answer_without_limits(&mut self, rule: Rule) -> Option<Rc<RefCell<ThunkChunk>>> {
461
460
  let offset = self.input.position_offset;
462
461
  if !self.memos.has(offset, rule) {
463
462
  let memo = LrMemo::new(offset);
@@ -465,7 +464,7 @@ impl <%= class_name %> {
465
464
  let answer = self.call_rule(rule, offset, None);
466
465
 
467
466
  let memo = self.memos.get(offset, rule);
468
- memo.start_match(answer, self.input.position_offset);
467
+ memo.update(answer, self.input.position_offset);
469
468
  if !memo.grow {
470
469
  return self.input.back_to(memo);
471
470
  }
@@ -491,16 +490,13 @@ impl <%= class_name %> {
491
490
  let offset = self.input.position_offset;
492
491
  let answer = self.call_rule(rule, offset, Some(limits));
493
492
  if !self.memos.has(offset, rule) {
494
- answer.as_ref()?;
495
- return Some(Rc::new(RefCell::new(answer.unwrap())));
493
+ return answer.map(|answer| Rc::new(RefCell::new(answer)));
496
494
  }
497
- let memo = self.memos.get(offset, rule);
498
495
 
496
+ let memo = self.memos.get(offset, rule);
499
497
  if self.input.position_offset > memo.offset {
500
- memo.start_match(answer, self.input.position_offset);
501
- return memo.answer_as_deref_mut();
498
+ memo.update(answer, self.input.position_offset);
502
499
  }
503
-
504
500
  self.input.back_to(memo)
505
501
  }
506
502
 
@@ -510,35 +506,42 @@ impl <%= class_name %> {
510
506
  parent: &mut ThunkChunk,
511
507
  value_index: usize,
512
508
  offset: usize,
513
- limits: Option<RuleSet>,
509
+ limits: &RuleLimit,
514
510
  ) -> bool {
515
- let answer = match &limits {
511
+ let node = self.rule_thunk_node(rule, parent, value_index, offset, limits);
512
+ node.is_some_and(|node| {
513
+ parent.thunks.borrow_mut().push(Thunk::Node(node));
514
+ true
515
+ })
516
+ }
517
+
518
+ fn rule_thunk_node(
519
+ &mut self,
520
+ rule: Rule,
521
+ parent: &ThunkChunk,
522
+ value_index: usize,
523
+ offset: usize,
524
+ limits: &RuleLimit,
525
+ ) -> Option<ThunkNode> {
526
+ match limits {
516
527
  Some(limit_set)
517
528
  if self.input.position_offset == offset && !limit_set.contains(&rule) =>
518
529
  {
519
- self.rule_answer_with_limits(rule, limits.unwrap())
530
+ self.rule_answer_with_limits(rule, limits.clone().unwrap())
520
531
  }
521
- _ => self.rule_answer(rule),
522
- };
523
-
524
- let Some(answer) = answer else {
525
- return false;
526
- };
527
-
528
- let new_node = Thunk::Node(ThunkNode {
532
+ _ => self.rule_answer_without_limits(rule),
533
+ }
534
+ .map(|answer| ThunkNode {
529
535
  thunks: answer.borrow().thunks.clone(),
530
536
  value: parent.value_ref(value_index),
531
- });
532
- parent.thunks.borrow_mut().push(new_node);
533
-
534
- true
537
+ })
535
538
  }
536
539
 
537
540
  fn call_rule(
538
541
  &mut self,
539
542
  rule: Rule,
540
543
  offset: usize,
541
- mut limits: Option<RuleSet>,
544
+ mut limits: RuleLimit,
542
545
  ) -> Option<ThunkChunk> {
543
546
  if let Some(ref mut limits) = limits {
544
547
  limits.insert(rule);
@@ -549,7 +552,6 @@ impl <%= class_name %> {
549
552
  <%- end -%>
550
553
  }
551
554
  }
552
-
553
555
  <%- @root.rules.each do |rule| -%>
554
556
 
555
557
  <%- gen = ::Packcr::Generator.new(rule, @ascii, @location, :rs) -%>
@@ -578,7 +580,7 @@ impl<'a> ThunkProcessor<'a> {
578
580
  <%- @root.rules.each do |rule| -%>
579
581
  <%- rule.codes.each do |code| -%>
580
582
 
581
- #[allow(unused_variables,non_snake_case)]
583
+ #[allow(unused_variables, non_snake_case)]
582
584
  fn action_<%= rule.name %>_<%= code.index %>(&self, leaf: &ThunkLeaf, out: &mut i32) {
583
585
  <%- code.vars.each_with_index do |ref, i| -%>
584
586
  <%- if i == 0 -%>
@@ -1,6 +1,6 @@
1
- answer.push_leaf(
2
- Action::<%= Packcr.camelize(gen.rule.name) %><%= index %>,
3
- self.input.position_offset,
4
- &[<% vars.each_with_index do |var, i| %><%= ", " if i > 0 %><%= var.index %><% end %>],
5
- &[<% capts.each_with_index do |capt, i| %><%= ", " if i > 0 %><%= capt.index %><% end %>],
1
+ answer.push_leaf(<% -%>
2
+ <%- %>Action::<%= Packcr.camelize(gen.rule.name) %><%= index %>, <% -%>
3
+ <%- %>self.input.position_offset, <% -%>
4
+ <%- %>&[<% vars.each_with_index do |var, i| %><%= ", " if i > 0 %><%= var.index %><% end %>], <% -%>
5
+ <%- %>&[<% capts.each_with_index do |capt, i| %><%= ", " if i > 0 %><%= capt.index %><% end %>]<% -%>
6
6
  );