line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Data::Pond - Perl-based open notation for data |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Data::Pond qw($pond_datum_rx); |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
if($expr =~ /\A$pond_datum_rx\z/o) { ... |
10
|
|
|
|
|
|
|
# and other regular expressions |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use Data::Pond qw(pond_read_datum pond_write_datum); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
$datum = pond_read_datum($text); |
15
|
|
|
|
|
|
|
$text = pond_write_datum($datum); |
16
|
|
|
|
|
|
|
$text = pond_write_datum($datum, { indent => 0 }); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 DESCRIPTION |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
This module is concerned with representing data structures in a textual |
21
|
|
|
|
|
|
|
notation known as "Pond" (I erl-based Ipen Iotation for Iata). |
22
|
|
|
|
|
|
|
The notation is a strict subset of Perl expression syntax, but is intended |
23
|
|
|
|
|
|
|
to have language-independent use. It is similar in spirit to JSON, which |
24
|
|
|
|
|
|
|
is based on JavaScript, but Pond represents fewer data types directly. |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
The data that can be represented in Pond consist of strings (of |
27
|
|
|
|
|
|
|
characters), arrays, and string-keyed hashes. Arrays and hashes can |
28
|
|
|
|
|
|
|
recursively (but not cyclically) contain any of these kinds of data. |
29
|
|
|
|
|
|
|
This does not cover the full range of data types that Perl or other |
30
|
|
|
|
|
|
|
languages can handle, but is intended to be a limited, fixed repertoire |
31
|
|
|
|
|
|
|
of data types that many languages can readily process. It is intended |
32
|
|
|
|
|
|
|
that more complex data can be represented using these basic types. |
33
|
|
|
|
|
|
|
The arrays and hashes provide structuring facilities (ordered and |
34
|
|
|
|
|
|
|
unordered collections, respectively), and strings are a convenient way |
35
|
|
|
|
|
|
|
to represent atomic data. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
The Pond syntax is a subset of Perl expression syntax, consisting of |
38
|
|
|
|
|
|
|
string literals and constructors for arrays and hashes. Strings may |
39
|
|
|
|
|
|
|
be single-quoted or double-quoted, or may be decimal integer literals. |
40
|
|
|
|
|
|
|
Double-quoted strings are restricted in which backslash sequences they |
41
|
|
|
|
|
|
|
can use: the permitted ones are the single-character ones (such as C<\n>), |
42
|
|
|
|
|
|
|
C<\x> sequences (such as C<\xe3> and C<\x{e3}>), and octal digit sequences |
43
|
|
|
|
|
|
|
(such as C<\010>). Non-ASCII characters are acceptable in quoted strings. |
44
|
|
|
|
|
|
|
Strings may also appear as pure-ASCII barewords, when they directly |
45
|
|
|
|
|
|
|
precede C<< => >> in an array or hash constructor. Array (C<[]>) and hash |
46
|
|
|
|
|
|
|
(C<{}>) constructors must contain data items separated by C<,> and C<< |
47
|
|
|
|
|
|
|
=> >> commas, and can have a trailing comma but not adjacent commas. |
48
|
|
|
|
|
|
|
Whitespace is permitted where Perl allows it. Control characters are |
49
|
|
|
|
|
|
|
not permitted, except for whitespace outside strings. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
A Pond expression can be Ced by Perl to yield the data item |
52
|
|
|
|
|
|
|
that it represents, but this is not the recommended way to do it. |
53
|
|
|
|
|
|
|
Any use of C on data opens up security issues. Instead use the |
54
|
|
|
|
|
|
|
L function of this module, which does not use Perl's |
55
|
|
|
|
|
|
|
parser but directly parses the restricted Pond syntax. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
This module is implemented in XS, with a pure Perl backup version for |
58
|
|
|
|
|
|
|
systems that can't handle XS. |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=cut |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
package Data::Pond; |
63
|
|
|
|
|
|
|
|
64
|
6
|
|
|
6
|
|
100150
|
{ use 5.008; } |
|
6
|
|
|
|
|
22
|
|
65
|
6
|
|
|
6
|
|
36
|
use warnings; |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
218
|
|
66
|
6
|
|
|
6
|
|
38
|
use strict; |
|
6
|
|
|
|
|
30
|
|
|
6
|
|
|
|
|
215
|
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
our $VERSION = "0.005"; |
69
|
|
|
|
|
|
|
|
70
|
6
|
|
|
6
|
|
2461
|
use parent "Exporter"; |
|
6
|
|
|
|
|
1519
|
|
|
6
|
|
|
|
|
37
|
|
71
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
72
|
|
|
|
|
|
|
$pond_string_rx $pond_ascii_string_rx |
73
|
|
|
|
|
|
|
$pond_array_rx $pond_ascii_array_rx |
74
|
|
|
|
|
|
|
$pond_hash_rx $pond_ascii_hash_rx |
75
|
|
|
|
|
|
|
$pond_datum_rx $pond_ascii_datum_rx |
76
|
|
|
|
|
|
|
pond_read_datum pond_write_datum |
77
|
|
|
|
|
|
|
); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head1 REGULAR EXPRESSIONS |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Each of these regular expressions corresponds precisely to part of |
82
|
|
|
|
|
|
|
Pond syntax. The regular expressions do not include any anchors, so to |
83
|
|
|
|
|
|
|
check whether an entire string matches a production you must supply the |
84
|
|
|
|
|
|
|
anchors yourself. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
The regular expressions with C<_ascii_> in the name match the subset |
87
|
|
|
|
|
|
|
of the grammar that uses only ASCII characters. All Pond data can be |
88
|
|
|
|
|
|
|
expressed using only ASCII characters. |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=over |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=item $pond_string_rx |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=item $pond_ascii_string_rx |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
A string literal. This may be a double-quoted string, a single-quoted |
97
|
|
|
|
|
|
|
string, or a decimal integer literal. It does not accept barewords. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=cut |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
my $pond_optwsp_rx = qr/[\t\n\f\r ]*/; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
my $pond_dqstringchar_rx = qr/[\ -\!\#\%-\?A-\[\]-\~\x{a1}-\x{7fffffff}]/; |
104
|
|
|
|
|
|
|
my $pond_dqstring_rx = qr/(?>"(?: |
105
|
|
|
|
|
|
|
$pond_dqstringchar_rx+ |
106
|
|
|
|
|
|
|
|\\(?:[\ -befnrt\{-\~\x{a1}-\x{7fffffff}] |
107
|
|
|
|
|
|
|
|x(?:[0-9a-fA-F]|\{[0-9a-fA-F]+\})) |
108
|
|
|
|
|
|
|
)*")/x; |
109
|
|
|
|
|
|
|
my $pond_ascii_dqstring_rx = qr/(?>"(?: |
110
|
|
|
|
|
|
|
[\ -\!\#\%-\?A-\[\]-\~]+ |
111
|
|
|
|
|
|
|
|\\(?:[\ -befnrt\{-\~] |
112
|
|
|
|
|
|
|
|x(?:[0-9a-fA-F]|\{[0-9a-fA-F]+\})) |
113
|
|
|
|
|
|
|
)*")/x; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my $pond_sqstringchar_rx = qr/[\ -\&\(-\[\]-\~\x{a1}-\x{7fffffff}]/; |
116
|
|
|
|
|
|
|
my $pond_sqstring_rx = qr/(?>'(?: |
117
|
|
|
|
|
|
|
$pond_sqstringchar_rx+ |
118
|
|
|
|
|
|
|
|\\[\ -\~\x{a1}-\x{7fffffff}] |
119
|
|
|
|
|
|
|
)*')/x; |
120
|
|
|
|
|
|
|
my $pond_ascii_sqstring_rx = qr/(?>'(?: |
121
|
|
|
|
|
|
|
[\ -\&\(-\[\]-\~]+ |
122
|
|
|
|
|
|
|
|\\[\ -\~] |
123
|
|
|
|
|
|
|
)*')/x; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
my $pond_number_rx = qr/0|[1-9][0-9]*/; |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
our $pond_string_rx = qr/$pond_dqstring_rx |
128
|
|
|
|
|
|
|
|$pond_sqstring_rx |
129
|
|
|
|
|
|
|
|$pond_number_rx/xo; |
130
|
|
|
|
|
|
|
our $pond_ascii_string_rx = qr/$pond_ascii_dqstring_rx |
131
|
|
|
|
|
|
|
|$pond_ascii_sqstring_rx |
132
|
|
|
|
|
|
|
|$pond_number_rx/xo; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
my $pond_bareword_rx = qr/(?>[A-Za-z_][0-9A-Za-z_]*(?=$pond_optwsp_rx=>))/o; |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
my $pond_interior_string_rx = qr/$pond_bareword_rx|$pond_string_rx/o; |
137
|
|
|
|
|
|
|
my $pond_ascii_interior_string_rx = |
138
|
|
|
|
|
|
|
qr/$pond_bareword_rx|$pond_ascii_string_rx/o; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item $pond_array_rx |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item $pond_ascii_array_rx |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
An array C<[]> constructor. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=cut |
147
|
|
|
|
|
|
|
|
148
|
6
|
|
|
6
|
|
1924
|
my $pond_interior_datum_rx = do { use re "eval"; |
|
6
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
512
|
|
149
|
|
|
|
|
|
|
qr/$pond_bareword_rx|(??{$Data::Pond::pond_datum_rx})/o |
150
|
|
|
|
|
|
|
}; |
151
|
6
|
|
|
6
|
|
40
|
my $pond_ascii_interior_datum_rx = do { use re "eval"; |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
2254
|
|
152
|
|
|
|
|
|
|
qr/$pond_bareword_rx|(??{$Data::Pond::pond_ascii_datum_rx})/o |
153
|
|
|
|
|
|
|
}; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my $pond_comma_rx = qr/,|=>/; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
our $pond_array_rx = qr/(?>\[$pond_optwsp_rx |
158
|
|
|
|
|
|
|
(?>$pond_interior_datum_rx$pond_optwsp_rx |
159
|
|
|
|
|
|
|
$pond_comma_rx$pond_optwsp_rx)* |
160
|
|
|
|
|
|
|
(?:$pond_interior_datum_rx$pond_optwsp_rx)? |
161
|
|
|
|
|
|
|
\])/xo; |
162
|
|
|
|
|
|
|
our $pond_ascii_array_rx = qr/(?>\[$pond_optwsp_rx |
163
|
|
|
|
|
|
|
(?>$pond_ascii_interior_datum_rx$pond_optwsp_rx |
164
|
|
|
|
|
|
|
$pond_comma_rx$pond_optwsp_rx)* |
165
|
|
|
|
|
|
|
(?:$pond_ascii_interior_datum_rx$pond_optwsp_rx)? |
166
|
|
|
|
|
|
|
\])/xo; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=item $pond_hash_rx |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=item $pond_ascii_hash_rx |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
A hash C<{}> constructor. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=cut |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
my $pond_hashelem_rx = qr/ |
177
|
|
|
|
|
|
|
$pond_interior_string_rx$pond_optwsp_rx |
178
|
|
|
|
|
|
|
$pond_comma_rx$pond_optwsp_rx$pond_interior_datum_rx |
179
|
|
|
|
|
|
|
/xo; |
180
|
|
|
|
|
|
|
my $pond_ascii_hashelem_rx = qr/ |
181
|
|
|
|
|
|
|
$pond_ascii_interior_string_rx$pond_optwsp_rx |
182
|
|
|
|
|
|
|
$pond_comma_rx$pond_optwsp_rx$pond_ascii_interior_datum_rx |
183
|
|
|
|
|
|
|
/xo; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
our $pond_hash_rx = qr/(?>\{$pond_optwsp_rx |
186
|
|
|
|
|
|
|
(?>$pond_hashelem_rx$pond_optwsp_rx$pond_comma_rx$pond_optwsp_rx)* |
187
|
|
|
|
|
|
|
(?:$pond_hashelem_rx$pond_optwsp_rx)? |
188
|
|
|
|
|
|
|
\})/xo; |
189
|
|
|
|
|
|
|
our $pond_ascii_hash_rx = qr/(?>\{$pond_optwsp_rx |
190
|
|
|
|
|
|
|
(?>$pond_ascii_hashelem_rx$pond_optwsp_rx$pond_comma_rx$pond_optwsp_rx)* |
191
|
|
|
|
|
|
|
(?:$pond_ascii_hashelem_rx$pond_optwsp_rx)? |
192
|
|
|
|
|
|
|
\})/xo; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item $pond_datum_rx |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=item $pond_ascii_datum_rx |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Any permitted expression. This may be a string literal, array |
199
|
|
|
|
|
|
|
constructor, or hash constructor. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=cut |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
our $pond_datum_rx = qr/$pond_string_rx |
204
|
|
|
|
|
|
|
|$pond_array_rx |
205
|
|
|
|
|
|
|
|$pond_hash_rx/xo; |
206
|
|
|
|
|
|
|
our $pond_ascii_datum_rx = qr/$pond_ascii_string_rx |
207
|
|
|
|
|
|
|
|$pond_ascii_array_rx |
208
|
|
|
|
|
|
|
|$pond_ascii_hash_rx/xo; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=back |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=cut |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
eval { local $SIG{__DIE__}; |
215
|
|
|
|
|
|
|
require XSLoader; |
216
|
|
|
|
|
|
|
XSLoader::load(__PACKAGE__, $VERSION); |
217
|
|
|
|
|
|
|
}; |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
if($@ eq "") { |
220
|
|
|
|
|
|
|
close(DATA); |
221
|
|
|
|
|
|
|
} else { |
222
|
|
|
|
|
|
|
(my $filename = __FILE__) =~ tr# -~##cd; |
223
|
|
|
|
|
|
|
local $/ = undef; |
224
|
3
|
|
|
3
|
|
1389
|
my $pp_code = "#line 223 \"$filename\"\n".; |
|
3
|
|
|
|
|
5581
|
|
|
3
|
|
|
|
|
4620
|
|
225
|
|
|
|
|
|
|
close(DATA); |
226
|
|
|
|
|
|
|
{ |
227
|
|
|
|
|
|
|
local $SIG{__DIE__}; |
228
|
|
|
|
|
|
|
eval $pp_code; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
die $@ if $@ ne ""; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
1; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
__DATA__ |