packcr 0.0.3 → 0.0.6

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/exe/packcr +3 -0
  3. data/lib/packcr/broadcast.rb +17 -0
  4. data/lib/packcr/cli.rb +25 -0
  5. data/lib/packcr/code_block.rb +2 -3
  6. data/lib/packcr/context.rb +58 -872
  7. data/lib/packcr/generator.rb +13 -10
  8. data/lib/packcr/node/action_node.rb +20 -5
  9. data/lib/packcr/node/alternate_node.rb +27 -14
  10. data/lib/packcr/node/capture_node.rb +22 -8
  11. data/lib/packcr/node/charclass_node.rb +41 -13
  12. data/lib/packcr/node/eof_node.rb +23 -0
  13. data/lib/packcr/node/error_node.rb +29 -11
  14. data/lib/packcr/node/expand_node.rb +14 -4
  15. data/lib/packcr/node/predicate_node.rb +19 -23
  16. data/lib/packcr/node/quantity_node.rb +28 -18
  17. data/lib/packcr/node/reference_node.rb +43 -5
  18. data/lib/packcr/node/root_node.rb +60 -0
  19. data/lib/packcr/node/rule_node.rb +38 -3
  20. data/lib/packcr/node/sequence_node.rb +51 -31
  21. data/lib/packcr/node/string_node.rb +16 -12
  22. data/lib/packcr/node.rb +48 -0
  23. data/lib/packcr/parser.rb +4570 -0
  24. data/lib/packcr/stream.rb +9 -13
  25. data/lib/packcr/templates/context/header.c.erb +29 -0
  26. data/lib/packcr/templates/context/source.c.erb +1292 -0
  27. data/lib/packcr/templates/context/source.rb.erb +406 -0
  28. data/lib/packcr/templates/node/action.c.erb +16 -0
  29. data/lib/packcr/templates/node/action.rb.erb +21 -0
  30. data/lib/packcr/templates/node/alternate.c.erb +34 -0
  31. data/lib/packcr/templates/node/alternate.rb.erb +40 -0
  32. data/lib/packcr/templates/node/capture.c.erb +17 -0
  33. data/lib/packcr/templates/node/capture.rb.erb +14 -0
  34. data/lib/packcr/templates/node/charclass.c.erb +47 -0
  35. data/lib/packcr/templates/node/charclass.rb.erb +49 -0
  36. data/lib/packcr/templates/node/charclass_any.c.erb +5 -0
  37. data/lib/packcr/templates/node/charclass_any.rb.erb +7 -0
  38. data/lib/packcr/templates/node/charclass_fail.c.erb +1 -0
  39. data/lib/packcr/templates/node/charclass_fail.rb.erb +1 -0
  40. data/lib/packcr/templates/node/charclass_one.c.erb +19 -0
  41. data/lib/packcr/templates/node/charclass_one.rb.erb +23 -0
  42. data/lib/packcr/templates/node/charclass_utf8.c.erb +49 -0
  43. data/lib/packcr/templates/node/charclass_utf8.rb.erb +50 -0
  44. data/lib/packcr/templates/node/charclass_utf8_reverse.rb.erb +51 -0
  45. data/lib/packcr/templates/node/eof.c.erb +1 -0
  46. data/lib/packcr/templates/node/eof.rb.erb +3 -0
  47. data/lib/packcr/templates/node/error.c.erb +28 -0
  48. data/lib/packcr/templates/node/error.rb.erb +34 -0
  49. data/lib/packcr/templates/node/expand.c.erb +16 -0
  50. data/lib/packcr/templates/node/expand.rb.erb +16 -0
  51. data/lib/packcr/templates/node/predicate.c.erb +30 -0
  52. data/lib/packcr/templates/node/predicate.rb.erb +28 -0
  53. data/lib/packcr/templates/node/predicate_neg.c.erb +23 -0
  54. data/lib/packcr/templates/node/predicate_neg.rb.erb +22 -0
  55. data/lib/packcr/templates/node/quantify_many.c.erb +45 -0
  56. data/lib/packcr/templates/node/quantify_many.rb.erb +47 -0
  57. data/lib/packcr/templates/node/quantify_one.c.erb +21 -0
  58. data/lib/packcr/templates/node/quantify_one.rb.erb +23 -0
  59. data/lib/packcr/templates/node/reference.c.erb +5 -0
  60. data/lib/packcr/templates/node/reference.rb.erb +9 -0
  61. data/lib/packcr/templates/node/reference_reverse.rb.erb +9 -0
  62. data/lib/packcr/templates/node/rule.c.erb +19 -0
  63. data/lib/packcr/templates/node/rule.rb.erb +23 -0
  64. data/lib/packcr/templates/node/sequence.c.erb +12 -0
  65. data/lib/packcr/templates/node/sequence.rb.erb +12 -0
  66. data/lib/packcr/templates/node/string_many.c.erb +11 -0
  67. data/lib/packcr/templates/node/string_many.rb.erb +10 -0
  68. data/lib/packcr/templates/node/string_one.c.erb +8 -0
  69. data/lib/packcr/templates/node/string_one.rb.erb +10 -0
  70. data/lib/packcr/tokenizer.rb +2948 -0
  71. data/lib/packcr/util.rb +3 -8
  72. data/lib/packcr/version.rb +1 -1
  73. data/lib/packcr.rb +1 -2
  74. metadata +88 -8
  75. data/lib/packcr/buffer.rb +0 -47
