File Coverage

blib/lib/TM/Literal.pm
Criterion Covered Total %
statement 10 24 41.6
branch 0 8 0.0
condition 2 17 11.7
subroutine 3 10 30.0
pod 0 7 0.0
total 15 66 22.7


line stmt bran cond sub pod time code
1             package TM::Literal;
2              
3             =pod
4              
5             =head1 NAME
6              
7             TM::Literal - Topic Maps, simple values (literals)
8              
9             =head2 SYNOPSIS
10              
11             use TM::Literal;
12             my $l = new TM::Literal (42, 'xsd:integer');
13              
14             print $l->[0]; # prints 42
15             print $l->[1]; # prints http://www.w3.org/2001/XMLSchema#integer
16              
17             $l = new TM::Literal (42); # default is xsd:string
18              
19             =head1 DESCRIPTION
20              
21             This packages will eventually handle all literal handling, i.e. not only a way to create and
22             retrieve information about simple values used inside topic maps, but also all necessary operations
23             such as I, I.
24              
25             This is quite a chore, especially since the data types adopted here are the XML Schema Data Types.
26              
27             =head2 Constants
28              
29             XSD http://www.w3.org/2001/XMLSchema#
30             INTEGER http://www.w3.org/2001/XMLSchema#integer
31             DECIMAL http://www.w3.org/2001/XMLSchema#decimal
32             FLOAT http://www.w3.org/2001/XMLSchema#float
33             DOUBLE http://www.w3.org/2001/XMLSchema#double
34             STRING http://www.w3.org/2001/XMLSchema#string
35             URI http://www.w3.org/2001/XMLSchema#anyURI
36             ANY http://www.w3.org/2001/XMLSchema#anyType
37              
38             =head2 Grammar
39              
40             TODO
41              
42             =head2 Operations
43              
44             TODO
45              
46             =cut
47              
48 9     9   138977 use constant XSD => "http://www.w3.org/2001/XMLSchema#";
  9         21  
  9         1431  
49              
50             use constant {
51 9         17914 INTEGER => XSD.'integer',
52             DECIMAL => XSD.'decimal',
53             FLOAT => XSD.'float',
54             DOUBLE => XSD.'double',
55             BOOLEAN => XSD.'boolean',
56             STRING => XSD.'string',
57             URI => XSD.'anyURI',
58             ANY => XSD.'anyType',
59 9     9   50 };
  9         18  
