line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Parse::Gnaw::Blocks::Letter; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.001'; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#BEGIN {print "Parse::Gnaw::Blocks::Letter\n";} |
9
|
|
|
|
|
|
|
|
10
|
19
|
|
|
19
|
|
103
|
use warnings; |
|
19
|
|
|
|
|
32
|
|
|
19
|
|
|
|
|
551
|
|
11
|
19
|
|
|
19
|
|
94
|
use strict; |
|
19
|
|
|
|
|
32
|
|
|
19
|
|
|
|
|
555
|
|
12
|
19
|
|
|
19
|
|
123
|
use Carp; |
|
19
|
|
|
|
|
46
|
|
|
19
|
|
|
|
|
1222
|
|
13
|
19
|
|
|
19
|
|
118
|
use Data::Dumper; |
|
19
|
|
|
|
|
31
|
|
|
19
|
|
|
|
|
1101
|
|
14
|
19
|
|
|
19
|
|
96
|
use Storable 'dclone'; |
|
19
|
|
|
|
|
43
|
|
|
19
|
|
|
|
|
1428
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
17
|
19
|
|
|
19
|
|
7443
|
use Parse::Gnaw::Blocks::LetterConstants; |
|
19
|
|
|
|
|
53
|
|
|
19
|
|
|
|
|
1697
|
|
18
|
19
|
|
|
19
|
|
7878
|
use Parse::Gnaw::LinkedListConstants; |
|
19
|
|
|
|
|
45
|
|
|
19
|
|
|
|
|
32260
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 NAME |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Parse::Gnaw::Blocks::Letter - a linked list element that holds a single scalar payload. |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head2 new |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
This is the constructor for a letter object, which is part of a LinkedListObject |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
Parse::Gnaw::Blocks::Letter->new($linkedlist, $lettervalue, $letterlocation); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Linkedlist is the linkedlist object that contains this letter. |
32
|
|
|
|
|
|
|
Lettervalue is probably a single character like 'b'. |
33
|
|
|
|
|
|
|
Letterlocation is a string that describes where the letter originaly came from (filename/linenum). |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=cut |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub new { |
39
|
|
|
|
|
|
|
|
40
|
263
|
|
|
263
|
1
|
435
|
my ($pkg, $llist, $value, $location)=@_; |
41
|
263
|
|
100
|
|
|
668
|
$location ||= 'unknown'; |
42
|
|
|
|
|
|
|
|
43
|
263
|
|
|
|
|
339
|
my $connmin1=$llist->[LIST__CONNECTIONS_MINUS_ONE]; |
44
|
263
|
|
|
|
|
286
|
my @connections; |
45
|
263
|
|
|
|
|
487
|
foreach my $dimension (0 .. $connmin1){ |
46
|
566
|
|
|
|
|
1500
|
push(@connections, [undef,undef]); |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
263
|
|
|
|
|
753
|
my $ltrobj=bless([],$pkg); |
51
|
|
|
|
|
|
|
|
52
|
263
|
|
|
|
|
504
|
$ltrobj->[LETTER__LINKED_LIST] = $llist; |
53
|
263
|
|
|
|
|
424
|
$ltrobj->[LETTER__DATA_PAYLOAD]= $value; |
54
|
263
|
|
|
|
|
398
|
$ltrobj->[LETTER__CONNECTIONS] = \@connections; |
55
|
263
|
|
|
|
|
454
|
$ltrobj->[LETTER__WHERE_LETTER_CAME_FROM] = $location; |
56
|
263
|
|
|
|
|
409
|
$ltrobj->[LETTER__LETTER_HAS_BEEN_CONSUMED]=0; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# get the most recently created letter |
59
|
263
|
|
|
|
|
281
|
my $previous_letter; |
60
|
263
|
100
|
|
|
|
683
|
if( $llist->[LIST__MOST_RECENTLY_CREATED_LETTER]){ |
61
|
236
|
|
|
|
|
299
|
$previous_letter = $llist->[LIST__MOST_RECENTLY_CREATED_LETTER]; |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# find out what most recently created letter pointed "next start" to. |
64
|
236
|
|
|
|
|
258
|
my $next_letter; |
65
|
236
|
100
|
66
|
|
|
1010
|
if($previous_letter and $previous_letter->[LETTER__NEXT_START]){ |
66
|
182
|
|
|
|
|
268
|
$next_letter = $previous_letter->[LETTER__NEXT_START]; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# previous_letter connects to newletter |
70
|
|
|
|
|
|
|
# $previous_letter->link_two_letters_via_next_start($ltrobj); |
71
|
236
|
|
|
|
|
313
|
$previous_letter->[LETTER__NEXT_START]=$ltrobj; |
72
|
236
|
|
|
|
|
392
|
$ltrobj->[LETTER__PREVIOUS_START]=$previous_letter; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# update the linked list so that THIS newly created letter is now the most recently created letter. |
77
|
263
|
|
|
|
|
405
|
$llist->[LIST__MOST_RECENTLY_CREATED_LETTER] = $ltrobj; |
78
|
|
|
|
|
|
|
|
79
|
263
|
|
|
|
|
897
|
return $ltrobj; # return the letter |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
my $blank_obj=[]; |
84
|
|
|
|
|
|
|
#print "blank_obj is '$blank_obj'\n"; die; |
85
|
|
|
|
|
|
|
my $blank_str=$blank_obj.''; |
86
|
|
|
|
|
|
|
my $blank_len=length($blank_str); |
87
|
|
|
|
|
|
|
my $BLANK = '.'x($blank_len-5); |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head2 get_raw_address |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
This is a subroutine. Do NOT call this as a method. This will allow it to handle undef values. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
my $retval = get_raw_address($letterobj); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Given a letter object, get the string that looks like |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
Parse::Gnaw::Blocks::Letter=ARRAY(0x850cea4) |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
and return something like |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
0x850cea4 |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=cut |
104
|
|
|
|
|
|
|
sub get_raw_address{ |
105
|
177
|
|
|
177
|
1
|
214
|
my ($ltrobj)=@_; |
106
|
|
|
|
|
|
|
|
107
|
177
|
100
|
|
|
|
419
|
unless(defined($ltrobj)){ |
108
|
40
|
|
|
|
|
85
|
return $BLANK; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
137
|
|
|
|
|
301
|
my $string=$ltrobj.''; |
112
|
137
|
50
|
|
|
|
563
|
$string=~m{(\(0x[0-9a-f]+\))} or croak "could not get_raw_address"; |
113
|
137
|
|
|
|
|
317
|
my $addr=$1; |
114
|
|
|
|
|
|
|
|
115
|
137
|
|
|
|
|
385
|
return $addr; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head2 display |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
print out a formatted version of letter object. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=cut |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub display { |
127
|
59
|
|
|
59
|
1
|
81
|
my ($ltrobj)=@_; |
128
|
59
|
|
|
|
|
1024
|
print "\n"; |
129
|
59
|
|
|
|
|
2030
|
print "\tletterobject: ".$ltrobj."\n"; |
130
|
59
|
|
|
|
|
2030
|
print "\tpayload: '".($ltrobj->[LETTER__DATA_PAYLOAD])."'\n"; |
131
|
59
|
|
|
|
|
1870
|
print "\tfrom: ".($ltrobj->[LETTER__WHERE_LETTER_CAME_FROM])."\n"; |
132
|
59
|
|
|
|
|
2466
|
print "\t"."connections:\n"; |
133
|
|
|
|
|
|
|
|
134
|
59
|
|
|
|
|
149
|
my $self = get_raw_address($ltrobj); |
135
|
|
|
|
|
|
|
|
136
|
59
|
|
|
|
|
83
|
foreach my $conn (@{$ltrobj->[LETTER__CONNECTIONS]}){ |
|
59
|
|
|
|
|
1237
|
|
137
|
59
|
|
|
|
|
92
|
my $prev = $conn->[LETTER__CONNECTION_PREV]; |
138
|
59
|
|
|
|
|
72
|
my $next = $conn->[LETTER__CONNECTION_NEXT]; |
139
|
59
|
|
|
|
|
103
|
my $prev_addr = get_raw_address($prev); |
140
|
59
|
|
|
|
|
109
|
my $next_addr = get_raw_address($next); |
141
|
|
|
|
|
|
|
|
142
|
59
|
|
|
|
|
2419
|
print "\t\t [ $prev_addr , $next_addr ]\n"; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
|
147
|
59
|
|
|
|
|
937
|
print "\n"; |
148
|
59
|
|
|
|
|
181
|
return; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=head2 get_more_letters |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
if a LETTER needs more letters, then call this and we'll have the linked list get more letters. |
157
|
|
|
|
|
|
|
Note that $which will be either NEXTSTART or NEXTCONN |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub get_more_letters{ |
162
|
|
|
|
|
|
|
# $which will be "CONNECTIONS" or "NEXTSTART" |
163
|
0
|
|
|
0
|
1
|
0
|
my($ltrobj,$which,$axis)=@_; # note: $axis will default to 0 if not supplied. |
164
|
0
|
|
|
|
|
0
|
eval{ |
165
|
0
|
|
|
|
|
0
|
$ltrobj->get_linked_list()->get_more_letters($ltrobj,$which,$axis); |
166
|
|
|
|
|
|
|
}; |
167
|
0
|
0
|
|
|
|
0
|
if($@){ |
168
|
0
|
|
|
|
|
0
|
croak "$@ "; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head2 Connections verus Next Starting Position |
174
|
|
|
|
|
|
|
If we want to parse a 2-D array of text, we have to step through each starting position |
175
|
|
|
|
|
|
|
and try to match the regular expression to the string. The regular expression can match |
176
|
|
|
|
|
|
|
through any connection between letters. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
For example, a simple 2D list could be interconnected vertically and horizontally like this: |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
1---2---3 |
181
|
|
|
|
|
|
|
| | | |
182
|
|
|
|
|
|
|
| | | |
183
|
|
|
|
|
|
|
| | | |
184
|
|
|
|
|
|
|
4---5---6 |
185
|
|
|
|
|
|
|
| | | |
186
|
|
|
|
|
|
|
| | | |
187
|
|
|
|
|
|
|
| | | |
188
|
|
|
|
|
|
|
7---8---9 |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Or it could be connected on diagonals as well: |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
1---2---3 |
193
|
|
|
|
|
|
|
|\ /|\ /| |
194
|
|
|
|
|
|
|
| X | X | |
195
|
|
|
|
|
|
|
|/ \|/ \| |
196
|
|
|
|
|
|
|
4---5---6 |
197
|
|
|
|
|
|
|
|\ /|\ /| |
198
|
|
|
|
|
|
|
| X | X | |
199
|
|
|
|
|
|
|
|/ \|/ \| |
200
|
|
|
|
|
|
|
7---8---9 |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
As we try to fit a regular expression to the linked list, we will follow the CONNECTIONS |
203
|
|
|
|
|
|
|
to figure out what letters are in sequential order. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
As we parse, if we're at letter "3", this can connect to 2, 6, and possibly 5. |
206
|
|
|
|
|
|
|
But if starting from "3" does not yeild a match, then we need to move to the next starting position, |
207
|
|
|
|
|
|
|
which could be "4". 4 doesn't connect to 3, but it is the next starting position after 3. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
simple 3D list might be connected horizontally and vertically like this: |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
1----2----3 |
214
|
|
|
|
|
|
|
|\ |\ |\ |
215
|
|
|
|
|
|
|
| 4--+-5--+-6 |
216
|
|
|
|
|
|
|
| | | | | | |
217
|
|
|
|
|
|
|
7-+--8-+--9 | |
218
|
|
|
|
|
|
|
\| \| \| |
219
|
|
|
|
|
|
|
a----b----c |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
The "starting position" order could be 1->2->3->4->5->6->7->8->9->a->b->c |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
Note that 3 is not CONNECTED to 4, but if we try 3 as a starting position |
225
|
|
|
|
|
|
|
and it fails, then after 3 the NEXT STARTING POSITION is 4. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
The NextStartingPosition and the ConnectionsBetweenLetters are two different concepts |
228
|
|
|
|
|
|
|
that are built into the data structures of the linked list and the letters. |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
And they are accessed through several methods: |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
Connections: |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
We can create a connection between two letters with: |
235
|
|
|
|
|
|
|
link_two_letters_via_interconnection |
236
|
|
|
|
|
|
|
And we can get the next connection with: |
237
|
|
|
|
|
|
|
next_connection |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Starting Positions: |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
We can create a link between letters for starting connections with: |
243
|
|
|
|
|
|
|
link_two_letters_via_next_start |
244
|
|
|
|
|
|
|
We can traverse from one starting position to the next with: |
245
|
|
|
|
|
|
|
advance_start_position |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=cut |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=head2 link_two_letters_via_next_start |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
$first->link_two_letters_via_next_start($second); |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Create a link so that after $first, the next starting position is $second. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=cut |
259
|
|
|
|
|
|
|
sub link_two_letters_via_next_start{ |
260
|
418
|
|
|
418
|
1
|
534
|
my ($firstltr,$nextltr)=@_; |
261
|
418
|
|
|
|
|
528
|
$firstltr->[LETTER__NEXT_START]=$nextltr; |
262
|
418
|
|
|
|
|
1109
|
$nextltr->[LETTER__PREVIOUS_START]=$firstltr; |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head2 advance_start_position |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Advance (move) the starting position to the next spot. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
my $second = $first->advance_start_position(); |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
We tried to match the regular expression starting from $first, but it didn't match. |
273
|
|
|
|
|
|
|
So, now we want to advance to the $second starting position and try from there. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
If nextstart points to end or null or whatever, then get more letters. |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=cut |
278
|
|
|
|
|
|
|
sub advance_start_position{ |
279
|
0
|
|
|
0
|
1
|
0
|
my $ltrobj=shift(@_); |
280
|
|
|
|
|
|
|
|
281
|
0
|
0
|
0
|
|
|
0
|
if( |
282
|
|
|
|
|
|
|
# if it is undef or 0 or "false" in any perl sense of false |
283
|
|
|
|
|
|
|
(not($ltrobj->[LETTER__NEXT_START])) |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# or if it points to the LAST POINTER of the linked list object |
286
|
|
|
|
|
|
|
or ($ltrobj->[LETTER__NEXT_START] eq $ltrobj->[LETTER__LINKED_LIST]->[LIST__LAST_START]) |
287
|
|
|
|
|
|
|
){ |
288
|
0
|
|
|
|
|
0
|
$ltrobj->get_more_letters("START_POSITION"); |
289
|
|
|
|
|
|
|
} |
290
|
0
|
|
|
|
|
0
|
return $ltrobj->[LETTER__NEXT_START]; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=head2 link_two_letters_via_interconnection |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
$first->link_two_letters_via_interconnection($second,$axis); |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Create a linkage between $first and $second so that they are INTERCONNECTED |
299
|
|
|
|
|
|
|
to be treated as sequential letters for parsing purposes. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
The $axis defaults to 0. It represents whatever axis your linked list structure needs. |
302
|
|
|
|
|
|
|
For example, one axis could be the "vertical" axis. In that example, $first could be thought |
303
|
|
|
|
|
|
|
of as being "up" from $second. And $second could be thought of as "down" from $first. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=cut |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
sub link_two_letters_via_interconnection{ |
308
|
329
|
|
|
329
|
1
|
441
|
my ($thisltr, $nextltr, $axis)=@_; # axis optional and defaults to 0 |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
#warn "link_two_letters_via_interconnection"; |
311
|
|
|
|
|
|
|
#if(defined($thisltr)){$thisltr->display();} |
312
|
|
|
|
|
|
|
#if(defined($nextltr)){$nextltr->display();} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
|
315
|
329
|
|
100
|
|
|
872
|
$axis||=0; |
316
|
|
|
|
|
|
|
|
317
|
329
|
50
|
|
|
|
714
|
if ($axis>($thisltr->[LETTER__LINKED_LIST]->[LIST__CONNECTIONS_MINUS_ONE])){ |
318
|
0
|
|
|
|
|
0
|
my $max=$thisltr->[LETTER__LINKED_LIST]->[LIST__CONNECTIONS_MINUS_ONE]; |
319
|
0
|
|
|
|
|
0
|
croak "ERROR: axis greater than max number of axis for letter (axis is $axis)(max is $max)"; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# initially we have START->LAST |
323
|
|
|
|
|
|
|
# when we add letter "A", we end up with START->A->LAST, |
324
|
|
|
|
|
|
|
# this is fine for starting position connectoin |
325
|
|
|
|
|
|
|
# but parsing interconnection does not connect to FIRSTSTART or LASTSTART. |
326
|
|
|
|
|
|
|
# FIRST and LAST are placeholders and should never be parsed. |
327
|
329
|
|
|
|
|
420
|
my $firststart=$thisltr->[LETTER__LINKED_LIST]->[LIST__FIRST_START]; |
328
|
329
|
|
|
|
|
381
|
my $laststart =$thisltr->[LETTER__LINKED_LIST]->[LIST__LAST_START]; |
329
|
329
|
50
|
33
|
|
|
4318
|
if( |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
330
|
|
|
|
|
|
|
not(defined($thisltr)) |
331
|
|
|
|
|
|
|
or not(defined($nextltr)) |
332
|
|
|
|
|
|
|
or ($thisltr eq $firststart) |
333
|
|
|
|
|
|
|
or ($thisltr eq $laststart) |
334
|
|
|
|
|
|
|
or ($nextltr eq $firststart) |
335
|
|
|
|
|
|
|
or ($nextltr eq $laststart) |
336
|
|
|
|
|
|
|
){ |
337
|
|
|
|
|
|
|
# do nothing. Do not create parsing interconnection to FIRSTSTART or LASTSTART markers. |
338
|
|
|
|
|
|
|
} else { |
339
|
|
|
|
|
|
|
# both letters are valid letters, interconnect them. |
340
|
329
|
|
|
|
|
493
|
$thisltr->[LETTER__CONNECTIONS]->[$axis]->[LETTER__CONNECTION_NEXT]=$nextltr; |
341
|
329
|
|
|
|
|
1398
|
$nextltr->[LETTER__CONNECTIONS]->[$axis]->[LETTER__CONNECTION_PREV]=$thisltr; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=head2 advance_to_next_connection |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
my $next_letter = $curr_letter->advance_to_next_connection($overalldirectionforrule); |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
We are at $curr_letter, trying to fit the regular expression to string. |
351
|
|
|
|
|
|
|
The next letter will be returned by advance_to_next_connection($axis) |
352
|
|
|
|
|
|
|
where axis is which index into the array to look for the connection. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=cut |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub advance_to_next_connection { |
357
|
0
|
|
|
0
|
1
|
0
|
my ($ltrobj)=@_; |
358
|
|
|
|
|
|
|
|
359
|
0
|
|
|
|
|
0
|
my $llist = $ltrobj->[LETTER__LINKED_LIST]; |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
0
|
my $axis =$llist->[LIST__HEADING_DIRECTION_INDEX]; |
362
|
0
|
|
|
|
|
0
|
my $prevnext=$llist->[LIST__HEADING_PREVNEXT_INDEX]; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
#warn "axis "; print Dumper $axis; |
365
|
|
|
|
|
|
|
#warn "prevnext "; print Dumper $prevnext; |
366
|
|
|
|
|
|
|
|
367
|
0
|
0
|
|
|
|
0
|
if ($ltrobj->[LETTER__CONNECTIONS]->[$axis]->[$prevnext]){ |
368
|
0
|
|
|
|
|
0
|
return $ltrobj->[LETTER__CONNECTIONS]->[$axis]->[$prevnext]; |
369
|
|
|
|
|
|
|
} else { |
370
|
0
|
|
|
|
|
0
|
$ltrobj->get_more_letters("CONNECTIONS", $axis, $prevnext); |
371
|
0
|
|
|
|
|
0
|
return $ltrobj->[LETTER__CONNECTIONS]->[$axis]->[$prevnext]; |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head2 get_list_of_connecting_letters |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
return a list of possible letters to try based on parsing connections array for this letter |
382
|
|
|
|
|
|
|
and any other rules you want to use for your grammar. |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
By default, this class method will return an array of any connected letter that is not already consumed. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
You can override this behaviour by redefining the method to do whatever you want. |
387
|
|
|
|
|
|
|
You could, for example, require that the connections only go in a straight line. |
388
|
|
|
|
|
|
|
Or you could, as a counter example, allow any connection, including letters that |
389
|
|
|
|
|
|
|
have been marked as "consumed" and allow them to be used again and again. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
You might even allow the current letter to be used multiple times for multiple rules without advancing. |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=cut |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub get_list_of_connecting_letters{ |
396
|
|
|
|
|
|
|
|
397
|
66
|
|
|
66
|
1
|
104
|
my($ltrobj)=@_; |
398
|
|
|
|
|
|
|
|
399
|
66
|
|
|
|
|
119
|
my $arrayref = []; |
400
|
|
|
|
|
|
|
|
401
|
66
|
|
|
|
|
90
|
my $size = scalar(@{$ltrobj->[LETTER__CONNECTIONS]}); |
|
66
|
|
|
|
|
166
|
|
402
|
|
|
|
|
|
|
|
403
|
66
|
|
|
|
|
1117
|
for(my $firstindex=0; $firstindex<$size; $firstindex++) { |
404
|
102
|
|
|
|
|
217
|
my $connection_array_ref = $ltrobj->[LETTER__CONNECTIONS]->[$firstindex]; |
405
|
|
|
|
|
|
|
|
406
|
102
|
|
|
|
|
600
|
foreach my $secondindex (LETTER__CONNECTION_NEXT, LETTER__CONNECTION_PREV){ |
407
|
|
|
|
|
|
|
|
408
|
204
|
|
|
|
|
274
|
my $nextletter = $connection_array_ref->[$secondindex]; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
|
411
|
204
|
100
|
66
|
|
|
1606
|
if(defined($nextletter) and ($nextletter) and ($nextletter->[LETTER__LETTER_HAS_BEEN_CONSUMED]==0) ){ |
|
|
|
100
|
|
|
|
|
412
|
113
|
|
|
|
|
314
|
push(@$arrayref, $nextletter); |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
66
|
|
|
|
|
260
|
return (@$arrayref); |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=head2 delete |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
delete this letter and all previous letters |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
work your way back until we get to the first_start position. |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Note: this assumes that object connections are symmetrical. |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
if A connects to B at dimension 3, then B connects to B at dimension 3 in the opposite direction. |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub delete{ |
434
|
0
|
|
|
0
|
1
|
|
my ($ltrobj)=@_; |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# if $thisobj is firststart or laststart, then return. leave the markers alone. |
437
|
0
|
0
|
|
|
|
|
return if($ltrobj eq $ltrobj->[LETTER__LINKED_LIST]->[LIST__FIRST_START]); |
438
|
0
|
0
|
|
|
|
|
return if($ltrobj eq $ltrobj->[LETTER__LINKED_LIST]->[LIST__LAST_START]); |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# look at all connections and make sure no one points to $thisobj. |
442
|
|
|
|
|
|
|
# want $thisobj reference count to go to zero so it will be garbage collected. |
443
|
|
|
|
|
|
|
# Note that this assumes one level of symmetry: that the only thing that points |
444
|
|
|
|
|
|
|
# to $thisobj are the letters connected to $thisobj. |
445
|
|
|
|
|
|
|
# The assumption is that nothing connects to A unless A also connects to IT. |
446
|
|
|
|
|
|
|
# so if we go through all the connections for $thisobj, then we'll find and delte |
447
|
|
|
|
|
|
|
# all the connections TO $thisobj. |
448
|
0
|
|
|
|
|
|
foreach my $dimension (0 .. scalar(@{$ltrobj->[LETTER__CONNECTIONS]})) { |
|
0
|
|
|
|
|
|
|
449
|
0
|
|
|
|
|
|
foreach my $direction ( LETTER__CONNECTION_NEXT, LETTER__CONNECTION_PREV){ |
450
|
0
|
|
|
|
|
|
my $otherobj=$ltrobj->[LETTER__CONNECTIONS]->[$dimension]->[$direction]; |
451
|
0
|
0
|
0
|
|
|
|
if(defined($otherobj) and ref($otherobj)){ |
452
|
|
|
|
|
|
|
# delete anything in $otherobj connections that equals $thisobj |
453
|
|
|
|
|
|
|
# note this assumes another level of symmetry. |
454
|
|
|
|
|
|
|
# i.e. if A points to B at dimension 3, direction 0, |
455
|
|
|
|
|
|
|
# then B points to A at dimension 3, direction 1. |
456
|
0
|
0
|
|
|
|
|
my $inversedirection=($direction == LETTER__CONNECTION_NEXT) |
457
|
|
|
|
|
|
|
? LETTER__CONNECTION_PREV : LETTER__CONNECTION_NEXT; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# delete the connection from $otherobj to $thisobj. Set it to undef. |
460
|
0
|
|
|
|
|
|
$otherobj->[LETTER__CONNECTIONS]->[$dimension]->[$inversedirection]=undef; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
# get the previous_start letter |
467
|
0
|
|
|
|
|
|
my $prevstart=$ltrobj->[LETTER__PREVIOUS_START]; |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
# get the nextstart letter from thisobj |
470
|
0
|
|
|
|
|
|
my $nextstart=$ltrobj->[LETTER__NEXT_START]; |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
# if linked list currstart points to thisobj, then have ll currstart point to nextstart. |
474
|
0
|
0
|
|
|
|
|
if($ltrobj eq $ltrobj->[LETTER__LINKED_LIST]->[LIST__CURR_START]){ |
475
|
0
|
|
|
|
|
|
$ltrobj->[LETTER__LINKED_LIST]->[LIST__CURR_START] = $nextstart; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
# if prevstart is something, then it's nextstart points to thisobj, delete that reference |
481
|
|
|
|
|
|
|
# have prevstart letter point to nextstart letter so that we still have a sequence of some kind. |
482
|
|
|
|
|
|
|
# if we continue going back through prevstart, then firststart should eventually end up |
483
|
|
|
|
|
|
|
# pointing to the nextstart letter, adn we'll still be in the correct order. |
484
|
0
|
0
|
0
|
|
|
|
if( defined($prevstart) and (ref($prevstart))){ |
485
|
0
|
|
|
|
|
|
$prevstart->[LETTER__NEXT_START] = $nextstart; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# return the previous_start letter. User can loop until we return first_start. |
489
|
0
|
|
|
|
|
|
return $prevstart; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
1; |
497
|
|
|
|
|
|
|
|