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; |