packcr 0.0.4 → 0.0.7
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 +4 -4
- data/exe/packcr +3 -0
- data/lib/packcr/broadcast.rb +17 -0
- data/lib/packcr/cli.rb +27 -0
- data/lib/packcr/code_block.rb +2 -4
- data/lib/packcr/context.rb +66 -61
- data/lib/packcr/generated/context.rb +440 -0
- data/lib/packcr/generated/node/action_node.rb +60 -0
- data/lib/packcr/generated/node/alternate_node.rb +98 -0
- data/lib/packcr/generated/node/capture_node.rb +39 -0
- data/lib/packcr/generated/node/charclass_node.rb +372 -0
- data/lib/packcr/generated/node/eof_node.rb +20 -0
- data/lib/packcr/generated/node/error_node.rb +67 -0
- data/lib/packcr/generated/node/expand_node.rb +30 -0
- data/lib/packcr/generated/node/predicate_node.rb +140 -0
- data/lib/packcr/generated/node/quantity_node.rb +167 -0
- data/lib/packcr/generated/node/reference_node.rb +70 -0
- data/lib/packcr/generated/node/rule_node.rb +63 -0
- data/lib/packcr/generated/node/sequence_node.rb +42 -0
- data/lib/packcr/generated/node/string_node.rb +60 -0
- data/lib/packcr/generator.rb +14 -11
- data/lib/packcr/node/action_node.rb +18 -7
- data/lib/packcr/node/alternate_node.rb +22 -12
- data/lib/packcr/node/capture_node.rb +14 -12
- data/lib/packcr/node/charclass_node.rb +44 -24
- data/lib/packcr/node/eof_node.rb +25 -0
- data/lib/packcr/node/error_node.rb +20 -13
- data/lib/packcr/node/expand_node.rb +18 -9
- data/lib/packcr/node/predicate_node.rb +19 -26
- data/lib/packcr/node/quantity_node.rb +31 -24
- data/lib/packcr/node/reference_node.rb +31 -9
- data/lib/packcr/node/root_node.rb +61 -0
- data/lib/packcr/node/rule_node.rb +29 -3
- data/lib/packcr/node/sequence_node.rb +48 -31
- data/lib/packcr/node/string_node.rb +19 -16
- data/lib/packcr/node.rb +34 -5
- data/lib/packcr/parser.rb +4493 -3896
- data/lib/packcr/stream.rb +22 -22
- data/lib/packcr/templates/context/header.c.erb +29 -0
- data/lib/packcr/templates/context/source.c.erb +1069 -0
- data/lib/packcr/templates/context/source.rb.erb +341 -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 +39 -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/quantity_many.c.erb +45 -0
- data/lib/packcr/templates/node/quantity_many.rb.erb +47 -0
- data/lib/packcr/templates/node/quantity_one.c.erb +21 -0
- data/lib/packcr/templates/node/quantity_one.rb.erb +23 -0
- data/lib/packcr/templates/node/reference.c.erb +17 -0
- data/lib/packcr/templates/node/reference.rb.erb +21 -0
- data/lib/packcr/templates/node/reference_reverse.rb.erb +21 -0
- data/lib/packcr/templates/node/rule.c.erb +26 -0
- data/lib/packcr/templates/node/rule.rb.erb +30 -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/util.rb +21 -24
- data/lib/packcr/version.rb +1 -1
- data/lib/packcr.rb +9 -13
- metadata +117 -10
- data/lib/packcr/buffer.rb +0 -47
|
@@ -13,44 +13,58 @@ class Packcr
|
|
|
13
13
|
$stdout.print "')\n"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def
|
|
17
|
-
|
|
18
|
-
return generate_ascii_code(gen, onfail, indent, bare)
|
|
19
|
-
else
|
|
20
|
-
return generate_utf8_charclass_code(gen, onfail, indent, bare)
|
|
21
|
-
end
|
|
16
|
+
def reversible?(gen)
|
|
17
|
+
gen.lang == :rb && !gen.ascii
|
|
22
18
|
end
|
|
23
19
|
|
|
24
|
-
def
|
|
20
|
+
def generate_code(gen, onfail, indent, bare, oncut: nil)
|
|
21
|
+
return generate_ascii_code(gen, onfail, indent, bare) if gen.ascii
|
|
22
|
+
|
|
23
|
+
generate_utf8_charclass_code(gen, onfail, indent, bare)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
def
|
|
26
|
+
def generate_reverse_code(gen, onsuccess, indent, bare, oncut: nil)
|
|
27
|
+
raise "unexpected" if gen.ascii
|
|
28
|
+
|
|
29
|
+
generate_utf8_charclass_reverse_code(gen, onsuccess, indent, bare)
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
def
|
|
32
|
+
def reachability
|
|
33
|
+
charclass = value
|
|
34
|
+
n = charclass&.length || 0
|
|
35
|
+
return Packcr::CODE_REACH__BOTH if charclass.nil? || n > 0
|
|
36
|
+
|
|
37
|
+
Packcr::CODE_REACH__ALWAYS_FAIL
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
private
|
|
34
41
|
|
|
35
42
|
def generate_utf8_charclass_code(gen, onfail, indent, bare)
|
|
36
|
-
charclass =
|
|
43
|
+
charclass = value
|
|
37
44
|
if charclass && charclass.encoding != Encoding::UTF_8
|
|
38
45
|
charclass = charclass.dup.force_encoding(Encoding::UTF_8)
|
|
39
46
|
end
|
|
40
47
|
n = charclass&.length || 0
|
|
41
48
|
if charclass.nil? || n > 0
|
|
42
|
-
|
|
43
|
-
i = a ? 1 : 0
|
|
44
|
-
gen.write Packcr.template("node/charclass_utf8.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
|
45
|
-
return Packcr::CODE_REACH__BOTH
|
|
49
|
+
gen.write Packcr.format_code(get_utf8_code(gen, onfail, indent, bare, charclass, n), indent: indent, unwrap: bare)
|
|
46
50
|
else
|
|
47
|
-
gen.write Packcr.
|
|
48
|
-
|
|
51
|
+
gen.write Packcr.format_code(get_fail_code(gen, onfail, indent, bare), indent: indent)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def generate_utf8_charclass_reverse_code(gen, onsuccess, indent, bare)
|
|
56
|
+
charclass = value
|
|
57
|
+
if charclass && charclass.encoding != Encoding::UTF_8
|
|
58
|
+
charclass = charclass.dup.force_encoding(Encoding::UTF_8)
|
|
49
59
|
end
|
|
60
|
+
n = charclass&.length || 0
|
|
61
|
+
return unless charclass.nil? || n > 0
|
|
62
|
+
|
|
63
|
+
gen.write Packcr.format_code(get_utf8_reverse_code(gen, onsuccess, indent, bare, charclass, n), indent: indent, unwrap: bare)
|
|
50
64
|
end
|
|
51
65
|
|
|
52
66
|
def generate_ascii_code(gen, onfail, indent, bare)
|
|
53
|
-
charclass =
|
|
67
|
+
charclass = value
|
|
54
68
|
if charclass
|
|
55
69
|
n = charclass.length
|
|
56
70
|
a = charclass[0] == "^"
|
|
@@ -60,20 +74,26 @@ class Packcr
|
|
|
60
74
|
end
|
|
61
75
|
if n > 0
|
|
62
76
|
if n > 1
|
|
63
|
-
gen.write Packcr.
|
|
77
|
+
gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, charclass, n, a), indent: indent, unwrap: bare)
|
|
64
78
|
else
|
|
65
|
-
gen.write Packcr.
|
|
79
|
+
gen.write Packcr.format_code(get_one_code(gen, onfail, indent, bare, charclass, n, a), indent: indent)
|
|
66
80
|
end
|
|
67
|
-
return Packcr::CODE_REACH__BOTH
|
|
68
81
|
else
|
|
69
|
-
gen.write Packcr.
|
|
70
|
-
return Packcr::CODE_REACH__ALWAYS_FAIL
|
|
82
|
+
gen.write Packcr.format_code(get_fail_code(gen, onfail, indent, bare), indent: indent)
|
|
71
83
|
end
|
|
72
84
|
else
|
|
73
|
-
gen.write Packcr.
|
|
74
|
-
return Packcr::CODE_REACH__BOTH
|
|
85
|
+
gen.write Packcr.format_code(get_any_code(gen, onfail, indent, bare, charclass), indent: indent)
|
|
75
86
|
end
|
|
76
87
|
end
|
|
88
|
+
|
|
89
|
+
def to_h
|
|
90
|
+
{
|
|
91
|
+
type: :charclass,
|
|
92
|
+
value: value,
|
|
93
|
+
}
|
|
94
|
+
end
|
|
77
95
|
end
|
|
78
96
|
end
|
|
79
97
|
end
|
|
98
|
+
|
|
99
|
+
require "packcr/generated/node/charclass_node"
|
|
@@ -0,0 +1,25 @@
|
|
|
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.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def reachability
|
|
13
|
+
Packcr::CODE_REACH__BOTH
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
{
|
|
18
|
+
type: :eof,
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
require "packcr/generated/node/eof_node"
|
|
@@ -29,26 +29,22 @@ class Packcr
|
|
|
29
29
|
$stdout.print "#{" " * indent}}\n"
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def generate_code(gen, onfail, indent, bare)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
def generate_code(gen, onfail, indent, bare, oncut: nil)
|
|
33
|
+
gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def reachability
|
|
37
|
+
expr.reachability
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def verify_variables(vars)
|
|
41
41
|
@vars = vars
|
|
42
|
-
|
|
42
|
+
super
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def verify_captures(ctx, capts)
|
|
46
46
|
@capts = capts
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def link_references(ctx)
|
|
51
|
-
expr.link_references(ctx)
|
|
47
|
+
super
|
|
52
48
|
end
|
|
53
49
|
|
|
54
50
|
def nodes
|
|
@@ -58,8 +54,19 @@ class Packcr
|
|
|
58
54
|
def setup_rule(rule)
|
|
59
55
|
@index = rule.codes.length
|
|
60
56
|
rule.codes.push(self)
|
|
61
|
-
|
|
57
|
+
end
|
|
58
|
+
|
|
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
|
+
}
|
|
62
67
|
end
|
|
63
68
|
end
|
|
64
69
|
end
|
|
65
70
|
end
|
|
71
|
+
|
|
72
|
+
require "packcr/generated/node/error_node"
|
|
@@ -3,8 +3,10 @@ class Packcr
|
|
|
3
3
|
class ExpandNode < Packcr::Node
|
|
4
4
|
attr_accessor :index, :line, :col
|
|
5
5
|
|
|
6
|
-
def initialize(index = nil)
|
|
6
|
+
def initialize(index = nil, line = nil, col = nil)
|
|
7
7
|
@index = index
|
|
8
|
+
@line = line
|
|
9
|
+
@col = col
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def debug_dump(indent = 0)
|
|
@@ -13,12 +15,12 @@ class Packcr
|
|
|
13
15
|
$stdout.print ")\n"
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
def generate_code(gen, onfail, indent, bare)
|
|
17
|
-
gen.write Packcr.
|
|
18
|
-
return Packcr::CODE_REACH__BOTH
|
|
18
|
+
def generate_code(gen, onfail, indent, bare, oncut: nil)
|
|
19
|
+
gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def
|
|
22
|
+
def reachability
|
|
23
|
+
Packcr::CODE_REACH__BOTH
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def verify_captures(ctx, capts)
|
|
@@ -26,15 +28,22 @@ class Packcr
|
|
|
26
28
|
unless capt.is_a?(Packcr::Node::CaptureNode)
|
|
27
29
|
raise "unexpected capture: #{capt.class}"
|
|
28
30
|
end
|
|
31
|
+
|
|
29
32
|
index == capt.index
|
|
30
33
|
end
|
|
31
|
-
if
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
return if found || index.nil?
|
|
35
|
+
|
|
36
|
+
ctx.error line + 1, col + 1, "Capture #{index + 1} not available at this position"
|
|
34
37
|
end
|
|
35
38
|
|
|
36
|
-
def
|
|
39
|
+
def to_h
|
|
40
|
+
{
|
|
41
|
+
type: :expand,
|
|
42
|
+
index: index,
|
|
43
|
+
}
|
|
37
44
|
end
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
end
|
|
48
|
+
|
|
49
|
+
require "packcr/generated/node/expand_node"
|
|
@@ -15,42 +15,35 @@ 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
|
-
|
|
22
|
-
r, code = gen.generate_code_str(expr, l, 4, false)
|
|
23
|
-
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
|
|
20
|
+
gen.write Packcr.format_code(get_neg_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
30
21
|
else
|
|
31
|
-
|
|
32
|
-
m = gen.next_label
|
|
33
|
-
r, code = gen.generate_code_str(expr, l, 4, false)
|
|
34
|
-
gen.write Packcr.template("node/predicate.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
|
22
|
+
gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
35
23
|
end
|
|
36
|
-
return r
|
|
37
24
|
end
|
|
38
25
|
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|
48
|
+
|
|
49
|
+
require "packcr/generated/node/predicate_node"
|
|
@@ -16,45 +16,52 @@ 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
|
-
|
|
22
|
-
gen.write Packcr.template("node/quantify_many.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
|
|
23
|
-
if min <= 0
|
|
24
|
-
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
|
25
|
-
end
|
|
26
|
-
if r == Packcr::CODE_REACH__ALWAYS_FAIL
|
|
27
|
-
return Packcr::CODE_REACH__ALWAYS_FAIL
|
|
28
|
-
end
|
|
29
|
-
return Packcr::CODE_REACH__BOTH
|
|
21
|
+
gen.write Packcr.format_code(get_many_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
30
22
|
elsif max == 1
|
|
31
23
|
if min > 0
|
|
32
|
-
|
|
24
|
+
gen.write gen.generate_code(expr, onfail, indent, bare, oncut: oncut)
|
|
33
25
|
else
|
|
34
|
-
gen.write Packcr.
|
|
35
|
-
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
|
26
|
+
gen.write Packcr.format_code(get_one_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
36
27
|
end
|
|
37
|
-
else
|
|
38
|
-
# no code to generate
|
|
39
|
-
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
|
40
28
|
end
|
|
41
29
|
end
|
|
42
30
|
|
|
43
|
-
def
|
|
44
|
-
|
|
45
|
-
|
|
31
|
+
def reachability
|
|
32
|
+
if max > 1 || max < 0
|
|
33
|
+
if min <= 0
|
|
34
|
+
return Packcr::CODE_REACH__ALWAYS_SUCCEED
|
|
35
|
+
end
|
|
36
|
+
if expr.reachability == Packcr::CODE_REACH__ALWAYS_FAIL
|
|
37
|
+
return Packcr::CODE_REACH__ALWAYS_FAIL
|
|
38
|
+
end
|
|
46
39
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
Packcr::CODE_REACH__BOTH
|
|
41
|
+
elsif max == 1
|
|
42
|
+
return expr.reachability if min > 0
|
|
43
|
+
|
|
44
|
+
Packcr::CODE_REACH__ALWAYS_SUCCEED
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
else
|
|
47
|
+
Packcr::CODE_REACH__ALWAYS_SUCCEED
|
|
48
|
+
end
|
|
53
49
|
end
|
|
54
50
|
|
|
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
|
|
66
|
+
|
|
67
|
+
require "packcr/generated/node/quantity_node"
|
|
@@ -16,17 +16,30 @@ class Packcr
|
|
|
16
16
|
$stdout.print ", name:'#{name}', rule:'#{rule&.name || "(null)"}')\n"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def
|
|
20
|
-
gen.
|
|
19
|
+
def reversible?(gen)
|
|
20
|
+
gen.lang == :rb
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def generate_code(gen, onfail, indent, bare, oncut: nil)
|
|
24
|
+
gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def generate_reverse_code(gen, onsuccess, indent, bare, oncut: nil)
|
|
28
|
+
gen.write Packcr.format_code(get_reverse_code(gen, onsuccess, indent, bare, oncut), indent: indent)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reachability
|
|
21
32
|
Packcr::CODE_REACH__BOTH
|
|
22
33
|
end
|
|
23
34
|
|
|
24
35
|
def setup_rule(rule)
|
|
25
36
|
return unless var
|
|
37
|
+
|
|
26
38
|
i = rule.vars.index do |ref|
|
|
27
39
|
unless ref.is_a?(Packcr::Node::ReferenceNode)
|
|
28
40
|
raise "Unexpected node type: #{ref.class}"
|
|
29
41
|
end
|
|
42
|
+
|
|
30
43
|
var == ref.var
|
|
31
44
|
end
|
|
32
45
|
if !i
|
|
@@ -43,26 +56,35 @@ class Packcr
|
|
|
43
56
|
unless var.is_a?(Packcr::Node::ReferenceNode)
|
|
44
57
|
raise "unexpected var: #{var.class}"
|
|
45
58
|
end
|
|
59
|
+
|
|
46
60
|
index == var.index
|
|
47
61
|
end
|
|
48
62
|
vars.push(self) if !found
|
|
49
63
|
end
|
|
50
64
|
|
|
51
|
-
def verify_captures(ctx, capts)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
65
|
def link_references(ctx)
|
|
55
|
-
rule = ctx.rule(name)
|
|
56
|
-
if
|
|
57
|
-
ctx.error line + 1, col + 1, "No definition of rule '#{name}'"
|
|
58
|
-
else
|
|
66
|
+
rule = ctx.root.rule(name)
|
|
67
|
+
if rule
|
|
59
68
|
unless rule.is_a?(Packcr::Node::RuleNode)
|
|
60
69
|
raise "unexpected node type #{rule.class}"
|
|
61
70
|
end
|
|
71
|
+
|
|
62
72
|
rule.add_ref
|
|
63
73
|
self.rule = rule
|
|
74
|
+
else
|
|
75
|
+
ctx.error line + 1, col + 1, "No definition of rule '#{name}'"
|
|
64
76
|
end
|
|
65
77
|
end
|
|
78
|
+
|
|
79
|
+
def to_h
|
|
80
|
+
{
|
|
81
|
+
type: :reference,
|
|
82
|
+
name: name,
|
|
83
|
+
var: var,
|
|
84
|
+
}
|
|
85
|
+
end
|
|
66
86
|
end
|
|
67
87
|
end
|
|
68
88
|
end
|
|
89
|
+
|
|
90
|
+
require "packcr/generated/node/reference_node"
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
|
|
42
|
+
case name
|
|
43
|
+
when "EOF"
|
|
44
|
+
expr = Packcr::Node::EofNode.new
|
|
45
|
+
else
|
|
46
|
+
return nil
|
|
47
|
+
end
|
|
48
|
+
rule = Packcr::Node::RuleNode.new(expr, name)
|
|
49
|
+
@rules << rule
|
|
50
|
+
@rulehash[name] = rule
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_h
|
|
54
|
+
{
|
|
55
|
+
type: :root,
|
|
56
|
+
rules: rules.map(&:to_h),
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
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,48 @@ 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.format_code(get_code(gen, onfail, indent, bare, oncut), 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
|
+
|
|
41
|
+
return unless ref == 0
|
|
42
|
+
|
|
43
|
+
ctx.error line + 1, col + 1, "Never used rule '#{name}'"
|
|
27
44
|
end
|
|
28
45
|
|
|
29
46
|
def add_ref
|
|
30
47
|
@ref += 1
|
|
31
48
|
end
|
|
32
49
|
|
|
33
|
-
def setup
|
|
34
|
-
|
|
50
|
+
def setup(ctx)
|
|
51
|
+
super(ctx, self)
|
|
35
52
|
end
|
|
36
53
|
|
|
37
54
|
def nodes
|
|
38
55
|
[expr]
|
|
39
56
|
end
|
|
57
|
+
|
|
58
|
+
def to_h
|
|
59
|
+
{
|
|
60
|
+
type: :rule,
|
|
61
|
+
expr: expr&.to_h,
|
|
62
|
+
}
|
|
63
|
+
end
|
|
40
64
|
end
|
|
41
65
|
end
|
|
42
66
|
end
|
|
67
|
+
|
|
68
|
+
require "packcr/generated/node/rule_node"
|
|
@@ -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
|
|
12
|
-
|
|
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,40 +53,31 @@ class Packcr
|
|
|
27
53
|
m
|
|
28
54
|
end
|
|
29
55
|
|
|
30
|
-
def generate_code(gen, onfail, indent, bare)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
56
|
+
def generate_code(gen, onfail, indent, bare, oncut: nil)
|
|
57
|
+
gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), 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::
|
|
40
|
-
|
|
41
|
-
b = true
|
|
66
|
+
when Packcr::CODE_REACH__BOTH
|
|
67
|
+
r = Packcr::CODE_REACH__BOTH
|
|
42
68
|
end
|
|
43
69
|
end
|
|
44
|
-
|
|
70
|
+
r
|
|
45
71
|
end
|
|
46
72
|
|
|
47
|
-
def
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
|
66
81
|
end
|
|
82
|
+
|
|
83
|
+
require "packcr/generated/node/sequence_node"
|