packcr 0.0.4 → 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 +59 -56
  7. data/lib/packcr/generator.rb +13 -11
  8. data/lib/packcr/node/action_node.rb +14 -5
  9. data/lib/packcr/node/alternate_node.rb +20 -12
  10. data/lib/packcr/node/capture_node.rb +11 -11
  11. data/lib/packcr/node/charclass_node.rb +37 -13
  12. data/lib/packcr/node/eof_node.rb +23 -0
  13. data/lib/packcr/node/error_node.rb +17 -12
  14. data/lib/packcr/node/expand_node.rb +11 -5
  15. data/lib/packcr/node/predicate_node.rb +15 -24
  16. data/lib/packcr/node/quantity_node.rb +23 -18
  17. data/lib/packcr/node/reference_node.rb +21 -5
  18. data/lib/packcr/node/root_node.rb +60 -0
  19. data/lib/packcr/node/rule_node.rb +26 -3
  20. data/lib/packcr/node/sequence_node.rb +46 -31
  21. data/lib/packcr/node/string_node.rb +12 -12
  22. data/lib/packcr/node.rb +35 -4
  23. data/lib/packcr/parser.rb +2939 -2661
  24. data/lib/packcr/stream.rb +8 -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 +0 -8
  72. data/lib/packcr/version.rb +1 -1
  73. data/lib/packcr.rb +1 -2
  74. metadata +87 -8
  75. data/lib/packcr/buffer.rb +0 -47
@@ -15,42 +15,33 @@ class Packcr
15
15
  $stdout.print "#{" " * indent}}\n"
16
16
  end
17
17
 
18
- def generate_code(gen, onfail, indent, bare)
19
- r = nil
18
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
20
19
  if neg