@@ -1,7 +1,6 @@
1
-
2
1
  class Packcr
3
2
  class Generator
4
- attr_reader :ascii, :rule, :location, :lang
3
+ attr_reader :ascii, :rule, :location, :lang, :level
5
4
 
6
5
  def initialize(rule, ascii, location, lang = :c)
7
6
  @rule = rule
@@ -9,27 +8,31 @@ class Packcr
9
8
  @ascii = !!ascii
10
9
  @location = !!location
11
10
  @lang = lang
11
+ @level = 0
12
12
  end
13
13
 
14
14
  def next_label
15
15
  @label += 1
16
16
  end
17
17
 
18
- def generate_code(node, onfail, indent, bare)
19
- node.generate_code(self, onfail, indent, bare)
20
- end
21
-
22
- def generate_code_str(node, onfail, indent, bare)
23
- @stream, stream = StringIO.new, @stream
18
+ def generate_code(node, onescape, indent, bare, reverse: false, oncut: nil)
19
+ @stream, stream = +"", @stream
20
+ @level += 1
24
21
  begin
25
- return generate_code(node, onfail, indent, bare), @stream.string
22
+ if reverse
23
+ node.generate_reverse_code(self, onescape, indent, bare, oncut: oncut)
24
+ else
25
+ node.generate_code(self, onescape, indent, bare, oncut: oncut)
26
+ end
27
+ @stream
26
28
  ensure
29
+ @level -= 1
27
30
  @stream = stream
28
31
  end
29
32
  end
30
33
 
31
34
  def write(str)
32
- @stream.write(str)
35
+ @stream << str
33
36
  end
34
37
  end
35
38
  end
@@ -3,8 +3,9 @@ class Packcr
3
3
  class ActionNode < Packcr::Node
4
4
  attr_accessor :code, :index, :vars, :capts
5
5
 
6
- def initialize
7
- super
6
+ def initialize(code = nil)
7
+ super()
8
+ @code = code
8
9
  self.vars = []
9
10
  self.capts = []
10
11
  end
@@ -32,9 +33,12 @@ class Packcr
32
33
  end
33
34
  end
34
35
 