60              
61             sub new {
62 2108     2108 0 4219 my ($class, $val, $type) = @_;
63              
64 2108   100     5036 $type ||= STRING;
65 2108         4186 $type =~ s/^xsd:/XSD/e;
  0         0  
66 2108         11731 return bless [ $val, $type ],$class;
67             }
68              
69              
70              
71             our $grammar = q{
72              
73             literal : decimal { $return = new TM::Literal ($item[1], TM::Literal->DECIMAL); }
74             | integer { $return = new TM::Literal ($item[1], TM::Literal->INTEGER); }
75             | boolean { $return = new TM::Literal ($item[1], TM::Literal->BOOLEAN); }
76             | wuri { $return = new TM::Literal ($item[1], TM::Literal->URI); }
77             | string
78             # TODO | date
79              
80             integer : /-?\d+/
81              
82             decimal : /-?\d+\.\d+/
83             # TODO: optional .234?)
84              
85             string : /\"{3}(.*?)\"{3}/s ('^^' iri)(?) { $return = new TM::Literal ($1, $item[2]->[0] || TM::Literal->STRING); }
86             | /\"([^\n]*?)\"/ ('^^' iri)(?) { $return = new TM::Literal ($1, $item[2]->[0] || TM::Literal->STRING); }
87              
88             # string : quoted_string
89             # | triple_quoted_string
90             #
91             # quoted_string : '"' /[^\"]*/ '"' { $return = $item[2]; }
92             #
93             # triple_quoted_string : '"""' /([^\"]|\"(?!""))*/ '"""' { $return = $item[2]; }
94              
95              
96             boolean : 'true' | 'false'
97              
98             wuri : '<' iri '>' { $item[2] }
99              
100             uri : /(\w+:[^\"\s)\]\>]+)/
101              
102             iri : /\w[\w\d\+\-\.]+:\/([^\.\s:;]|\.(?!\s)|:(?!\s)|;(?!\s))+/
103             # | '<' ... '>'
104             | qname # other implementation has to provide this!
105              
106             # an option? the official pattern -> perldoc URI
107             # uri : m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
108              
109              
110             };
111              
112             our $comparators = {
113             ( INTEGER ) => sub { return $_[0] == $_[1]; },
114             ( DECIMAL ) => sub { return $_[0] == $_[1]; },
115             ( FLOAT ) => sub { return $_[0] == $_[1]; },
116             ( DOUBLE ) => sub { return $_[0] == $_[1]; },
117             ( STRING ) => sub { return $_[0] eq $_[1]; },
118             };
119              
120             our $operators = {
121             '+' => {
122             (INTEGER) => {
123             (INTEGER) => \&op_numeric_add,
124             },
125             (DECIMAL) => {
126             (DECIMAL) => \&op_numeric_add,
127             },
128             (FLOAT) => {
129             (FLOAT) => \&op_numeric_add,
130             },
131             (DOUBLE) => {
132             (DOUBLE) => \&op_numeric_add,
133             },
134             },
135             '-' => {
136             (INTEGER) => {
137             (INTEGER) => \&op_numeric_subtract,
138             },
139             (DECIMAL) => {
140             (DECIMAL) => \&op_numeric_subtract,
141             },
142             (FLOAT) => {
143             (FLOAT) => \&op_numeric_subtract,
144             },
145             (DOUBLE) => {
146             (DOUBLE) => \&op_numeric_subtract,
147             },
148             },
149             '*' => {
150             (INTEGER) => {
151             (INTEGER) => \&op_numeric_multiply,
152             },
153             (DECIMAL) => {
154             (DECIMAL) => \&op_numeric_multiply,
155             },
156             (FLOAT) => {
157             (FLOAT) => \&op_numeric_multiply,
158             },
159             (DOUBLE) => {
160             (DOUBLE) => \&op_numeric_multiply,
161             },
162             },
163             'div' => {
164             (INTEGER) => {
165             (INTEGER) => \&op_numeric_divide,
166             },
167             (DECIMAL) => {
168             (DECIMAL) => \&op_numeric_divide,
169             },
170             (FLOAT) => {
171             (FLOAT) => \&op_numeric_divide,
172             },
173             (DOUBLE) => {
174             (DOUBLE) => \&op_numeric_divide,
175             },
176             },
177             '==' => {
178             (INTEGER) => {
179             (INTEGER) => \&cmp_numeric_eq,
180             },
181             (DECIMAL) => {
182             (DECIMAL) => \&cmp_numeric_eq,
183             },
184             (FLOAT) => {
185             (FLOAT) => \&cmp_numeric_eq,
186             },
187             (DOUBLE) => {
188             (DOUBLE) => \&cmp_numeric_eq,
189             },
190             },
191             };
192              
193             our %OPS = (
194             'tmql:add_int_int' => \&TM::Literal::op_numeric_add
195             );
196              
197             sub _lub {
198 0     0     my $a = shift;
199 0           my $b = shift;
200              
201 0 0 0       if ( $a eq DOUBLE || $b eq DOUBLE) {
    0 0        
    0 0        
202 0           return DOUBLE;
203             } elsif ($a eq FLOAT || $b eq FLOAT) {
204 0           return FLOAT;
205             } elsif ($a eq DECIMAL || $b eq DECIMAL) {
206 0           return DECIMAL;
207             } else {
208 0           return INTEGER;
209             }
210             }
211              
212             sub op_numeric_add { # (A, B)
213 0     0 0   return new TM::Literal ($_[0]->[0] + $_[1]->[0], _lub ($_[0]->[1], $_[1]->[1]));
214             }
215              
216             sub op_numeric_subtract { # (A, B)
217 0     0 0   return new TM::Literal ($_[0]->[0] - $_[1]->[0], _lub ($_[0]->[1], $_[1]->[1]));
218             }
219              
220             sub op_numeric_multiply { # (A, B)
221 0     0 0   return new TM::Literal ($_[0]->[0] * $_[1]->[0], _lub ($_[0]->[1], $_[1]->[1]));
222             }
223              
224             sub op_numeric_divide { # (A, B)
225 0 0 0 0 0   return new TM::Literal ($_[0]->[0] / $_[1]->[0],
226             $_[0]->[1] eq INTEGER && $_[1]->[1] eq INTEGER ?
227             INTEGER :
228             DECIMAL);
229             ## @@ needs to be fixed
230             }
231              
232             sub op_numeric_integer_divide { # (A, B)
233 0     0 0   return new TM::Literal (int ($_[0]->[0] / $_[1]->[0]), 'xsd:integer');
234             }
235              
236             sub cmp_numeric_eq {
237 0   0 0 0   return $_[0]->[0] == $_[1]->[0] && $_[0]->[1] eq $_[1]->[1];
238             }
239              
240              
241              
242              
243             =pod
244              
245             =head1 SEE ALSO
246              
247             L
248              
249             =head1 COPYRIGHT AND LICENSE
250              
251             Copyright 200[6] by Robert Barta, Edrrho@cpan.orgE
252              
253             This library is free software; you can redistribute it and/or modify it under the same terms as Perl
254             itself.
255              
256             =cut
257              
258             our $VERSION = 0.1;
259             our $REVISION = '$Id: Literal.pm,v 1.10 2006/12/29 09:33:42 rho Exp $';
260              
261             1;