| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mylisp::Type; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
13
|
use 5.012; |
|
|
1
|
|
|
|
|
3
|
|
|
4
|
1
|
|
|
1
|
|
4
|
no warnings 'experimental'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
23
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
4
|
use Exporter; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
62
|
|
|
7
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
8
|
|
|
|
|
|
|
our @EXPORT = |
|
9
|
|
|
|
|
|
|
qw(new_lint get_type_parser get_type_cursor match_type pat_to_type_rule opt_pat_match match_type_rule match_type_rules match_type_branch match_type_token match_type_rept match_type_str match_type_end report type_grammar my_type_grammar opt_type_match map_opt_type_atom opt_type_atom opt_type_spec opt_type_atoms gather_type_branch opt_type_str is_branch type_rule_to_pat rules_to_pat branch_to_pat rept_to_pat); |
|
10
|
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
5
|
use Spp; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
50
|
|
|
12
|
1
|
|
|
1
|
|
5
|
use Spp::MatchRule; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
112
|
|
|
13
|
1
|
|
|
1
|
|
5
|
use Spp::Tools; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
90
|
|
|
14
|
1
|
|
|
1
|
|
5
|
use Spp::Builtin; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
154
|
|
|
15
|
1
|
|
|
1
|
|
5
|
use Spp::Cursor; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
46
|
|
|
16
|
1
|
|
|
1
|
|
4
|
use Spp::OptAst; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
76
|
|
|
17
|
1
|
|
|
1
|
|
5
|
use Spp::LintAst; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1534
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new_lint { |
|
20
|
0
|
|
|
0
|
0
|
|
my $parser = get_type_parser(); |
|
21
|
0
|
|
|
|
|
|
my $cursor = get_type_cursor(); |
|
22
|
|
|
|
|
|
|
return { |
|
23
|
0
|
|
|
|
|
|
'offline' => '', |
|
24
|
|
|
|
|
|
|
'stack' => [], |
|
25
|
|
|
|
|
|
|
'st' => {}, |
|
26
|
|
|
|
|
|
|
'ret' => '', |
|
27
|
|
|
|
|
|
|
'parser' => $parser, |
|
28
|
|
|
|
|
|
|
'cursor' => $cursor |
|
29
|
|
|
|
|
|
|
}; |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub get_type_parser { |
|
33
|
0
|
|
|
0
|
0
|
|
my $grammar = type_grammar(); |
|
34
|
0
|
|
|
|
|
|
my $ast = grammar_to_ast($grammar); |
|
35
|
0
|
|
|
|
|
|
lint_spp_ast($ast); |
|
36
|
0
|
|
|
|
|
|
my $parser = ast_to_table($ast); |
|
37
|
0
|
|
|
|
|
|
return $parser; |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub get_type_cursor { |
|
41
|
0
|
|
|
0
|
0
|
|
my $parser = get_type_parser(); |
|
42
|
0
|
|
|
|
|
|
my $grammar = my_type_grammar(); |
|
43
|
0
|
|
|
|
|
|
my ($match, $ok) = match_text($parser, $grammar); |
|
44
|
0
|
0
|
|
|
|
|
if ($ok) { |
|
45
|
0
|
|
|
|
|
|
my $ast = opt_type_match($match); |
|
46
|
0
|
|
|
|
|
|
lint_spp_ast($ast); |
|
47
|
0
|
|
|
|
|
|
my $table = ast_to_table($ast); |
|
48
|
0
|
|
|
|
|
|
my $cursor = new_cursor('text', $table); |
|
49
|
0
|
|
|
|
|
|
return $cursor; |
|
50
|
|
|
|
|
|
|
} |
|
51
|
0
|
|
|
|
|
|
else { error($match) } |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub match_type { |
|
55
|
0
|
|
|
0
|
0
|
|
my ($t, $rule, $text) = @_; |
|
56
|
0
|
|
|
|
|
|
my $cursor = $t->{'cursor'}; |
|
57
|
0
|
|
|
|
|
|
$cursor->{'text'} = add($text, End); |
|
58
|
0
|
|
|
|
|
|
$cursor->{'off'} = 0; |
|
59
|
0
|
|
|
|
|
|
return match_type_rule($cursor, $rule); |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub pat_to_type_rule { |
|
63
|
0
|
|
|
0
|
0
|
|
my ($t, $pat) = @_; |
|
64
|
0
|
|
|
|
|
|
my $table = $t->{'parser'}; |
|
65
|
0
|
|
|
|
|
|
my $rule = $table->{'pat'}; |
|
66
|
0
|
|
|
|
|
|
my $cursor = new_cursor($pat, $table); |
|
67
|
0
|
|
|
|
|
|
my $match = match_spp_rule($cursor, $rule); |
|
68
|
0
|
0
|
|
|
|
|
if (is_false($match)) { |
|
69
|
0
|
|
|
|
|
|
report($t, "pattern: |$pat| could not to rule!"); |
|
70
|
|
|
|
|
|
|
} |
|
71
|
0
|
|
|
|
|
|
return opt_pat_match($match); |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub opt_pat_match { |
|
75
|
0
|
|
|
0
|
0
|
|
my $match = shift; |
|
76
|
0
|
|
|
|
|
|
my $end = cons('End', 'End'); |
|
77
|
0
|
0
|
|
|
|
|
if (is_atom($match)) { |
|
78
|
0
|
|
|
|
|
|
my $atom = opt_type_atom($match); |
|
79
|
0
|
|
|
|
|
|
return cons('Rules', cons($atom, $end)); |
|
80
|
|
|
|
|
|
|
} |
|
81
|
0
|
|
|
|
|
|
my $atoms = opt_type_atoms($match); |
|
82
|
0
|
0
|
|
|
|
|
if (is_atom($atoms)) { |
|
83
|
0
|
|
|
|
|
|
return cons('Rules', cons($atoms, $end)); |
|
84
|
|
|
|
|
|
|
} |
|
85
|
0
|
|
|
|
|
|
return cons('Rules', epush($atoms, $end)); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub match_type_rule { |
|
89
|
0
|
|
|
0
|
0
|
|
my ($c, $rule) = @_; |
|
90
|
0
|
0
|
|
|
|
|
if (elen($rule) < 2) { |
|
91
|
0
|
|
|
|
|
|
say see_ast($rule); |
|
92
|
0
|
|
|
|
|
|
croak('trace it...'); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
0
|
|
|
|
|
|
my ($name, $value) = flat($rule); |
|
95
|
0
|
|
|
|
|
|
given ($name) { |
|
96
|
0
|
|
|
|
|
|
when ('Rules') { return match_type_rules($c, $value) } |
|
|
0
|
|
|
|
|
|
|
|
97
|
0
|
|
|
|
|
|
when ('Branch') { return match_type_branch($c, $value) } |
|
|
0
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
when ('Rept') { return match_type_rept($c, $value) } |
|
|
0
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
when ('Str') { return match_type_str($c, $value) } |
|
|
0
|
|
|
|
|
|
|
|
100
|
0
|
|
|
|
|
|
when ('Token') { return match_type_token($c, $value) } |
|
|
0
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
when ('End') { return match_type_end($c, $value) } |
|
|
0
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
default { |
|
103
|
0
|
|
|
|
|
|
error("unknown rule: $name to match!"); |
|
104
|
0
|
|
|
|
|
|
return False |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub match_type_rules { |
|
110
|
0
|
|
|
0
|
0
|
|
my ($c, $rules) = @_; |
|
111
|
0
|
|
|
|
|
|
my $return = False; |
|
112
|
0
|
|
|
|
|
|
for my $rule (@{ atoms($rules) }) { |
|
|
0
|
|
|
|
|
|
|
|
113
|
0
|
0
|
|
|
|
|
if (is_hspace(get_char($c))) { $c->{'off'}++ } |
|
|
0
|
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
my $match = match_type_rule($c, $rule); |
|
115
|
0
|
0
|
|
|
|
|
if (is_false($match)) { return False } |
|
|
0
|
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
|
$return = $match; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
0
|
|
|
|
|
|
return $return; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub match_type_branch { |
|
122
|
0
|
|
|
0
|
0
|
|
my ($c, $branch) = @_; |
|
123
|
0
|
|
|
|
|
|
my $off = $c->{'off'}; |
|
124
|
0
|
|
|
|
|
|
for my $rule (@{ atoms($branch) }) { |
|
|
0
|
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
my $match = match_type_rule($c, $rule); |
|
126
|
0
|
0
|
|
|
|
|
if (not(is_false($match))) { return $match } |
|
|
0
|
|
|
|
|
|
|
|
127
|
0
|
|
|
|
|
|
$c->{'off'} = $off; |
|
128
|
|
|
|
|
|
|
} |
|
129
|
0
|
|
|
|
|
|
return False; |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub match_type_token { |
|
133
|
0
|
|
|
0
|
0
|
|
my ($c, $name) = @_; |
|
134
|
0
|
|
|
|
|
|
my $table = $c->{'ns'}; |
|
135
|
0
|
|
|
|
|
|
my $rule = $table->{$name}; |
|
136
|
0
|
|
|
|
|
|
return match_type_rule($c, $rule); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub match_type_rept { |
|
140
|
0
|
|
|
0
|
0
|
|
my ($c, $rule) = @_; |
|
141
|
0
|
|
|
|
|
|
my ($rept, $atom) = flat($rule); |
|
142
|
0
|
|
|
|
|
|
my ($min, $max) = get_rept_time($rept); |
|
143
|
0
|
|
|
|
|
|
my $time = 0; |
|
144
|
0
|
|
|
|
|
|
while ($time != $max) { |
|
145
|
0
|
|
|
|
|
|
my $off = $c->{'off'}; |
|
146
|
0
|
0
|
|
|
|
|
if (is_hspace(get_char($c))) { $c->{'off'}++ } |
|
|
0
|
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
|
my $match = match_type_rule($c, $atom); |
|
148
|
0
|
0
|
|
|
|
|
if (is_false($match)) { |
|
149
|
0
|
0
|
|
|
|
|
if ($time < $min) { return False } |
|
|
0
|
|
|
|
|
|
|
|
150
|
0
|
|
|
|
|
|
$c->{'off'} = $off; |
|
151
|
0
|
|
|
|
|
|
return True; |
|
152
|
|
|
|
|
|
|
} |
|
153
|
0
|
|
|
|
|
|
$time++; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
0
|
|
|
|
|
|
return True; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub match_type_str { |
|
159
|
0
|
|
|
0
|
0
|
|
my ($c, $str) = @_; |
|
160
|
0
|
|
|
|
|
|
for my $char (split '', $str) { |
|
161
|
0
|
0
|
|
|
|
|
if ($char ne get_char($c)) { return False } |
|
|
0
|
|
|
|
|
|
|
|
162
|
0
|
|
|
|
|
|
$c->{'off'}++; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
0
|
|
|
|
|
|
return True; |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub match_type_end { |
|
168
|
0
|
|
|
0
|
0
|
|
my ($c, $end) = @_; |
|
169
|
0
|
0
|
|
|
|
|
if (get_char($c) eq End) { return True } |
|
|
0
|
|
|
|
|
|
|
|
170
|
0
|
|
|
|
|
|
return False; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub report { |
|
174
|
0
|
|
|
0
|
0
|
|
my ($t, $message) = @_; |
|
175
|
0
|
|
|
|
|
|
my $offline = $t->{'offline'}; |
|
176
|
0
|
|
|
|
|
|
my $line = value($offline); |
|
177
|
0
|
|
|
|
|
|
error("error! line: $line $message"); |
|
178
|
0
|
|
|
|
|
|
return False; |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub type_grammar { |
|
182
|
|
|
|
|
|
|
return <<'EOF' |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
door = |\s+ Spec|+ $ ; |
|
185
|
|
|
|
|
|
|
Spec = Token \h+ '=' \h+ pat ; |
|
186
|
|
|
|
|
|
|
pat = |\h Branch Token Str Rept|+ ; |
|
187
|
|
|
|
|
|
|
Branch = '|' ; |
|
188
|
|
|
|
|
|
|
Token = \a+ ; |
|
189
|
|
|
|
|
|
|
Str = ':' \a+ ; |
|
190
|
|
|
|
|
|
|
Rept = [+?] ; |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
EOF |
|
193
|
0
|
|
|
0
|
0
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
sub my_type_grammar { |
|
196
|
|
|
|
|
|
|
return <<'EOF' |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
door = Bool|Int|StrOrArray|Ints|Map|Fn|Lint|Cursor |
|
199
|
|
|
|
|
|
|
Bool = :Bool |
|
200
|
|
|
|
|
|
|
Str = :Str|:String|:Lstr|:Char |
|
201
|
|
|
|
|
|
|
Int = :Int |
|
202
|
|
|
|
|
|
|
Array = :Array |
|
203
|
|
|
|
|
|
|
Ints = :Ints |
|
204
|
|
|
|
|
|
|
Hash = :Hash |
|
205
|
|
|
|
|
|
|
Table = :Table |
|
206
|
|
|
|
|
|
|
Cursor = :Cursor |
|
207
|
|
|
|
|
|
|
Lint = :Lint |
|
208
|
|
|
|
|
|
|
Fn = :Fn |
|
209
|
|
|
|
|
|
|
StrOrArray = Str|Array |
|
210
|
|
|
|
|
|
|
Map = Hash|Table |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
EOF |
|
213
|
0
|
|
|
0
|
0
|
|
} |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub opt_type_match { |
|
216
|
0
|
|
|
0
|
0
|
|
my $match = shift; |
|
217
|
0
|
0
|
|
|
|
|
if (is_atom($match)) { return opt_type_atom($match) } |
|
|
0
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
|
return map_opt_type_atom($match); |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub map_opt_type_atom { |
|
222
|
0
|
|
|
0
|
0
|
|
my $atoms = shift; |
|
223
|
|
|
|
|
|
|
return estr( |
|
224
|
0
|
|
|
|
|
|
[map { opt_type_atom($_) } @{ atoms($atoms) }]); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub opt_type_atom { |
|
228
|
0
|
|
|
0
|
0
|
|
my $atom = shift; |
|
229
|
0
|
|
|
|
|
|
my ($name, $value) = flat($atom); |
|
230
|
0
|
|
|
|
|
|
given ($name) { |
|
231
|
0
|
|
|
|
|
|
when ('Spec') { return opt_type_spec($value) } |
|
|
0
|
|
|
|
|
|
|
|
232
|
0
|
|
|
|
|
|
when ('Str') { return opt_type_str($value) } |
|
|
0
|
|
|
|
|
|
|
|
233
|
0
|
|
|
|
|
|
when ('Rept') { return cons('rept', $value) } |
|
|
0
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
|
when ('Branch') { return cons('branch', $value) } |
|
|
0
|
|
|
|
|
|
|
|
235
|
0
|
|
|
|
|
|
when ('Token') { return cons('Token', $value) } |
|
|
0
|
|
|
|
|
|
|
|
236
|
0
|
|
|
|
|
|
default { say "unknown atom: |$name|" } |
|
|
0
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub opt_type_spec { |
|
241
|
0
|
|
|
0
|
0
|
|
my $atoms = shift; |
|
242
|
0
|
|
|
|
|
|
my ($token, $rules) = match($atoms); |
|
243
|
0
|
|
|
|
|
|
my $name = value($token); |
|
244
|
0
|
|
|
|
|
|
my $rule = opt_type_atoms($rules); |
|
245
|
0
|
|
|
|
|
|
return cons($name, $rule); |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub opt_type_atoms { |
|
249
|
0
|
|
|
0
|
0
|
|
my $atoms = shift; |
|
250
|
0
|
|
|
|
|
|
$atoms = map_opt_type_atom($atoms); |
|
251
|
0
|
|
|
|
|
|
$atoms = gather_spp_rept($atoms); |
|
252
|
0
|
|
|
|
|
|
$atoms = gather_type_branch($atoms); |
|
253
|
0
|
|
|
|
|
|
return $atoms; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub gather_type_branch { |
|
257
|
0
|
|
|
0
|
0
|
|
my $atoms = shift; |
|
258
|
0
|
|
|
|
|
|
my $branches = []; |
|
259
|
0
|
|
|
|
|
|
my $branch = []; |
|
260
|
0
|
|
|
|
|
|
my $flag = 0; |
|
261
|
0
|
|
|
|
|
|
my $count = 0; |
|
262
|
0
|
|
|
|
|
|
for my $atom (@{ atoms($atoms) }) { |
|
|
0
|
|
|
|
|
|
|
|
263
|
0
|
0
|
|
|
|
|
if (is_branch($atom)) { |
|
264
|
0
|
0
|
|
|
|
|
if ($count > 1) { |
|
265
|
0
|
|
|
|
|
|
push @{$branches}, cons('Rules', estr($branch)); |
|
|
0
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
} |
|
267
|
0
|
|
|
|
|
|
else { push @{$branches}, $branch->[0]; } |
|
|
0
|
|
|
|
|
|
|
|
268
|
0
|
|
|
|
|
|
$flag = 1; |
|
269
|
0
|
|
|
|
|
|
$branch = []; |
|
270
|
0
|
|
|
|
|
|
$count = 0; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
0
|
|
|
|
|
|
else { push @{$branch}, $atom; $count++ } |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
} |
|
274
|
0
|
0
|
|
|
|
|
if ($flag == 0) { |
|
275
|
0
|
0
|
|
|
|
|
if ($count == 1) { return $branch->[0] } |
|
|
0
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
|
else { return cons('Rules', estr($branch)) } |
|
277
|
|
|
|
|
|
|
} |
|
278
|
0
|
0
|
|
|
|
|
if ($count > 1) { |
|
279
|
0
|
|
|
|
|
|
push @{$branches}, cons('Rules', estr($branch)); |
|
|
0
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
} |
|
281
|
0
|
|
|
|
|
|
else { push @{$branches}, $branch->[0]; } |
|
|
0
|
|
|
|
|
|
|
|
282
|
0
|
|
|
|
|
|
return cons('Branch', estr($branches)); |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub opt_type_str { |
|
286
|
0
|
|
|
0
|
0
|
|
my $str = shift; |
|
287
|
0
|
|
|
|
|
|
return cons('Str', rest_str($str)); |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub is_branch { |
|
291
|
0
|
|
|
0
|
0
|
|
my $atom = shift; |
|
292
|
0
|
|
|
|
|
|
return is_atom_name($atom, 'branch'); |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub type_rule_to_pat { |
|
296
|
0
|
|
|
0
|
0
|
|
my $pat = shift; |
|
297
|
0
|
|
|
|
|
|
my ($name, $value) = flat($pat); |
|
298
|
0
|
|
|
|
|
|
given ($name) { |
|
299
|
0
|
|
|
|
|
|
when ('Rules') { return rules_to_pat($value) } |
|
|
0
|
|
|
|
|
|
|
|
300
|
0
|
|
|
|
|
|
when ('Branch') { return branch_to_pat($value) } |
|
|
0
|
|
|
|
|
|
|
|
301
|
0
|
|
|
|
|
|
when ('Rept') { return rept_to_pat($value) } |
|
|
0
|
|
|
|
|
|
|
|
302
|
0
|
|
|
|
|
|
when ('Str') { return ":$value" } |
|
|
0
|
|
|
|
|
|
|
|
303
|
0
|
|
|
|
|
|
when ('Token') { return $value } |
|
|
0
|
|
|
|
|
|
|
|
304
|
0
|
|
|
|
|
|
when ('End') { return '$' } |
|
|
0
|
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
default { say "unknown pat name: |$name| to str" } |
|
|
0
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub rules_to_pat { |
|
310
|
0
|
|
|
0
|
0
|
|
my $atoms = shift; |
|
311
|
|
|
|
|
|
|
my $strs = |
|
312
|
0
|
|
|
|
|
|
[map { type_rule_to_pat($_) } @{ atoms($atoms) }]; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
313
|
0
|
|
|
|
|
|
return join ' ', @{$strs}; |
|
|
0
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
} |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
sub branch_to_pat { |
|
317
|
0
|
|
|
0
|
0
|
|
my $atoms = shift; |
|
318
|
|
|
|
|
|
|
my $strs = |
|
319
|
0
|
|
|
|
|
|
[map { type_rule_to_pat($_) } @{ atoms($atoms) }]; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
320
|
0
|
|
|
|
|
|
return join '|', @{$strs}; |
|
|
0
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
sub rept_to_pat { |
|
324
|
0
|
|
|
0
|
0
|
|
my $rule = shift; |
|
325
|
0
|
|
|
|
|
|
my ($rept, $atom) = flat($rule); |
|
326
|
0
|
|
|
|
|
|
my $atom_str = type_rule_to_pat($atom); |
|
327
|
0
|
|
|
|
|
|
return add($atom_str, $rept); |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
1; |