packcr 0.0.7 → 0.1.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/README.md +73 -0
  4. data/lib/packcr/context.rb +15 -6
  5. data/lib/packcr/generated/context.rb +290 -143
  6. data/lib/packcr/generated/node/action_node.rb +19 -2
  7. data/lib/packcr/generated/node/alternate_node.rb +54 -8
  8. data/lib/packcr/generated/node/capture_node.rb +16 -1
  9. data/lib/packcr/generated/node/charclass_node.rb +76 -9
  10. data/lib/packcr/generated/node/eof_node.rb +8 -1
  11. data/lib/packcr/generated/node/error_node.rb +9 -2
  12. data/lib/packcr/generated/node/expand_node.rb +9 -2
  13. data/lib/packcr/generated/node/predicate_node.rb +35 -2
  14. data/lib/packcr/generated/node/quantity_node.rb +84 -31
  15. data/lib/packcr/generated/node/reference_node.rb +16 -2
  16. data/lib/packcr/generated/node/rule_node.rb +38 -7
  17. data/lib/packcr/generated/node/sequence_node.rb +18 -0
  18. data/lib/packcr/generated/node/string_node.rb +28 -4
  19. data/lib/packcr/node/reference_node.rb +1 -0
  20. data/lib/packcr/node/rule_node.rb +2 -1
  21. data/lib/packcr/parser.rb +993 -838
  22. data/lib/packcr/stream.rb +1 -1
  23. data/lib/packcr/templates/context/header.c.erb +3 -3
  24. data/lib/packcr/templates/context/source.c.erb +438 -420
  25. data/lib/packcr/templates/context/source.rb.erb +185 -167
  26. data/lib/packcr/templates/context/source.rs.erb +625 -0
  27. data/lib/packcr/templates/node/action.c.erb +2 -2
  28. data/lib/packcr/templates/node/action.rs.erb +6 -0
  29. data/lib/packcr/templates/node/alternate.c.erb +2 -2
  30. data/lib/packcr/templates/node/alternate.rs.erb +39 -0
  31. data/lib/packcr/templates/node/capture.c.erb +2 -2
  32. data/lib/packcr/templates/node/capture.rs.erb +13 -0
  33. data/lib/packcr/templates/node/charclass.c.erb +4 -4
  34. data/lib/packcr/templates/node/charclass_any.c.erb +2 -2
  35. data/lib/packcr/templates/node/charclass_one.c.erb +4 -4
  36. data/lib/packcr/templates/node/charclass_utf8.c.erb +2 -2
  37. data/lib/packcr/templates/node/charclass_utf8.rs.erb +41 -0
  38. data/lib/packcr/templates/node/eof.c.erb +1 -1
  39. data/lib/packcr/templates/node/error.c.erb +4 -4
  40. data/lib/packcr/templates/node/expand.c.erb +2 -2
  41. data/lib/packcr/templates/node/predicate.c.erb +1 -1
  42. data/lib/packcr/templates/node/predicate_neg.c.erb +1 -1
  43. data/lib/packcr/templates/node/predicate_neg.rs.erb +24 -0
  44. data/lib/packcr/templates/node/quantity_many.c.erb +9 -7
  45. data/lib/packcr/templates/node/quantity_many.rs.erb +50 -0
  46. data/lib/packcr/templates/node/quantity_one.c.erb +9 -7
  47. data/lib/packcr/templates/node/quantity_one.rb.erb +4 -4
  48. data/lib/packcr/templates/node/reference.c.erb +6 -6
  49. data/lib/packcr/templates/node/reference.rs.erb +3 -0
  50. data/lib/packcr/templates/node/rule.c.erb +9 -9
  51. data/lib/packcr/templates/node/rule.rs.erb +34 -0
  52. data/lib/packcr/templates/node/sequence.rs.erb +12 -0
  53. data/lib/packcr/templates/node/string_many.c.erb +2 -2
  54. data/lib/packcr/templates/node/string_many.rs.erb +10 -0
  55. data/lib/packcr/templates/node/string_one.c.erb +2 -2
  56. data/lib/packcr/templates/node/string_one.rs.erb +9 -0
  57. data/lib/packcr/util.rb +10 -1
  58. data/lib/packcr/version.rb +1 -1
  59. metadata +18 -65
