packcr 0.0.3 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/packcr +3 -0
- data/lib/packcr/broadcast.rb +17 -0
- data/lib/packcr/cli.rb +25 -0
- data/lib/packcr/code_block.rb +2 -3
- data/lib/packcr/context.rb +58 -872
- data/lib/packcr/generator.rb +13 -10
- data/lib/packcr/node/action_node.rb +20 -5
- data/lib/packcr/node/alternate_node.rb +27 -14
- data/lib/packcr/node/capture_node.rb +22 -8
- data/lib/packcr/node/charclass_node.rb +41 -13
- data/lib/packcr/node/eof_node.rb +23 -0
- data/lib/packcr/node/error_node.rb +29 -11
- data/lib/packcr/node/expand_node.rb +14 -4
- data/lib/packcr/node/predicate_node.rb +19 -23
- data/lib/packcr/node/quantity_node.rb +28 -18
- data/lib/packcr/node/reference_node.rb +43 -5
- data/lib/packcr/node/root_node.rb +60 -0
- data/lib/packcr/node/rule_node.rb +38 -3
- data/lib/packcr/node/sequence_node.rb +51 -31
- data/lib/packcr/node/string_node.rb +16 -12
- data/lib/packcr/node.rb +48 -0
- data/lib/packcr/parser.rb +4570 -0
- data/lib/packcr/stream.rb +9 -13
- data/lib/packcr/templates/context/header.c.erb +29 -0
- data/lib/packcr/templates/context/source.c.erb +1292 -0
- data/lib/packcr/templates/context/source.rb.erb +406 -0
- data/lib/packcr/templates/node/action.c.erb +16 -0
- data/lib/packcr/templates/node/action.rb.erb +21 -0
- data/lib/packcr/templates/node/alternate.c.erb +34 -0
- data/lib/packcr/templates/node/alternate.rb.erb +40 -0
- data/lib/packcr/templates/node/capture.c.erb +17 -0
- data/lib/packcr/templates/node/capture.rb.erb +14 -0
- data/lib/packcr/templates/node/charclass.c.erb +47 -0
- data/lib/packcr/templates/node/charclass.rb.erb +49 -0
- data/lib/packcr/templates/node/charclass_any.c.erb +5 -0
- data/lib/packcr/templates/node/charclass_any.rb.erb +7 -0
- data/lib/packcr/templates/node/charclass_fail.c.erb +1 -0
- data/lib/packcr/templates/node/charclass_fail.rb.erb +1 -0
- data/lib/packcr/templates/node/charclass_one.c.erb +19 -0
- data/lib/packcr/templates/node/charclass_one.rb.erb +23 -0
- data/lib/packcr/templates/node/charclass_utf8.c.erb +49 -0
- data/lib/packcr/templates/node/charclass_utf8.rb.erb +50 -0
- data/lib/packcr/templates/node/charclass_utf8_reverse.rb.erb +51 -0
- data/lib/packcr/templates/node/eof.c.erb +1 -0
- data/lib/packcr/templates/node/eof.rb.erb +3 -0
- data/lib/packcr/templates/node/error.c.erb +28 -0
- data/lib/packcr/templates/node/error.rb.erb +34 -0
- data/lib/packcr/templates/node/expand.c.erb +16 -0
- data/lib/packcr/templates/node/expand.rb.erb +16 -0
- data/lib/packcr/templates/node/predicate.c.erb +30 -0
- data/lib/packcr/templates/node/predicate.rb.erb +28 -0
- data/lib/packcr/templates/node/predicate_neg.c.erb +23 -0
- data/lib/packcr/templates/node/predicate_neg.rb.erb +22 -0
- data/lib/packcr/templates/node/quantify_many.c.erb +45 -0
- data/lib/packcr/templates/node/quantify_many.rb.erb +47 -0
- data/lib/packcr/templates/node/quantify_one.c.erb +21 -0
- data/lib/packcr/templates/node/quantify_one.rb.erb +23 -0
- data/lib/packcr/templates/node/reference.c.erb +5 -0
- data/lib/packcr/templates/node/reference.rb.erb +9 -0
- data/lib/packcr/templates/node/reference_reverse.rb.erb +9 -0
- data/lib/packcr/templates/node/rule.c.erb +19 -0
- data/lib/packcr/templates/node/rule.rb.erb +23 -0
- data/lib/packcr/templates/node/sequence.c.erb +12 -0
- data/lib/packcr/templates/node/sequence.rb.erb +12 -0
- data/lib/packcr/templates/node/string_many.c.erb +11 -0
- data/lib/packcr/templates/node/string_many.rb.erb +10 -0
- data/lib/packcr/templates/node/string_one.c.erb +8 -0
- data/lib/packcr/templates/node/string_one.rb.erb +10 -0
- data/lib/packcr/tokenizer.rb +2948 -0
- data/lib/packcr/util.rb +3 -8
- data/lib/packcr/version.rb +1 -1
- data/lib/packcr.rb +1 -2
- metadata +88 -8
- data/lib/packcr/buffer.rb +0 -47
data/lib/packcr/generator.rb
CHANGED
@@ -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,
|
19
|
-
|
20
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
27
|
-
|
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
|
-
|
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
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
21
|
-
expr.
|
22
|
+
def reachability
|
23
|
+
expr.reachability
|
22
24
|
end
|
23
25
|
|
24
26
|
def verify_captures(ctx, capts)
|
25
|
-
|
27
|
+
super
|
26
28
|
capts.push(self)
|
27
29
|
end
|
28
30
|
|
29
|
-
def
|
30
|
-
expr
|
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
|
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
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
42
|
+
super
|
40
43
|
end
|
41
44
|
|
42
45
|
def verify_captures(ctx, capts)
|
43
46
|
@capts = capts
|
44
|
-
|
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
|
48
|
-
|
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
|
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
|
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
|
-
|
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
|
39
|
-
|
26
|
+
def reachability
|
27
|
+
if neg
|
28
|
+
-expr.reachability
|
29
|
+
else
|
30
|
+
expr.reachability
|
31
|
+
end
|
40
32
|
end
|
41
33
|
|
42
|
-
def
|
43
|
-
expr
|
34
|
+
def nodes
|
35
|
+
[expr]
|
44
36
|
end
|
45
37
|
|
46
|
-
def
|
47
|
-
|
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
|
-
|
9
|
-
|
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
|
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
|
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
|
43
|
-
expr
|
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
|
51
|
-
|
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
|
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
|