21
- l = gen.next_label
22
- r, code = gen.generate_code_str(expr, l, 4, false)
23
20
  gen.write Packcr.template("node/predicate_neg.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
24
- case r
25
- when Packcr::CODE_REACH__ALWAYS_SUCCEED
26
- r = Packcr::CODE_REACH__ALWAYS_FAIL
27
- when Packcr::CODE_REACH__ALWAYS_FAIL
28
- r = Packcr::CODE_REACH__ALWAYS_SUCCEED
29
- end
30
21
  else
31
- l = gen.next_label
32
- m = gen.next_label
33
- r, code = gen.generate_code_str(expr, l, 4, false)
34
22
  gen.write Packcr.template("node/predicate.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
35
23
  end
36
- return r
37
24
  end
38
25
 
39
- def verify_variables(vars)
40
- expr.verify_variables(vars)
41
- end
42
-
43
- def verify_captures(ctx, capts)
44
- expr.verify_captures(ctx, capts)
45
- end
46
-
47
- def link_references(ctx)
48
- expr.link_references(ctx)
26
+ def reachability
27
+ if neg
28
+ -expr.reachability
29
+ else
30
+ expr.reachability
31
+ end
49
32
  end
50
33
 
51
34
  def nodes
52
35
  [expr]
53
36
  end
37
+
38
+ def to_h
39
+ {
40
+ type: :predicate,
41
+ expr: expr&.to_h,
42
+ neg: neg,
43
+ }
44
+ end
54
45
  end
55
46
  end
56
47
  end
@@ -16,45 +16,50 @@ class Packcr
16
16
  $stdout.print "#{" " * indent}}\n"
17
17
  end
18
18
 
19
- def generate_code(gen, onfail, indent, bare)
19
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
20
20
  if max > 1 || max < 0
21
- r = nil
22
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
23
33
  if min <= 0
24
34
  return Packcr::CODE_REACH__ALWAYS_SUCCEED
25
35
  end
26
- if r == Packcr::CODE_REACH__ALWAYS_FAIL
36
+ if expr.reachability == Packcr::CODE_REACH__ALWAYS_FAIL
27
37
  return Packcr::CODE_REACH__ALWAYS_FAIL
28
38
  end
29
39
  return Packcr::CODE_REACH__BOTH
30
40
  elsif max == 1
31
41
  if min > 0
32
- return gen.generate_code(expr, onfail, indent, bare)
42
+ return expr.reachability
33
43
  else
34
- gen.write Packcr.template("node/quantify_one.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
35
44
  return Packcr::CODE_REACH__ALWAYS_SUCCEED
36
45
  end
37
46
  else
38
- # no code to generate
39
47
  return Packcr::CODE_REACH__ALWAYS_SUCCEED
40
48
  end
41
49
  end
42
50
 
43
- def verify_variables(vars)
44
- expr.verify_variables(vars)
45
- end
46
-
47
- def verify_captures(ctx, capts)
48
- expr.verify_captures(ctx, capts)
49
- end
50
-
51
- def link_references(ctx)
52
- expr.link_references(ctx)
53
- end
54
-
55
51
  def nodes
56
52
  [expr]
57
53
  end
54
+
55
+ def to_h
56
+ {
57
+ type: :predicate,
58
+ expr: expr&.to_h,
59
+ min: min,
60
+ max: max,
61
+ }
62
+ end
58
63
  end
59
64
  end
60
65
  end
@@ -16,8 +16,19 @@ class Packcr
16
16
  $stdout.print ", name:'#{name}', rule:'#{rule&.name || "(null)"}')\n"
17
17
  end
18
18
 
19
- 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)
20
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
21
32
  Packcr::CODE_REACH__BOTH
22
33
  end
23
34
 
@@ -48,11 +59,8 @@ class Packcr
48
59
  vars.push(self) if !found
49
60
  end
50
61
 
51
- def verify_captures(ctx, capts)
52
- end
53
-
54
62
  def link_references(ctx)
55
- rule = ctx.rule(name)
63
+ rule = ctx.root.rule(name)
56
64
  if !rule
57
65
  ctx.error line + 1, col + 1, "No definition of rule '#{name}'"
58
66
  else
@@ -63,6 +71,14 @@ class Packcr
63
71
  self.rule = rule
64
72
  end
65
73
  end
74
+
75
+ def to_h
76
+ {
77
+ type: :reference,
78
+ name: name,
79
+ var: var,
80
+ }
81
+ end
66
82
  end
67
83
  end
68
84
  end
@@ -0,0 +1,60 @@
1
+ class Packcr
2
+ class Node
3
+ class RootNode < Packcr::Node
4
+ attr_accessor :rules
5
+ attr_reader :rulehash
6
+
7
+ def initialize
8
+ @rules = []
9
+ @rulehash = {}
10
+ @implicit_rules = []
11
+ end
12
+
13
+ def debug_dump
14
+ @rules.each(&:debug_dump)
15
+ end
16
+
17
+ def make_rulehash(ctx)
18
+ @rules.each do |rule|
19
+ if @rulehash[rule.name]
20
+ ctx.error rule.line + 1, rule.col + 1, "Multiple definition of rule '#{rule.name}'"
21
+ else
22
+ @rulehash[rule.name] = rule
23
+ end
24
+ end
25
+ end
26
+
27
+ def setup(ctx)
28
+ make_rulehash(ctx)
29
+ @rules.first&.top = true
30
+ @rules.each do |rule|
31
+ rule.setup(ctx)
32
+ end
33
+ @rules.each do |rule|
34
+ rule.verify(ctx)
35
+ end
36
+ end
37
+
38
+ def rule(name)
39
+ rule = @rulehash[name]
40
+ return rule if rule
41
+ case name
42
+ when "EOF"
43
+ expr = Packcr::Node::EofNode.new
44
+ else
45
+ return nil
46
+ end
47
+ rule = Packcr::Node::RuleNode.new(expr, name)
48
+ @rules << rule
49
+ @rulehash[name] = rule
50
+ end
51
+
52
+ def to_h
53
+ {
54
+ type: :root,
55
+ rules: rules.map(&:to_h),
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,7 +1,7 @@
1
1
  class Packcr
2
2
  class Node
3
3
  class RuleNode < Packcr::Node
4
- attr_accessor :codes, :name, :expr, :ref, :vars, :capts, :line, :col
4
+ attr_accessor :codes, :name, :expr, :ref, :vars, :capts, :line, :col, :top
5
5
 
6
6
  def initialize(expr = nil, name = nil, line = nil, col = nil)
7
7
  super()
@@ -21,22 +21,45 @@ class Packcr
21
21
  $stdout.print "#{" " * indent}}\n"
22
22
  end
23
23
 
24
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
25
+ gen.write Packcr.template("node/rule.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
26
+ end
27
+
28
+ def reachability
29
+ expr.reachability
30
+ end
31
+
24
32
  def verify(ctx)
25
33
  expr.verify_variables([])
26
34
  expr.verify_captures(ctx, [])
35
+ verify_rule_reference(ctx)
36
+ end
37
+
38
+ def verify_rule_reference(ctx)
39
+ return if top
40
+ if ref == 0
41
+ ctx.error line + 1, col + 1, "Never used rule '#{name}'"
42
+ end
27
43
  end
28
44
 
29
45
  def add_ref
30
46
  @ref += 1
31
47
  end
32
48
 
33
- def setup
34
- setup_rule(self)
49
+ def setup(ctx)
50
+ super(ctx, self)
35
51
  end
36
52
 
37
53
  def nodes
38
54
  [expr]
39
55
  end
56
+
57
+ def to_h
58
+ {
59
+ type: :rule,
60
+ expr: expr&.to_h,
61
+ }
62
+ end
40
63
  end
41
64
  end
42
65
  end
@@ -3,18 +3,44 @@ class Packcr
3
3
  class SequenceNode < Packcr::Node
4
4
  attr_accessor :nodes
5
5
 
6
- def initialize(*nodes)
6
+ def initialize(*nodes, cut: false)
7
7
  super()
8
8
  self.nodes = nodes
9
+ @cut = cut
9
10
  end
10
11
 
11
- def seq(node)
12
- @nodes << node
12
+ def sequence?
13
+ true
14
+ end
15
+
16
+ def seq(node, cut: false)
17
+ if node&.sequence?
18
+ node.nodes.each do |child|
19
+ seq(child, cut: cut)
20
+ cut = false
21
+ end
22
+ return self
23
+ end
24
+
25
+ if cut
26
+ if node
27
+ node = Packcr::Node::SequenceNode.new(node, cut: true)
28
+ else
29
+ node = Packcr::Node::SequenceNode.new(cut: true)
30
+ end
31
+ end
32
+ if node
33
+ if @nodes.last.sequence?
34
+ @nodes.last.seq(node)
35
+ else
36
+ @nodes << node
37
+ end
38
+ end
13
39
  self
14
40
  end
15
41
 
16
42
  def debug_dump(indent = 0)
17
- $stdout.print "#{" " * indent}Sequence(max:#{max}, len:#{nodes.length}) {\n"
43
+ $stdout.print "#{" " * indent}Sequence(max:#{max}, len:#{nodes.length}#{@cut ? ", cut: true" : ""}) {\n"
18
44
  nodes.each do |child_node|
19
45
  child_node.debug_dump(indent + 2)
20
46
  end
@@ -27,39 +53,28 @@ class Packcr
27
53
  m
28
54
  end
29
55
 
30
- def generate_code(gen, onfail, indent, bare)
31
- b = false
32
- nodes.each_with_index do |expr, i|
33
- case gen.generate_code(expr, onfail, indent, false)
56
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
57
+ gen.write Packcr.template("node/sequence.#{gen.lang}.erb", binding, indent: indent)
58
+ end
59
+
60
+ def reachability
61
+ r = Packcr::CODE_REACH__ALWAYS_SUCCEED
62
+ nodes.each do |expr|
63
+ case expr.reachability
34
64
  when Packcr::CODE_REACH__ALWAYS_FAIL
35
- if i + 1 < nodes.length
36
- gen.write Packcr.template("node/sequence_unreachable.#{gen.lang}.erb", binding, indent: indent)
37
- end
38
65
  return Packcr::CODE_REACH__ALWAYS_FAIL
39
- when Packcr::CODE_REACH__ALWAYS_SUCCEED
40
- else
41
- b = true
66
+ when Packcr::CODE_REACH__BOTH
67
+ r = Packcr::CODE_REACH__BOTH
42
68
  end
43
69
  end
44
- return b ? Packcr::CODE_REACH__BOTH : Packcr::CODE_REACH__ALWAYS_SUCCEED
45
- end
46
-
47
- def verify_variables(vars)
48
- nodes.each do |node|
49
- node.verify_variables(vars)
50
- end
70
+ r
51
71
  end
52
72
 
53
- def verify_captures(ctx, capts)
54
- nodes.each do |node|
55
- node.verify_captures(ctx, capts)
56
- end
57
- end
58
-
59
- def link_references(ctx)
60
- nodes.each do |node|
61
- node.link_references(ctx)
62
- end
73
+ def to_h
74
+ {
75
+ type: :sequence,
76
+ nodes: nodes.map(&:to_h),
77
+ }
63
78
  end
64
79
  end
65
80
  end
@@ -17,30 +17,30 @@ class Packcr
17
17
  $stdout.print "')\n"
18
18
  end
19
19
 
20
- def generate_code(gen, onfail, indent, bare)
20
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
21
21
  n = value&.length || 0
22
22
  if n > 0
23
23
  if n > 1
24
24
  gen.write Packcr.template("node/string_many.#{gen.lang}.erb", binding, indent: indent)
25
- return Packcr::CODE_REACH__BOTH
26
25
  else
27
26
  gen.write Packcr.template("node/string_one.#{gen.lang}.erb", binding, indent: indent)
28
- return Packcr::CODE_REACH__BOTH
29
27
  end
30
- else
31
- # no code to generate
32
- return Packcr::CODE_REACH__ALWAYS_SUCCEED
33
28
  end
34
- Packcr::CODE_REACH__BOTH
35
- end
36
-
37
- def verify_variables(vars)
38
29
  end
39
30
 
40
- def verify_captures(ctx, capts)
31
+ def reachability
32
+ n = value&.length || 0
33
+ if n <= 0
34
+ return Packcr::CODE_REACH__ALWAYS_SUCCEED
35
+ end
36
+ Packcr::CODE_REACH__BOTH
41
37
  end
42
38
 
43
- def link_references(ctx)
39
+ def to_h
40
+ {
41
+ type: :string,
42
+ value: value,
43
+ }
44
44
  end
45
45
  end
46
46
  end
data/lib/packcr/node.rb CHANGED
@@ -1,25 +1,55 @@
1
1
  class Packcr
2
2
  class Node
3
- def seq(expr)
4
- SequenceNode.new(self, expr)
3
+ def seq(expr, cut: false)
4
+ SequenceNode.new(self).seq(expr, cut: cut)
5
5
  end
6
6
 
7
7
  def alt(expr)
8
- AlternateNode.new(self, expr)
8
+ AlternateNode.new(self).alt(expr)
9
+ end
10
+
11
+ def verify_variables(vars)
12
+ nodes.each do |node|
13
+ node.verify_variables(vars)
14
+ end
15
+ end
16
+
17
+ def verify_captures(ctx, capts)
18
+ nodes.each do |node|
19
+ node.verify_captures(ctx, capts)
20
+ end
21
+ end
22
+
23
+ def link_references(ctx)
9
24
  end
10
25
 
11
26
  def setup_rule(rule)
27
+ end
28
+
29
+ def setup(ctx, rule)
30
+ setup_rule(rule)
31
+ link_references(ctx)
32
+
12
33
  nodes.each do |node|
13
- node.setup_rule(rule)
34
+ node.setup(ctx, rule)
14
35
  end
15
36
  end
16
37
 
17
38
  def nodes
18
39
  []
19
40
  end
41
+
42
+ def reversible?(gen)
43
+ false
44
+ end
45
+
46
+ def sequence?
47
+ false
48
+ end
20
49
  end
21
50
  end
22
51
 
52
+ require "packcr/node/root_node"
23
53
  require "packcr/node/rule_node"
24
54
  require "packcr/node/reference_node"
25
55
  require "packcr/node/string_node"
@@ -32,3 +62,4 @@ require "packcr/node/capture_node"
32
62
  require "packcr/node/expand_node"
33
63
  require "packcr/node/action_node"
34
64
  require "packcr/node/error_node"
65
+ require "packcr/node/eof_node"