@@ -0,0 +1,625 @@
1
+ /* A packrat parser generated by PackCR <%= Packcr::VERSION %> */
2
+
3
+ use std::cell::RefCell;
4
+ use std::collections::{HashMap, HashSet};
5
+ use std::io::Read;
6
+ use std::rc::Rc;
7
+
8
+ <%- if !code(:esource).empty? -%>
9
+
10
+ <%- code(:esource).each do |code| -%>
11
+ <%= stream.get_code_block(code, 0, @iname) -%>
12
+ <%- end -%>
13
+ <%- end -%>
14
+ <%- use_value = @root.rules.map {|r| r.vars.size }.max > 0 -%>
15
+
16
+ struct LrMemoTable {
17
+ memos: HashMap<usize, LrMemoMap>,
18
+ }
19
+ impl LrMemoTable {
20
+ fn new() -> Self {
21
+ Self {
22
+ memos: HashMap::new(),
23
+ }
24
+ }
25
+
26
+ fn clear(&mut self) {
27
+ self.memos.clear();
28
+ }
29
+
30
+ fn set(&mut self, index: usize, rule: Rule, memo: LrMemo) {
31
+ let memo_map = self.memos.entry(index).or_default();
32
+ memo_map.insert(rule, memo);
33
+ }
34
+
35
+ fn get(&mut self, index: usize, rule: Rule) -> &mut LrMemo {
36
+ self.memos.get_mut(&index).unwrap().get_mut(&rule).unwrap()
37
+ }
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)
44
+ }
45
+ }
46
+
47
+ struct LrMemo {
48
+ offset: usize,
49
+ answer: Option<Rc<RefCell<ThunkChunk>>>,
50
+ grow: bool,
51
+ }
52
+
53
+ impl LrMemo {
54
+ fn new(offset: usize) -> Self {
55
+ Self {
56
+ offset,
57
+ answer: None,
58
+ grow: false,
59
+ }
60
+ }
61
+
62
+ fn start_grow(&mut self) -> bool {
63
+ if self.grow || self.answer.is_some() {
64
+ return false;
65
+ }
66
+ self.answer = None;
67
+ self.grow = true;
68
+ true
69
+ }
70
+
71
+ fn start_match(&mut self, answer: Option<ThunkChunk>, offset: usize) {
72
+ self.answer = answer.map(|c| Rc::new(RefCell::new(c)));
73
+ self.offset = offset;
74
+ }
75
+
76
+ fn answer_as_deref_mut(&mut self) -> Option<Rc<RefCell<ThunkChunk>>> {
77
+ self.answer.as_ref()?;
78
+ self.answer.as_ref().map(Rc::clone)
79
+ }
80
+ }
81
+
82
+ struct ThunkChunk {
83
+ thunks: Rc<RefCell<Vec<Thunk>>>,
84
+ capts: CaptureTable,
85
+ pos: usize,
86
+ values: ValueTable,
87
+ }
88
+
89
+ impl ThunkChunk {
90
+ fn new(pos: usize) -> Self {
91
+ Self {
92
+ values: ValueTable::new(),
93
+ capts: CaptureTable::new(),
94
+ thunks: Rc::new(RefCell::new(Vec::new())),
95
+ pos,
96
+ }
97
+ }
98
+
99
+ fn push_leaf(
100
+ &self,
101
+ action: Action,
102
+ end: usize,
103
+ value_indices: &[usize],
104
+ capt_indices: &[usize],
105
+ ) {
106
+ {
107
+ let start = self.pos;
108
+ let mut value_refs = HashMap::new();
109
+ for &index in value_indices {
110
+ value_refs.insert(index, ValueRef::new(index, self.values.clone()));
111
+ }
112
+ let mut capts = HashMap::new();
113
+ for &index in capt_indices {
114
+ capts.insert(index, self.capts[index].clone());
115
+ }
116
+ let leaf = Thunk::Leaf(ThunkLeaf::new(action, start, end, value_refs, capts));
117
+ self.thunks.borrow_mut().push(leaf);
118
+ }
119
+ }
120
+
121
+ fn value_ref(&self, index: usize) -> ValueRef {
122
+ ValueRef::new(index, self.values.clone())
123
+ }
124
+ }
125
+
126
+ enum Thunk {
127
+ Leaf(ThunkLeaf),
128
+ Node(ThunkNode),
129
+ }
130
+ impl Thunk {
131
+ fn do_action(&self, processor: &ThunkProcessor, value: ValueRef) {
132
+ match self {
133
+ Thunk::Leaf(leaf) => leaf.do_action(processor, value),
134
+ Thunk::Node(node) => node.do_action(processor),
135
+ }
136
+ }
137
+ }
138
+
139
+ #[allow(dead_code)]
140
+ struct ThunkLeaf {
141
+ value_refs: HashMap<usize, ValueRef>,
142
+ capts: HashMap<usize, Capture>,
143
+ capt0: Capture,
144
+ action: Action,
145
+ }
146
+ impl ThunkLeaf {
147
+ fn new(
148
+ action: Action,
149
+ start: usize,
150
+ end: usize,
151
+ value_refs: HashMap<usize, ValueRef>,
152
+ capts: HashMap<usize, Capture>,
153
+ ) -> Self {
154
+ Self {
155
+ value_refs,
156
+ capts,
157
+ capt0: Capture { start, end },
158
+ action,
159
+ }
160
+ }
161
+
162
+ fn do_action(&self, processor: &ThunkProcessor, mut value: ValueRef) {
163
+ value.with_mut(|v| {
164
+ processor.call_action(self.action, self, v);
165
+ });
166
+ }
167
+ <%- if use_value -%>
168
+
169
+ fn values(&self) -> HashMap<usize, Value> {
170
+ self.value_refs.iter().map(|(k, v)| (*k, v.get())).collect()
171
+ }
172
+ <%- end -%>
173
+ }
174
+
175
+ struct ThunkNode {
176
+ thunks: Rc<RefCell<Vec<Thunk>>>,
177
+ value: ValueRef,
178
+ }
179
+ 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());
183
+ }
184
+ }
185
+ }
186
+
187
+ #[derive(Clone)]
188
+ struct Capture {
189
+ start: usize,
190
+ end: usize,
191
+ }
192
+
193
+ type Value = i32;
194
+
195
+ struct ValueTable {
196
+ table: Rc<RefCell<HashMap<usize, Value>>>,
197
+ }
198
+ impl ValueTable {
199
+ fn new() -> Self {
200
+ Self {
201
+ table: Rc::new(RefCell::new(HashMap::new())),
202
+ }
203
+ }
204
+ <%- if use_value -%>
205
+
206
+ fn clear(&mut self) {
207
+ self.table.borrow_mut().clear();
208
+ }
209
+ <%- end -%>
210
+
211
+ fn with_mut<F>(&mut self, index: usize, f: F)
212
+ where
213
+ F: FnOnce(&mut Value),
214
+ {
215
+ let mut table = self.table.borrow_mut();
216
+ let value = table.entry(index).or_insert(0);
217
+ f(value);
218
+ }
219
+ }
220
+ impl Clone for ValueTable {
221
+ fn clone(&self) -> Self {
222
+ Self {
223
+ table: self.table.clone(),
224
+ }
225
+ }
226
+ }
227
+
228
+ struct ValueRef {
229
+ values: ValueTable,
230
+ index: usize,
231
+ }
232
+ impl ValueRef {
233
+ fn new(index: usize, values: ValueTable) -> Self {
234
+ Self { index, values }
235
+ }
236
+
237
+ fn with_mut<F>(&mut self, f: F)
238
+ where
239
+ F: FnOnce(&mut i32),
240
+ {
241
+ self.values.with_mut(self.index, f);
242
+ }
243
+
244
+ <%- if use_value -%>
245
+ fn get(&self) -> i32 {
246
+ *self.values.table.borrow().get(&self.index).unwrap_or(&0)
247
+ }
248
+ <%- end -%>
249
+ }
250
+ impl Clone for ValueRef {
251
+ fn clone(&self) -> Self {
252
+ Self {
253
+ index: self.index,
254
+ values: self.values.clone(),
255
+ }
256
+ }
257
+ }
258
+
259
+ struct CaptureTable {
260
+ table: HashMap<usize, Capture>,
261
+ len: usize,
262
+ }
263
+
264
+ type RuleSet = HashSet<Rule>;
265
+
266
+ type LrMemoMap = HashMap<Rule, LrMemo>;
267
+
268
+ impl CaptureTable {
269
+ fn new() -> Self {
270
+ Self {
271
+ table: HashMap::new(),
272
+ len: 0,
273
+ }
274
+ }
275
+
276
+ fn resize(&mut self, len: usize) {
277
+ let current_len = self.len;
278
+ if len > current_len {
279
+ for i in current_len..len {
280
+ self.table.insert(i, Capture { start: 0, end: 0 });
281
+ }
282
+ } else if len < current_len {
283
+ for i in len..current_len {
284
+ self.table.remove(&i);
285
+ }
286
+ }
287
+ self.len = len;
288
+ }
289
+ }
290
+ impl std::ops::Index<usize> for CaptureTable {
291
+ type Output = Capture;
292
+
293
+ fn index(&self, index: usize) -> &Self::Output {
294
+ &self.table[&index]
295
+ }
296
+ }
297
+ impl std::ops::IndexMut<usize> for CaptureTable {
298
+ fn index_mut(&mut self, index: usize) -> &mut Self::Output {
299
+ if self.len <= index {
300
+ self.resize(index + 1);
301
+ }
302
+ self.table.get_mut(&index).unwrap()
303
+ }
304
+ }
305
+
306
+ struct Input {
307
+ input: Box<dyn std::io::Read>,
308
+ start_position: usize,
309
+ position_offset: usize,
310
+ buffer: String,
311
+ }
312
+
313
+ impl Input {
314
+ fn new(input: impl std::io::Read + 'static) -> Self {
315
+ Self {
316
+ input: Box::new(input),
317
+ start_position: 0,
318
+ position_offset: 0,
319
+ buffer: String::new(),
320
+ }
321
+ }
322
+
323
+ fn refill_buffer(&mut self, num: usize) -> usize {
324
+ let mut len = self.buffer.len();
325
+ if len >= self.position_offset + num {
326
+ return len - self.position_offset;
327
+ }
328
+
329
+ let mut input_buffer = [0u8; 1024];
330
+
331
+ while len < self.position_offset + num {
332
+ match self.input.read(&mut input_buffer) {
333
+ Ok(0) => break,
334
+ Ok(bytes_read) => {
335
+ let s = std::string::String::from_utf8_lossy(&input_buffer[..bytes_read]);
336
+ self.buffer.push_str(&s);
337
+ }
338
+ Err(_) => break,
339
+ }
340
+ len = self.buffer.len();
341
+ }
342
+
343
+ len - self.position_offset
344
+ }
345
+
346
+ fn commit_buffer(&mut self) {
347
+ let position_offset = self.position_offset;
348
+
349
+ self.buffer.drain(..position_offset);
350
+
351
+ self.start_position += position_offset;
352
+ self.position_offset = 0;
353
+ }
354
+
355
+ #[allow(dead_code)]
356
+ fn get_char_as_utf32(&mut self) -> (i32, usize) {
357
+ if self.refill_buffer(1) < 1 {
358
+ return (0, 0);
359
+ }
360
+
361
+ let current_position = self.position_offset;
362
+ let remaining_chars: &str = &self.buffer[current_position..];
363
+
364
+ if let Some(ch) = remaining_chars.chars().next() {
365
+ let bytes_used = ch.len_utf8();
366
+
367
+ if self.refill_buffer(bytes_used) < bytes_used {
368
+ return (0, 0);
369
+ }
370
+
371
+ let utf32_value = ch as u32 as i32;
372
+
373
+ return (utf32_value, bytes_used);
374
+ }
375
+
376
+ (0, 0)
377
+ }
378
+
379
+ fn back_to(&mut self, memo: &mut LrMemo) -> Option<Rc<RefCell<ThunkChunk>>> {
380
+ self.position_offset = memo.offset;
381
+ memo.answer_as_deref_mut()
382
+ }
383
+ }
384
+
385
+ struct <%= class_name %> {
386
+ level: usize,
387
+ memos: LrMemoTable,
388
+ input: Input,
389
+ }
390
+
391
+ impl <%= class_name %> {
392
+ fn new(input: impl std::io::Read + 'static) -> Self {
393
+ Self {
394
+ level: 0,
395
+ memos: LrMemoTable::new(),
396
+ input: Input::new(input),
397
+ }
398
+ }
399
+
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
+
414
+ fn parse(&mut self) -> bool {
415
+ let mut answer = ThunkChunk::new(0);
416
+ let pos = self.input.start_position;
417
+
418
+ <%- 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
+
435
+ <%- 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
+ }
444
+
445
+ fn grow_lr(&mut self, rule: Rule, offset: usize) {
446
+ loop {
447
+ let old_offset = self.input.position_offset;
448
+ self.input.position_offset = offset;
449
+
450
+ let answer = self.call_rule(rule, offset, Some(RuleSet::new()));
451
+ if answer.is_none() || self.input.position_offset <= old_offset {
452
+ return;
453
+ }
454
+
455
+ let memo = self.memos.get(offset, rule);
456
+ memo.start_match(answer, self.input.position_offset);
457
+ }
458
+ }
459
+
460
+ fn rule_answer(&mut self, rule: Rule) -> Option<Rc<RefCell<ThunkChunk>>> {
461
+ let offset = self.input.position_offset;
462
+ if !self.memos.has(offset, rule) {
463
+ let memo = LrMemo::new(offset);
464
+ self.memos.set(offset, rule, memo);
465
+ let answer = self.call_rule(rule, offset, None);
466
+
467
+ let memo = self.memos.get(offset, rule);
468
+ memo.start_match(answer, self.input.position_offset);
469
+ if !memo.grow {
470
+ return self.input.back_to(memo);
471
+ }
472
+ self.grow_lr(rule, offset);
473
+
474
+ let memo = self.memos.get(offset, rule);
475
+ memo.grow = false;
476
+ return self.input.back_to(memo);
477
+ }
478
+
479
+ let memo = self.memos.get(offset, rule);
480
+ if memo.start_grow() {
481
+ return None;
482
+ }
483
+ self.input.back_to(memo)
484
+ }
485
+
486
+ fn rule_answer_with_limits(
487
+ &mut self,
488
+ rule: Rule,
489
+ limits: RuleSet,
490
+ ) -> Option<Rc<RefCell<ThunkChunk>>> {
491
+ let offset = self.input.position_offset;
492
+ let answer = self.call_rule(rule, offset, Some(limits));
493
+ if !self.memos.has(offset, rule) {
494
+ answer.as_ref()?;
495
+ return Some(Rc::new(RefCell::new(answer.unwrap())));
496
+ }
497
+ let memo = self.memos.get(offset, rule);
498
+
499
+ if self.input.position_offset > memo.offset {
500
+ memo.start_match(answer, self.input.position_offset);
501
+ return memo.answer_as_deref_mut();
502
+ }
503
+
504
+ self.input.back_to(memo)
505
+ }
506
+
507
+ fn apply_rule(
508
+ &mut self,
509
+ rule: Rule,
510
+ parent: &mut ThunkChunk,
511
+ value_index: usize,
512
+ offset: usize,
513
+ limits: Option<RuleSet>,
514
+ ) -> bool {
515
+ let answer = match &limits {
516
+ Some(limit_set)
517
+ if self.input.position_offset == offset && !limit_set.contains(&rule) =>
518
+ {
519
+ self.rule_answer_with_limits(rule, limits.unwrap())
520
+ }
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 {
529
+ thunks: answer.borrow().thunks.clone(),
530
+ value: parent.value_ref(value_index),
531
+ });
532
+ parent.thunks.borrow_mut().push(new_node);
533
+
534
+ true
535
+ }
536
+
537
+ fn call_rule(
538
+ &mut self,
539
+ rule: Rule,
540
+ offset: usize,
541
+ mut limits: Option<RuleSet>,
542
+ ) -> Option<ThunkChunk> {
543
+ if let Some(ref mut limits) = limits {
544
+ limits.insert(rule);
545
+ }
546
+ match rule {
547
+ <%- @root.rules.each do |rule| -%>
548
+ Rule::<%= Packcr.camelize(rule.name) %> => self.evaluate_rule_<%= rule.name %>(offset, limits),
549
+ <%- end -%>
550
+ }
551
+ }
552
+
553
+ <%- @root.rules.each do |rule| -%>
554
+
555
+ <%- gen = ::Packcr::Generator.new(rule, @ascii, @location, :rs) -%>
556
+ <%- %><%= gen.generate_code(rule, 0, 4, false) -%>
557
+ <%- end -%>
558
+ }
559
+
560
+ struct ThunkProcessor<'a> {
561
+ buffer: &'a str,
562
+ }
563
+
564
+ impl<'a> ThunkProcessor<'a> {
565
+ fn new(buffer: &'a str) -> Self {
566
+ Self { buffer }
567
+ }
568
+
569
+ fn call_action(&self, action: Action, thunk: &ThunkLeaf, value: &mut i32) {
570
+ match action {
571
+ <%- @root.rules.each do |rule| -%>
572
+ <%- rule.codes.each do |code| -%>
573
+ Action::<%= Packcr.camelize(rule.name) %><%= code.index %> => self.action_<%= rule.name %>_<%= code.index %>(thunk, value),
574
+ <%- end -%>
575
+ <%- end -%>
576
+ }
577
+ }
578
+ <%- @root.rules.each do |rule| -%>
579
+ <%- rule.codes.each do |code| -%>
580
+
581
+ #[allow(unused_variables,non_snake_case)]
582
+ fn action_<%= rule.name %>_<%= code.index %>(&self, leaf: &ThunkLeaf, out: &mut i32) {
583
+ <%- code.vars.each_with_index do |ref, i| -%>
584
+ <%- if i == 0 -%>
585
+ let values = leaf.values();
586
+ <%- end -%>
587
+ let <%= ref.var %> = values[&<%= ref.index %>];
588
+ <%- end -%>
589
+ let _0 = {
590
+ let capt = &leaf.capt0;
591
+ &self.buffer[(capt.start)..(capt.end)]
592
+ };
593
+ <%- code.capts.size.times do |i| -%>
594
+ let _<%= i + 1 %> = {
595
+ let capt = &leaf.capts[&<%= i %>];
596
+ &self.buffer[(capt.start)..(capt.end)]
597
+ };
598
+ <%- end -%>
599
+ <%= stream.get_code_block(code.code, 4, @iname) -%>
600
+ }
601
+ <%- end -%>
602
+ <%- end -%>
603
+ }
604
+
605
+ #[derive(Copy, Clone)]
606
+ enum Action {
607
+ <%- @root.rules.each do |rule| -%>
608
+ <%- rule.codes.each do |code| -%>
609
+ <%= Packcr.camelize(rule.name) %><%= code.index %>,
610
+ <%- end -%>
611
+ <%- end -%>
612
+ }
613
+
614
+ #[derive(Copy, Clone, PartialEq, Eq, Hash)]
615
+ enum Rule {
616
+ <%- @root.rules.each do |rule| -%>
617
+ <%= Packcr.camelize(rule.name) %>,
618
+ <%- end -%>
619
+ }
620
+ <%- if !code(:lsource).empty? -%>
621
+
622
+ <%- code(:lsource).each do |code| -%>
623
+ <%= stream.get_code_block(code, 0, @iname) -%>
624
+ <%- end -%>
625
+ <%- end -%>
@@ -1,5 +1,5 @@
1
1
  {
2
- pcc_thunk_t *const thunk = pcc_thunk__create_leaf(ctx->auxil, pcc_action_<%= gen.rule.name %>_<%= index %>, <%= gen.rule.vars.length %>, <%= gen.rule.capts.length %>);
2
+ packcr_thunk_t *const thunk = packcr_thunk__create_leaf(ctx->auxil, packcr_action_<%= gen.rule.name %>_<%= index %>, <%= gen.rule.vars.length %>, <%= gen.rule.capts.length %>);
3
3
  <%- vars.each do |var| -%>
4
4
  thunk->data.leaf.values.buf[<%= var.index %>] = &(chunk->values.buf[<%= var.index %>]);
5
5
  <%- end -%>
@@ -12,5 +12,5 @@
12
12
  thunk->data.leaf.capt0.range.start_loc = chunk->pos_loc;
13
13
  thunk->data.leaf.capt0.range.end_loc = ctx->position_offset_loc;
14
14
  <%- end -%>
15
- pcc_thunk_array__add(ctx->auxil, &chunk->thunks, thunk);
15
+ packcr_thunk_array__add(ctx->auxil, &chunk->thunks, thunk);
16
16
  }
