packcr 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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"