packcr 0.0.3
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.
- checksums.yaml +7 -0
- data/lib/packcr/buffer.rb +47 -0
- data/lib/packcr/code_block.rb +13 -0
- data/lib/packcr/context.rb +982 -0
- data/lib/packcr/generator.rb +35 -0
- data/lib/packcr/node/action_node.rb +52 -0
- data/lib/packcr/node/alternate_node.rb +71 -0
- data/lib/packcr/node/capture_node.rb +34 -0
- data/lib/packcr/node/charclass_node.rb +75 -0
- data/lib/packcr/node/error_node.rb +52 -0
- data/lib/packcr/node/expand_node.rb +36 -0
- data/lib/packcr/node/predicate_node.rb +51 -0
- data/lib/packcr/node/quantity_node.rb +55 -0
- data/lib/packcr/node/reference_node.rb +46 -0
- data/lib/packcr/node/rule_node.rb +30 -0
- data/lib/packcr/node/sequence_node.rb +61 -0
- data/lib/packcr/node/string_node.rb +43 -0
- data/lib/packcr/node.rb +17 -0
- data/lib/packcr/stream.rb +101 -0
- data/lib/packcr/util.rb +94 -0
- data/lib/packcr/version.rb +3 -0
- data/lib/packcr.rb +33 -0
- metadata +77 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
class Packcr
|
3
|
+
class Generator
|
4
|
+
attr_reader :ascii, :rule, :location, :lang
|
5
|
+
|
6
|
+
def initialize(rule, ascii, location, lang = :c)
|
7
|
+
@rule = rule
|
8
|
+
@label = 0
|
9
|
+
@ascii = !!ascii
|
10
|
+
@location = !!location
|
11
|
+
@lang = lang
|
12
|
+
end
|
13
|
+
|
14
|
+
def next_label
|
15
|
+
@label += 1
|
16
|
+
end
|
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
|
24
|
+
begin
|
25
|
+
return generate_code(node, onfail, indent, bare), @stream.string
|
26
|
+
ensure
|
27
|
+
@stream = stream
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def write(str)
|
32
|
+
@stream.write(str)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class ActionNode < Packcr::Node
|
4
|
+
attr_accessor :code, :index, :vars, :capts
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.vars = []
|
9
|
+
self.capts = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def debug_dump(indent = 0)
|
13
|
+
$stdout.print "#{" " * indent}Action(index:"
|
14
|
+
Packcr.dump_integer_value(index)
|
15
|
+
$stdout.print ", code:{"
|
16
|
+
Packcr.dump_escaped_string(code.text)
|
17
|
+
$stdout.print "}, vars:"
|
18
|
+
|
19
|
+
vars = self.vars
|
20
|
+
capts = self.capts
|
21
|
+
if vars.length + capts.length > 0
|
22
|
+
$stdout.print "\n"
|
23
|
+
vars.each do |ref|
|
24
|
+
$stdout.print "#{" " * (indent + 2)}'#{ref.var}'\n"
|
25
|
+
end
|
26
|
+
capts.each do |capt|
|
27
|
+
$stdout.print "#{" " * (indent + 2)}$#{capt.index + 1}\n"
|
28
|
+
end
|
29
|
+
$stdout.print "#{" " * indent})\n"
|
30
|
+
else
|
31
|
+
$stdout.print "none)\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_code(gen, onfail, indent, bare)
|
36
|
+
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 verify_variables(vars)
|
41
|
+
@vars = vars
|
42
|
+
end
|
43
|
+
|
44
|
+
def verify_captures(ctx, capts)
|
45
|
+
@capts = capts
|
46
|
+
end
|
47
|
+
|
48
|
+
def link_references(ctx)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class AlternateNode < Packcr::Node
|
4
|
+
attr_accessor :nodes
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.nodes = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def debug_dump(indent = 0)
|
12
|
+
$stdout.print "#{" " * indent}Alternate(max:#{max}, len:#{nodes.length}) {\n"
|
13
|
+
nodes.each do |node|
|
14
|
+
node.debug_dump(indent + 2)
|
15
|
+
end
|
16
|
+
$stdout.print "#{" " * indent}}\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def max
|
20
|
+
m = 1
|
21
|
+
m <<= 1 while m < @nodes.length
|
22
|
+
m
|
23
|
+
end
|
24
|
+
|
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)
|
31
|
+
|
32
|
+
reach || Packcr::CODE_REACH__ALWAYS_FAIL
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_variables(vars)
|
36
|
+
m = vars.length
|
37
|
+
v = vars.dup
|
38
|
+
nodes.each do |node|
|
39
|
+
v = v[0, m]
|
40
|
+
node.verify_variables(v)
|
41
|
+
v[m...-1].each do |added_node|
|
42
|
+
found = vars[m...-1].any? do |added_var|
|
43
|
+
added_node.index == added_var.index
|
44
|
+
end
|
45
|
+
if !found
|
46
|
+
vars.push(added_node)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def verify_captures(ctx, capts)
|
53
|
+
m = capts.length
|
54
|
+
v = capts.dup
|
55
|
+
nodes.each do |node|
|
56
|
+
v = v[0, m]
|
57
|
+
node.verify_captures(ctx, v)
|
58
|
+
v[m...-1].each do |added_node|
|
59
|
+
capts.push(added_node)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def link_references(ctx)
|
65
|
+
nodes.each do |node|
|
66
|
+
node.link_references(ctx)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class CaptureNode < Packcr::Node
|
4
|
+
attr_accessor :expr, :index
|
5
|
+
|
6
|
+
def debug_dump(indent = 0)
|
7
|
+
$stdout.print "#{" " * indent}Capture(index:"
|
8
|
+
Packcr.dump_integer_value(index)
|
9
|
+
$stdout.print ") {\n"
|
10
|
+
expr.debug_dump(indent + 2)
|
11
|
+
$stdout.print "#{" " * indent}}\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_code(gen, onfail, indent, bare)
|
15
|
+
r = nil
|
16
|
+
gen.write Packcr.template("node/capture.#{gen.lang}.erb", binding, indent: indent)
|
17
|
+
return r
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify_variables(vars)
|
21
|
+
expr.verify_variables(vars)
|
22
|
+
end
|
23
|
+
|
24
|
+
def verify_captures(ctx, capts)
|
25
|
+
expr.verify_captures(ctx, capts)
|
26
|
+
capts.push(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def link_references(ctx)
|
30
|
+
expr.link_references(ctx)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class CharclassNode < Packcr::Node
|
4
|
+
attr_accessor :value
|
5
|
+
|
6
|
+
def debug_dump(indent = 0)
|
7
|
+
$stdout.print "#{" " * indent}Charclass(value:'"
|
8
|
+
Packcr.dump_escaped_string(value)
|
9
|
+
$stdout.print "')\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_code(gen, onfail, indent, bare)
|
13
|
+
if gen.ascii
|
14
|
+
return generate_ascii_code(gen, onfail, indent, bare)
|
15
|
+
else
|
16
|
+
return generate_utf8_charclass_code(gen, onfail, indent, bare)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify_variables(vars)
|
21
|
+
end
|
22
|
+
|
23
|
+
def verify_captures(ctx, capts)
|
24
|
+
end
|
25
|
+
|
26
|
+
def link_references(ctx)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def generate_utf8_charclass_code(gen, onfail, indent, bare)
|
32
|
+
charclass = self.value
|
33
|
+
if charclass && charclass.encoding != Encoding::UTF_8
|
34
|
+
charclass = charclass.dup.force_encoding(Encoding::UTF_8)
|
35
|
+
end
|
36
|
+
n = charclass&.length || 0
|
37
|
+
if charclass.nil? || n > 0
|
38
|
+
a = charclass && charclass[0] == '^'
|
39
|
+
i = a ? 1 : 0
|
40
|
+
gen.write Packcr.template("node/charclass_utf8.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
41
|
+
return Packcr::CODE_REACH__BOTH
|
42
|
+
else
|
43
|
+
gen.write Packcr.template("node/charclass_fail.#{gen.lang}.erb", binding, indent: indent)
|
44
|
+
return Packcr::CODE_REACH__ALWAYS_FAIL
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_ascii_code(gen, onfail, indent, bare)
|
49
|
+
charclass = self.value
|
50
|
+
if charclass
|
51
|
+
n = charclass.length
|
52
|
+
a = charclass[0] == "^"
|
53
|
+
if a
|
54
|
+
n -= 1
|
55
|
+
charclass = charclass[1..-1]
|
56
|
+
end
|
57
|
+
if n > 0
|
58
|
+
if n > 1
|
59
|
+
gen.write Packcr.template("node/charclass.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
60
|
+
else
|
61
|
+
gen.write Packcr.template("node/charclass_one.#{gen.lang}.erb", binding, indent: indent)
|
62
|
+
end
|
63
|
+
return Packcr::CODE_REACH__BOTH
|
64
|
+
else
|
65
|
+
gen.write Packcr.template("node/charclass_fail.#{gen.lang}.erb", binding, indent: indent)
|
66
|
+
return Packcr::CODE_REACH__ALWAYS_FAIL
|
67
|
+
end
|
68
|
+
else
|
69
|
+
gen.write Packcr.template("node/charclass_any.#{gen.lang}.erb", binding, indent: indent)
|
70
|
+
return Packcr::CODE_REACH__BOTH
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class ErrorNode < Packcr::Node
|
4
|
+
attr_accessor :expr, :code, :index, :vars, :capts
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.vars = []
|
9
|
+
self.capts = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def debug_dump(indent = 0)
|
13
|
+
$stdout.print "#{" " * indent}Error(index:"
|
14
|
+
Packcr.dump_integer_value(index)
|
15
|
+
$stdout.print ", code:{"
|
16
|
+
Packcr.dump_escaped_string(code.text)
|
17
|
+
$stdout.print "}, vars:\n"
|
18
|
+
vars.each do |ref|
|
19
|
+
$stdout.print "#{" " * (indent + 2)}'#{ref.var}'\n"
|
20
|
+
end
|
21
|
+
capts.each do |capt|
|
22
|
+
$stdout.print "#{" " * (indent + 2)}$#{capt.index + 1}\n"
|
23
|
+
end
|
24
|
+
$stdout.print "#{" " * indent}) {\n"
|
25
|
+
expr.debug_dump(indent + 2)
|
26
|
+
$stdout.print "#{" " * indent}}\n"
|
27
|
+
end
|
28
|
+
|
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)
|
33
|
+
gen.write Packcr.template("node/error.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
34
|
+
return r
|
35
|
+
end
|
36
|
+
|
37
|
+
def verify_variables(vars)
|
38
|
+
@vars = vars
|
39
|
+
expr.verify_variables(vars)
|
40
|
+
end
|
41
|
+
|
42
|
+
def verify_captures(ctx, capts)
|
43
|
+
@capts = capts
|
44
|
+
expr.verify_captures(ctx, capts)
|
45
|
+
end
|
46
|
+
|
47
|
+
def link_references(ctx)
|
48
|
+
expr.link_references(ctx)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class ExpandNode < Packcr::Node
|
4
|
+
attr_accessor :index, :line, :col
|
5
|
+
|
6
|
+
def debug_dump(indent = 0)
|
7
|
+
$stdout.print "#{" " * indent}Expand(index:"
|
8
|
+
Packcr.dump_integer_value(index)
|
9
|
+
$stdout.print ")\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_code(gen, onfail, indent, bare)
|
13
|
+
gen.write Packcr.template("node/expand.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
14
|
+
return Packcr::CODE_REACH__BOTH
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify_variables(vars)
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify_captures(ctx, capts)
|
21
|
+
found = capts.any? do |capt|
|
22
|
+
unless capt.is_a?(Packcr::Node::CaptureNode)
|
23
|
+
raise "unexpected capture: #{capt.class}"
|
24
|
+
end
|
25
|
+
index == capt.index
|
26
|
+
end
|
27
|
+
if !found && index != nil
|
28
|
+
ctx.error line + 1, col + 1, "Capture #{index + 1} not available at this position"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def link_references(ctx)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class PredicateNode < Packcr::Node
|
4
|
+
attr_accessor :neg, :expr
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.neg = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def debug_dump(indent = 0)
|
12
|
+
$stdout.print "#{" " * indent}Predicate(neg:#{neg ? 1 : 0}) {\n"
|
13
|
+
expr.debug_dump(indent + 2)
|
14
|
+
$stdout.print "#{" " * indent}}\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_code(gen, onfail, indent, bare)
|
18
|
+
r = nil
|
19
|
+
if neg
|
20
|
+
l = gen.next_label
|
21
|
+
r, code = gen.generate_code_str(expr, l, 4, false)
|
22
|
+
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
|
+
else
|
30
|
+
l = gen.next_label
|
31
|
+
m = gen.next_label
|
32
|
+
r, code = gen.generate_code_str(expr, l, 4, false)
|
33
|
+
gen.write Packcr.template("node/predicate.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
34
|
+
end
|
35
|
+
return r
|
36
|
+
end
|
37
|
+
|
38
|
+
def verify_variables(vars)
|
39
|
+
expr.verify_variables(vars)
|
40
|
+
end
|
41
|
+
|
42
|
+
def verify_captures(ctx, capts)
|
43
|
+
expr.verify_captures(ctx, capts)
|
44
|
+
end
|
45
|
+
|
46
|
+
def link_references(ctx)
|
47
|
+
expr.link_references(ctx)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class QuantityNode < Packcr::Node
|
4
|
+
attr_accessor :min, :max, :expr
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.min = 0
|
9
|
+
self.max = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def debug_dump(indent = 0)
|
13
|
+
$stdout.print "#{" " * indent}Quantity(min:#{min}, max:#{max}) {\n"
|
14
|
+
expr.debug_dump(indent + 2)
|
15
|
+
$stdout.print "#{" " * indent}}\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_code(gen, onfail, indent, bare)
|
19
|
+
if max > 1 || max < 0
|
20
|
+
r = nil
|
21
|
+
gen.write Packcr.template("node/quantify_many.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
22
|
+
if min <= 0
|
23
|
+
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
24
|
+
end
|
25
|
+
if r == Packcr::CODE_REACH__ALWAYS_FAIL
|
26
|
+
return Packcr::CODE_REACH__ALWAYS_FAIL
|
27
|
+
end
|
28
|
+
return Packcr::CODE_REACH__BOTH
|
29
|
+
elsif max == 1
|
30
|
+
if min > 0
|
31
|
+
return gen.generate_code(expr, onfail, indent, bare)
|
32
|
+
else
|
33
|
+
gen.write Packcr.template("node/quantify_one.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
34
|
+
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
35
|
+
end
|
36
|
+
else
|
37
|
+
# no code to generate
|
38
|
+
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
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)
|
48
|
+
end
|
49
|
+
|
50
|
+
def link_references(ctx)
|
51
|
+
expr.link_references(ctx)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class ReferenceNode < Packcr::Node
|
4
|
+
attr_accessor :var, :index, :name, :rule, :line, :col
|
5
|
+
|
6
|
+
def debug_dump(indent = 0)
|
7
|
+
$stdout.print "#{" " * indent}Reference(var:'#{var || "(null)"}', index:"
|
8
|
+
Packcr.dump_integer_value(index)
|
9
|
+
$stdout.print ", name:'#{name}', rule:'#{rule&.name || "(null)"}')\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_code(gen, onfail, indent, bare)
|
13
|
+
gen.write Packcr.template("node/reference.#{gen.lang}.erb", binding, indent: indent)
|
14
|
+
Packcr::CODE_REACH__BOTH
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify_variables(vars)
|
18
|
+
return if index.nil?
|
19
|
+
|
20
|
+
found = vars.any? do |var|
|
21
|
+
unless var.is_a?(Packcr::Node::ReferenceNode)
|
22
|
+
raise "unexpected var: #{var.class}"
|
23
|
+
end
|
24
|
+
index == var.index
|
25
|
+
end
|
26
|
+
vars.push(self) if !found
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_captures(ctx, capts)
|
30
|
+
end
|
31
|
+
|
32
|
+
def link_references(ctx)
|
33
|
+
rule = ctx.rule(name)
|
34
|
+
if !rule
|
35
|
+
ctx.error line + 1, col + 1, "No definition of rule '#{name}'"
|
36
|
+
else
|
37
|
+
unless rule.is_a?(Packcr::Node::RuleNode)
|
38
|
+
raise "unexpected node type #{rule.class}"
|
39
|
+
end
|
40
|
+
rule.add_ref
|
41
|
+
self.rule = rule
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class RuleNode < Packcr::Node
|
4
|
+
attr_accessor :codes, :name, :expr, :ref, :vars, :capts, :line, :col
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.ref = 0
|
9
|
+
self.vars = []
|
10
|
+
self.capts = []
|
11
|
+
self.codes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def debug_dump(indent = 0)
|
15
|
+
$stdout.print "#{" " * indent}Rule(name:'#{name}', ref:#{ref}, vars.len:#{vars.length}, capts.len:#{capts.length}, codes.len:#{codes.length}) {\n"
|
16
|
+
expr.debug_dump(indent + 2)
|
17
|
+
$stdout.print "#{" " * indent}}\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify(ctx)
|
21
|
+
expr.verify_variables([])
|
22
|
+
expr.verify_captures(ctx, [])
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_ref
|
26
|
+
@ref += 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class SequenceNode < Packcr::Node
|
4
|
+
attr_accessor :nodes
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.nodes = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def debug_dump(indent = 0)
|
12
|
+
$stdout.print "#{" " * indent}Sequence(max:#{max}, len:#{nodes.length}) {\n"
|
13
|
+
nodes.each do |child_node|
|
14
|
+
child_node.debug_dump(indent + 2)
|
15
|
+
end
|
16
|
+
$stdout.print "#{" " * indent}}\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def max
|
20
|
+
m = 1
|
21
|
+
m <<= 1 while m < @nodes.length
|
22
|
+
m
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_code(gen, onfail, indent, bare)
|
26
|
+
b = false
|
27
|
+
nodes.each_with_index do |expr, i|
|
28
|
+
case gen.generate_code(expr, onfail, indent, false)
|
29
|
+
when Packcr::CODE_REACH__ALWAYS_FAIL
|
30
|
+
if i + 1 < nodes.length
|
31
|
+
gen.write Packcr.template("node/sequence_unreachable.#{gen.lang}.erb", binding, indent: indent)
|
32
|
+
end
|
33
|
+
return Packcr::CODE_REACH__ALWAYS_FAIL
|
34
|
+
when Packcr::CODE_REACH__ALWAYS_SUCCEED
|
35
|
+
else
|
36
|
+
b = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
return b ? Packcr::CODE_REACH__BOTH : Packcr::CODE_REACH__ALWAYS_SUCCEED
|
40
|
+
end
|
41
|
+
|
42
|
+
def verify_variables(vars)
|
43
|
+
nodes.each do |node|
|
44
|
+
node.verify_variables(vars)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def verify_captures(ctx, capts)
|
49
|
+
nodes.each do |node|
|
50
|
+
node.verify_captures(ctx, capts)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def link_references(ctx)
|
55
|
+
nodes.each do |node|
|
56
|
+
node.link_references(ctx)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
class StringNode < Packcr::Node
|
4
|
+
attr_accessor :value
|
5
|
+
|
6
|
+
def value=(value)
|
7
|
+
@value = value&.b
|
8
|
+
end
|
9
|
+
|
10
|
+
def debug_dump(indent = 0)
|
11
|
+
$stdout.print "#{" " * indent}String(value:'"
|
12
|
+
Packcr.dump_escaped_string(value)
|
13
|
+
$stdout.print "')\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_code(gen, onfail, indent, bare)
|
17
|
+
n = value&.length || 0
|
18
|
+
if n > 0
|
19
|
+
if n > 1
|
20
|
+
gen.write Packcr.template("node/string_many.#{gen.lang}.erb", binding, indent: indent)
|
21
|
+
return Packcr::CODE_REACH__BOTH
|
22
|
+
else
|
23
|
+
gen.write Packcr.template("node/string_one.#{gen.lang}.erb", binding, indent: indent)
|
24
|
+
return Packcr::CODE_REACH__BOTH
|
25
|
+
end
|
26
|
+
else
|
27
|
+
# no code to generate
|
28
|
+
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
29
|
+
end
|
30
|
+
Packcr::CODE_REACH__BOTH
|
31
|
+
end
|
32
|
+
|
33
|
+
def verify_variables(vars)
|
34
|
+
end
|
35
|
+
|
36
|
+
def verify_captures(ctx, capts)
|
37
|
+
end
|
38
|
+
|
39
|
+
def link_references(ctx)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/packcr/node.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Node
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require "packcr/node/rule_node"
|
7
|
+
require "packcr/node/reference_node"
|
8
|
+
require "packcr/node/string_node"
|
9
|
+
require "packcr/node/charclass_node"
|
10
|
+
require "packcr/node/quantity_node"
|
11
|
+
require "packcr/node/predicate_node"
|
12
|
+
require "packcr/node/sequence_node"
|
13
|
+
require "packcr/node/alternate_node"
|
14
|
+
require "packcr/node/capture_node"
|
15
|
+
require "packcr/node/expand_node"
|
16
|
+
require "packcr/node/action_node"
|
17
|
+
require "packcr/node/error_node"
|