35
- def generate_code(gen, onfail, indent, bare)
36
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
36
37
  gen.write Packcr.template("node/action.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
37
- return Packcr::CODE_REACH__ALWAYS_SUCCEED
38
+ end
39
+
40
+ def reachability
41
+ Packcr::CODE_REACH__ALWAYS_SUCCEED
38
42
  end
39
43
 
40
44
  def verify_variables(vars)
@@ -45,7 +49,18 @@ class Packcr
45
49
  @capts = capts
46
50
  end
47
51
 
48
- def link_references(ctx)
52
+ def setup_rule(rule)
53
+ @index = rule.codes.length
54
+ rule.codes.push(self)
55
+ end
56
+
57
+ def to_h
58
+ {
59
+ type: :action,
60
+ code: code&.text,
61
+ vars: vars&.map(&:to_h),
62
+ capts: capts&.map(&:to_h),
63
+ }
49
64
  end
50
65
  end
51
66
  end
@@ -3,9 +3,14 @@ class Packcr
3
3
  class AlternateNode < Packcr::Node
4
4
  attr_accessor :nodes
5
5
 
6
- def initialize
7
- super
8
- self.nodes = []
6
+ def initialize(*nodes)
7
+ super()
8
+ self.nodes = nodes
9
+ end
10
+
11
+ def alt(node)
12
+ @nodes << node if node
13
+ self
9
14
  end
10
15
 
11
16
  def debug_dump(indent = 0)
@@ -22,14 +27,21 @@ class Packcr
22
27
  m
23
28
  end
24
29
 
25
- def generate_code(gen, onfail, indent, bare)
26
- b = false
27
- m = gen.next_label
28
-
29
- reach = nil
30
- gen.write Packcr.template("node/alternate.#{gen.lang}.erb", binding, indent: indent - 4, unwrap: bare)
30
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
31
+ gen.write Packcr.template("node/alternate.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
32
+ end
31
33
 
32
- reach || Packcr::CODE_REACH__ALWAYS_FAIL
34
+ def reachability
35
+ r = Packcr::CODE_REACH__ALWAYS_FAIL
36
+ nodes.each do |expr|
37
+ case expr.reachability
38
+ when Packcr::CODE_REACH__ALWAYS_SUCCEED
39
+ return Packcr::CODE_REACH__ALWAYS_SUCCEED
40
+ when Packcr::CODE_REACH__BOTH
41
+ r = Packcr::CODE_REACH__BOTH
42
+ end
43
+ end
44
+ r
33
45
  end
34
46
 
35
47
  def verify_variables(vars)
@@ -61,10 +73,11 @@ class Packcr
61
73
  end
62
74
  end
63
75
 
64
- def link_references(ctx)
65
- nodes.each do |node|
66
- node.link_references(ctx)
67
- end
76
+ def to_h
77
+ {
78
+ type: :alternate,
79
+ nodes: nodes&.map(&:to_h),
80
+ }
68
81
  end
69
82
  end
70
83
  end
@@ -3,6 +3,10 @@ class Packcr
3
3
  class CaptureNode < Packcr::Node
4
4
  attr_accessor :expr, :index
5
5
 
6
+ def initialize(expr = nil)
7
+ @expr = expr
8
+ end
9
+
6
10
  def debug_dump(indent = 0)
7
11
  $stdout.print "#{" " * indent}Capture(index:"
8
12
  Packcr.dump_integer_value(index)
@@ -11,23 +15,33 @@ class Packcr
11
15
  $stdout.print "#{" " * indent}}\n"
12
16
  end
13
17
 
14
- def generate_code(gen, onfail, indent, bare)
15
- r = nil
18
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
16
19
  gen.write Packcr.template("node/capture.#{gen.lang}.erb", binding, indent: indent)
17
- return r
18
20
  end
19
21
 
20
- def verify_variables(vars)
21
- expr.verify_variables(vars)
22
+ def reachability
23
+ expr.reachability
22
24
  end
23
25
 
24
26
  def verify_captures(ctx, capts)
25
- expr.verify_captures(ctx, capts)
27
+ super
26
28
  capts.push(self)
27
29
  end
28
30
 
29
- def link_references(ctx)
30
- expr.link_references(ctx)
31
+ def nodes
32
+ [expr]
33
+ end
34
+
35
+ def setup_rule(rule)
36
+ @index = rule.capts.length
37
+ rule.capts << self
38
+ end
39
+
40
+ def to_h
41
+ {
42
+ type: :capture,
43
+ expr: expr&.to_h,
44
+ }
31
45
  end
32
46
  end
33
47
  end
@@ -3,13 +3,21 @@ class Packcr
3
3
  class CharclassNode < Packcr::Node
4
4
  attr_accessor :value
5
5
 
6
+ def initialize(value = nil)
7
+ @value = value
8
+ end
9
+
6
10
  def debug_dump(indent = 0)
7
11
  $stdout.print "#{" " * indent}Charclass(value:'"
8
12
  Packcr.dump_escaped_string(value)
9
13
  $stdout.print "')\n"
10
14
  end
11
15
 
12
- def generate_code(gen, onfail, indent, bare)
16
+ def reversible?(gen)
17
+ gen.lang == :rb && !gen.ascii
18
+ end
19
+
20
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
13
21
  if gen.ascii
14
22
  return generate_ascii_code(gen, onfail, indent, bare)
15
23
  else
@@ -17,13 +25,22 @@ class Packcr
17
25
  end
18
26
  end
19
27
 
20
- def verify_variables(vars)
21
- end
22
-
23
- def verify_captures(ctx, capts)
28
+ def generate_reverse_code(gen, onsuccess, indent, bare, oncut: nil)
29
+ if gen.ascii
30
+ raise "unexpected"
31
+ else
32
+ return generate_utf8_charclass_reverse_code(gen, onsuccess, indent, bare)
33
+ end
24
34
  end
25
35
 
26
- def link_references(ctx)
36
+ def reachability
37
+ charclass = self.value
38
+ n = charclass&.length || 0
39
+ if charclass.nil? || n > 0
40
+ return Packcr::CODE_REACH__BOTH
41
+ else
42
+ return Packcr::CODE_REACH__ALWAYS_FAIL
43
+ end
27
44
  end
28
45
 
29
46
  private
@@ -35,13 +52,20 @@ class Packcr
35
52
  end
36
53
  n = charclass&.length || 0
37
54
  if charclass.nil? || n > 0
38
- a = charclass && charclass[0] == '^'
39
- i = a ? 1 : 0
40
55
  gen.write Packcr.template("node/charclass_utf8.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
41
- return Packcr::CODE_REACH__BOTH
42
56
  else
43
57
  gen.write Packcr.template("node/charclass_fail.#{gen.lang}.erb", binding, indent: indent)
44
- return Packcr::CODE_REACH__ALWAYS_FAIL
58
+ end
59
+ end
60
+
61
+ def generate_utf8_charclass_reverse_code(gen, onsuccess, indent, bare)
62
+ charclass = self.value
63
+ if charclass && charclass.encoding != Encoding::UTF_8
64
+ charclass = charclass.dup.force_encoding(Encoding::UTF_8)
65
+ end
66
+ n = charclass&.length || 0
67
+ if charclass.nil? || n > 0
68
+ gen.write Packcr.template("node/charclass_utf8_reverse.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
45
69
  end
46
70
  end
47
71
 
@@ -60,16 +84,20 @@ class Packcr
60
84
  else
61
85
  gen.write Packcr.template("node/charclass_one.#{gen.lang}.erb", binding, indent: indent)
62
86
  end
63
- return Packcr::CODE_REACH__BOTH
64
87
  else
65
88
  gen.write Packcr.template("node/charclass_fail.#{gen.lang}.erb", binding, indent: indent)
66
- return Packcr::CODE_REACH__ALWAYS_FAIL
67
89
  end
68
90
  else
69
91
  gen.write Packcr.template("node/charclass_any.#{gen.lang}.erb", binding, indent: indent)
70
- return Packcr::CODE_REACH__BOTH
71
92
  end
72
93
  end
94
+
95
+ def to_h
96
+ {
97
+ type: :charclass,
98
+ value: value,
99
+ }
100
+ end
73
101
  end
74
102
  end
75
103
  end
@@ -0,0 +1,23 @@
1
+ class Packcr
2
+ class Node
3
+ class EofNode < Packcr::Node
4
+ def debug_dump(indent = 0)
5
+ $stdout.print "#{" " * indent}Eof()\n"
6
+ end
7
+
8
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
9
+ gen.write Packcr.template("node/eof.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
10
+ end
11
+
12
+ def reachability
13
+ return Packcr::CODE_REACH__BOTH
14
+ end
15
+
16
+ def to_h
17
+ {
18
+ type: :eof,
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,8 +3,11 @@ class Packcr
3
3
  class ErrorNode < Packcr::Node
4
4
  attr_accessor :expr, :code, :index, :vars, :capts
5
5
 
6
- def initialize
7
- super
6
+ def initialize(expr = nil, code = nil, index = nil)
7
+ super()
8
+ @expr = expr
9
+ @code = code
10
+ @index = index
8
11
  self.vars = []
9
12
  self.capts = []
10
13
  end
@@ -26,26 +29,41 @@ class Packcr
26
29
  $stdout.print "#{" " * indent}}\n"
27
30
  end
28
31
 
29
- def generate_code(gen, onfail, indent, bare)
30
- l = gen.next_label
31
- m = gen.next_label
32
- r, code = gen.generate_code_str(expr, l, 4, true)
32
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
33
33
  gen.write Packcr.template("node/error.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
34
- return r
34
+ end
35
+
36
+ def reachability
37
+ expr.reachability
35
38
  end
36
39
 
37
40
  def verify_variables(vars)
38
41
  @vars = vars
39
- expr.verify_variables(vars)
42
+ super
40
43
  end
41
44
 
42
45
  def verify_captures(ctx, capts)
43
46
  @capts = capts
44
- expr.verify_captures(ctx, capts)
47
+ super
48
+ end
49
+
50
+ def nodes
51
+ [expr]
52
+ end
53
+
54
+ def setup_rule(rule)
55
+ @index = rule.codes.length
56
+ rule.codes.push(self)
45
57
  end
46
58
 
47
- def link_references(ctx)
48
- expr.link_references(ctx)
59
+ def to_h
60
+ {
61
+ type: :error,
62
+ code: code&.text,
63
+ vars: vars&.map(&:to_h),
64
+ capts: capts&.map(&:to_h),
65
+ index: @index,
66
+ }
49
67
  end
50
68
  end
51
69
  end
@@ -3,18 +3,24 @@ class Packcr
3
3
  class ExpandNode < Packcr::Node
4
4
  attr_accessor :index, :line, :col
5
5
 
6
+ def initialize(index = nil, line = nil, col = nil)
7
+ @index = index
8
+ @line = line
9
+ @col = col
10
+ end
11
+
6
12
  def debug_dump(indent = 0)
7
13
  $stdout.print "#{" " * indent}Expand(index:"
8
14
  Packcr.dump_integer_value(index)
9
15
  $stdout.print ")\n"
10
16
  end
11
17
 
12
- def generate_code(gen, onfail, indent, bare)
18
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
13
19
  gen.write Packcr.template("node/expand.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
14
- return Packcr::CODE_REACH__BOTH
15
20
  end
16
21
 
17
- def verify_variables(vars)
22
+ def reachability
23
+ return Packcr::CODE_REACH__BOTH
18
24
  end
19
25
 
20
26
  def verify_captures(ctx, capts)
@@ -29,7 +35,11 @@ class Packcr
29
35
  end
30
36
  end
31
37
 
32
- def link_references(ctx)
38
+ def to_h
39
+ {
40
+ type: :expand,
41
+ index: index,
42
+ }
33
43
  end
34
44
  end
35
45
  end
@@ -3,9 +3,10 @@ class Packcr
3
3
  class PredicateNode < Packcr::Node
4
4
  attr_accessor :neg, :expr
5
5
 
6
- def initialize
7
- super
8
- self.neg = false
6
+ def initialize(expr = nil, neg = false)
7
+ super()
8
+ @expr = expr
9
+ @neg = neg
9
10
  end
10
11
 
11
12
  def debug_dump(indent = 0)
@@ -14,37 +15,32 @@ class Packcr
14
15
  $stdout.print "#{" " * indent}}\n"
15
16
  end
16
17
 
17
- def generate_code(gen, onfail, indent, bare)
18
- r = nil
18
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
19
19
  if neg
20
- l = gen.next_label
21
- r, code = gen.generate_code_str(expr, l, 4, false)
22
20
  gen.write Packcr.template("node/predicate_neg.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
23
- case r
24
- when Packcr::CODE_REACH__ALWAYS_SUCCEED
25
- r = Packcr::CODE_REACH__ALWAYS_FAIL
26
- when Packcr::CODE_REACH__ALWAYS_FAIL
27
- r = Packcr::CODE_REACH__ALWAYS_SUCCEED
28
- end
29
21
  else
30
- l = gen.next_label
31
- m = gen.next_label
32
- r, code = gen.generate_code_str(expr, l, 4, false)
33
22
  gen.write Packcr.template("node/predicate.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
34
23
  end
35
- return r
36
24
  end
37
25
 
38
- def verify_variables(vars)
39
- expr.verify_variables(vars)
26
+ def reachability
27
+ if neg
28
+ -expr.reachability
29
+ else
30
+ expr.reachability
31
+ end
40
32
  end
41
33
 
42
- def verify_captures(ctx, capts)
43
- expr.verify_captures(ctx, capts)
34
+ def nodes
35
+ [expr]
44
36
  end
45
37
 
46
- def link_references(ctx)
47
- expr.link_references(ctx)
38
+ def to_h
39
+ {
40
+ type: :predicate,
41
+ expr: expr&.to_h,
42
+ neg: neg,
43
+ }
48
44
  end
49
45
  end
50
46
  end
@@ -3,10 +3,11 @@ class Packcr
3
3
  class QuantityNode < Packcr::Node
4
4
  attr_accessor :min, :max, :expr
5
5
 
6
- def initialize
7
- super
8
- self.min = 0
9
- self.max = 0
6
+ def initialize(expr = nil, min = 0, max = 0)
7
+ super()
8
+ @expr = expr
9
+ @min = min
10
+ @max = max
10
11
  end
11
12
 
12
13
  def debug_dump(indent = 0)
@@ -15,40 +16,49 @@ class Packcr
15
16
  $stdout.print "#{" " * indent}}\n"
16
17
  end
17
18
 
18
- def generate_code(gen, onfail, indent, bare)
19
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
19
20
  if max > 1 || max < 0
20
- r = nil
21
21
  gen.write Packcr.template("node/quantify_many.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
22
+ elsif max == 1
23
+ if min > 0
24
+ gen.write gen.generate_code(expr, onfail, indent, bare)
25
+ else
26
+ gen.write Packcr.template("node/quantify_one.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
27
+ end
28
+ end
29
+ end
30
+
31
+ def reachability
32
+ if max > 1 || max < 0
22
33
  if min <= 0
23
34
  return Packcr::CODE_REACH__ALWAYS_SUCCEED
24
35
  end
25
- if r == Packcr::CODE_REACH__ALWAYS_FAIL
36
+ if expr.reachability == Packcr::CODE_REACH__ALWAYS_FAIL
26
37
  return Packcr::CODE_REACH__ALWAYS_FAIL
27
38
  end
28
39
  return Packcr::CODE_REACH__BOTH
29
40
  elsif max == 1
30
41
  if min > 0
31
- return gen.generate_code(expr, onfail, indent, bare)
42
+ return expr.reachability
32
43
  else
33
- gen.write Packcr.template("node/quantify_one.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
34
44
  return Packcr::CODE_REACH__ALWAYS_SUCCEED
35
45
  end
36
46
  else
37
- # no code to generate
38
47
  return Packcr::CODE_REACH__ALWAYS_SUCCEED
39
48
  end
40
49
  end
41
50
 
42
- def verify_variables(vars)
43
- expr.verify_variables(vars)
44
- end
45
-
46
- def verify_captures(ctx, capts)
47
- expr.verify_captures(ctx, capts)
51
+ def nodes
52
+ [expr]
48
53
  end
49
54
 
50
- def link_references(ctx)
51
- expr.link_references(ctx)
55
+ def to_h
56
+ {
57
+ type: :predicate,
58
+ expr: expr&.to_h,
59
+ min: min,
60
+ max: max,
61
+ }
52
62
  end
53
63
  end
54
64
  end
@@ -3,17 +3,50 @@ class Packcr
3
3
  class ReferenceNode < Packcr::Node
4
4
  attr_accessor :var, :index, :name, :rule, :line, :col
5
5
 
6
+ def initialize(name = nil, var = nil, line = nil, col = nil)
7
+ @name = name
8
+ @var = var
9
+ @line = line
10
+ @col = col
11
+ end
12
+
6
13
  def debug_dump(indent = 0)
7
14
  $stdout.print "#{" " * indent}Reference(var:'#{var || "(null)"}', index:"
8
15
  Packcr.dump_integer_value(index)
9
16
  $stdout.print ", name:'#{name}', rule:'#{rule&.name || "(null)"}')\n"
10
17
  end
11
18
 
12
- def generate_code(gen, onfail, indent, bare)
19
+ def reversible?(gen)
20
+ gen.lang == :rb
21
+ end
22
+
23
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
13
24
  gen.write Packcr.template("node/reference.#{gen.lang}.erb", binding, indent: indent)
25
+ end
26
+
27
+ def generate_reverse_code(gen, onsuccess, indent, bare, oncut: nil)
28
+ gen.write Packcr.template("node/reference_reverse.#{gen.lang}.erb", binding, indent: indent)
29
+ end
30
+
31
+ def reachability
14
32
  Packcr::CODE_REACH__BOTH
15
33
  end
16
34
 
35
+ def setup_rule(rule)
36
+ return unless var
37
+ i = rule.vars.index do |ref|
38
+ unless ref.is_a?(Packcr::Node::ReferenceNode)
39
+ raise "Unexpected node type: #{ref.class}"
40
+ end
41
+ var == ref.var
42
+ end
43
+ if !i
44
+ i = rule.vars.length
45
+ rule.vars << self
46
+ end
47
+ @index = i
48
+ end
49
+
17
50
  def verify_variables(vars)
18
51
  return if index.nil?
19
52
 
@@ -26,11 +59,8 @@ class Packcr
26
59
  vars.push(self) if !found
27
60
  end
28
61
 
29
- def verify_captures(ctx, capts)
30
- end
31
-
32
62
  def link_references(ctx)
33
- rule = ctx.rule(name)
63
+ rule = ctx.root.rule(name)
34
64
  if !rule
35
65
  ctx.error line + 1, col + 1, "No definition of rule '#{name}'"
36
66
  else
@@ -41,6 +71,14 @@ class Packcr
41
71
  self.rule = rule
42
72
  end
43
73
  end
74
+
75
+ def to_h
76
+ {
77
+ type: :reference,
78
+ name: name,
79
+ var: var,
80
+ }
81
+ end
44
82
  end
45
83
  end
46
84
  end