@@ -0,0 +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 %>],
6
+ );
@@ -2,7 +2,7 @@
2
2
  {
3
3
  const size_t p = ctx->position_offset;
4
4
  <%- if gen.location -%>
5
- const pcc_location_t p_loc = ctx->position_offset_loc;
5
+ const packcr_location_t p_loc = ctx->position_offset_loc;
6
6
  <%- end -%>
7
7
  const size_t n = chunk->thunks.len;
8
8
  <%- nodes.each_with_index do |expr, i| -%>
@@ -25,7 +25,7 @@ L<%= format("%04d", l) %>:;
25
25
  <%- if gen.location -%>
26
26
  ctx->position_offset_loc = p_loc;
27
27
  <%- end -%>
28
- pcc_thunk_array__revert(ctx->auxil, &chunk->thunks, n);
28
+ packcr_thunk_array__revert(ctx->auxil, &chunk->thunks, n);
29
29
  <%- if !c -%>
30
30
  goto L<%= format("%04d", onfail) %>;
31
31
  <%- end -%>
@@ -0,0 +1,39 @@
1
+ <%- m = gen.next_label -%>
2
+ 'L<%= format("%04d", m) %>: {
3
+ let p = self.input.position_offset;
4
+ <%- if gen.location -%>
5
+ TODO
6
+ <%- end -%>
7
+ <%- nodes.each_with_index do |expr, i| -%>
8
+ {
9
+ <%- c = i + 1 < nodes.length -%>
10
+ <%- if expr.reversible?(gen) -%>
11
+ <%- %><%= gen.generate_code(expr, m, 8, false, reverse: true, oncut: onfail) -%>
12
+ <%- else -%>
13
+ <%- l = gen.next_label -%>
14
+ 'L<%= format("%04d", l) %>: {
15
+ <%- r = expr.reachability -%>
16
+ <%- %><%= gen.generate_code(expr, l, 12, false, oncut: onfail) -%>
17
+ <%- if r == Packcr::CODE_REACH__ALWAYS_SUCCEED -%>
18
+ <%- if c -%>
19
+ // unreachable codes omitted
20
+ <%- end -%>
21
+ }
22
+ <%- break -%>
23
+ <%- else -%>
24
+ <%- if r == Packcr::CODE_REACH__BOTH -%>
25
+ break 'L<%= format("%04d", m) %>;
26
+ <%- end -%>
27
+ <%- end -%>
28
+ }
29
+ <%- end -%>
30
+ }
31
+ self.input.position_offset = p;
32
+ <%- if gen.location -%>
33
+ TODO
34
+ <%- end -%>
35
+ <%- if !c -%>
36
+ break 'L<%= format("%04d", onfail) %>;
37
+ <%- end -%>
38
+ <%- end -%>
39
+ } // 'L<%= format("%04d", m) %>
@@ -2,8 +2,8 @@
2
2
  const size_t p = ctx->position_offset;
3
3
  size_t q;
4
4
  <%- if gen.location -%>
5
- pcc_location_t p_loc = ctx->position_offset_loc;
6
- pcc_location_t q_loc;
5
+ packcr_location_t p_loc = ctx->position_offset_loc;
6
+ packcr_location_t q_loc;
7
7
  <%- end -%>
8
8
  <%= gen.generate_code(expr, onfail, 4, false) -%>
9
9
  q = ctx->position_offset;