File Coverage

blib/lib/WWW/Webrobot/SymbolTable.pm
Criterion Covered Total %
statement 9 67 13.4
branch 0 22 0.0
condition 0 5 0.0
subroutine 3 9 33.3
pod 5 5 100.0
total 17 108 15.7


line stmt bran cond sub pod time code
1             package WWW::Webrobot::SymbolTable;
2 28     28   145 use strict;
  28         50  
  28         989  
3 28     28   143 use warnings;
  28         59  
  28         966  
4              
5             # Author: Stefan Trcek
6             # Copyright(c) 2004 ABAS Software AG
7              
8              
9 28     28   140 use Carp;
  28         47  
  28         23564  
10              
11              
12             =head1 NAME
13              
14             WWW::Webrobot::SymbolTable - Symbol table for Webrobot properties
15              
16             =head1 SYNOPSIS
17              
18             use WWW::Webrobot::SymbolTable;
19             my $symbols = WWW::Webrobot::SymbolTable -> new();
20              
21             =head1 DESCRIPTION
22              
23             =head1 METHODS
24              
25             =over
26              
27             =item new
28              
29             Constructor
30              
31             =cut
32              
33             sub new {
34 0     0 1   my $class = shift;
35 0   0       my $self = bless({}, ref($class) || $class);
36 0           $self->{_symbols} = {};
37 0           $self->{_scope} = [{}];
38 0           return $self;
39             }
40              
41             =item $symbols->push_scope()
42              
43             Open a new scope for symbols.
44              
45             =cut
46              
47             sub push_scope {
48 0     0 1   my ($self) = @_;
49 0           push @{$self->{_scope}}, {};
  0            
50             }
51              
52             =item $symbols->pop_scope()
53              
54             Close (delete) the last scope, delete all symbols in this scope.
55              
56             =cut
57              
58             sub pop_scope {
59 0     0 1   my ($self) = @_;
60 0           my $scope = $self->{_scope};
61 0           my $symbols = $self->{_symbols};
62              
63 0           foreach (keys %{$scope->[-1]}) {
  0            
64 0           pop @{$symbols->{$_}};
  0            
65 0 0         delete $symbols->{$_} if scalar @{$symbols->{$_}} == 0;
  0            
66             }
67 0           pop @$scope;
68             }
69              
70             =item $symbols->define_symbol($name, $value)
71              
72             Define a symbol in the current scope.
73              
74             =cut
75              
76             sub define_symbol {
77 0     0 1   my ($self, $l, $r) = @_;
78 0           my $symbols = $self->{_symbols};
79 0           my $last_scope = $self->{_scope}->[-1];
80             # was: my $entry = [$l, $r || "", qr/(?
81 0   0       my $entry = $r || "";
82              
83 0 0         if ($last_scope->{$l}) { # entry exists in last scope, overwrite
84 0           $symbols->{$l}->[-1] = $entry;
85             }
86             else { # no entry yet
87 0           $last_scope->{$l} = 1;
88 0           push @{$symbols->{$l}}, $entry;
  0            
89             }
90             }
91              
92             # private
93             sub _evaluate_string {
94 0     0     my ($self, $str) = @_;
95 0 0         return undef if !defined $str;
96 0           my $symbols = $self->{_symbols};
97 0 0         $str =~ s/ \${ ([^}]+) } / $symbols->{$1} ? $symbols->{$1}->[-1] : "\${$1}" /gex;
  0            
98 0           return $str;
99             }
100              
101             =item $symbols->evaluate($string)
102              
103             Evaluate all symbols in a string.
104             The symbol variables must obey the syntax C<${name}>.
105             Returns the evaluated string.
106              
107             =cut
108              
109             sub evaluate {
110 0     0 1   my ($self, $entry) = @_;
111 0           SWITCH: foreach (ref $entry) {
112 0 0         /^HASH$/ and do {
113 0           foreach my $key (keys %$entry) {
114             # substitute value
115 0 0         if (ref $entry->{$key}) {
116 0           $self -> evaluate($entry->{$key});
117             }
118             else {
119 0           my $tmp = $entry->{$key};
120 0           $self -> evaluate(\$tmp);
121 0           $entry->{$key} = $tmp;
122             }
123              
124             # substitute key
125 0           my $nkey = $key;
126 0           $self -> evaluate(\$nkey);
127 0 0         if ($key ne $nkey) {
128 0           $entry->{$nkey} = delete $entry->{$key};
129             }
130             }
131 0           last;
132             };
133 0 0         /^ARRAY$/ and do {
134 0           foreach my $e (@$entry) {
135 0 0         $self -> evaluate((ref $e) ? $e : \$e);
136             }
137 0           last;
138             };
139 0 0         /^SCALAR$/ and do {
140 0           $$entry = $self->_evaluate_string($$entry);
141 0           last;
142             };
143 0 0         /^$/ and do {
144 0           $entry = $self->_evaluate_string($entry);
145 0           last;
146             }
147             # ??? missing error handling
148             # my $ref = ref $entry;
149             # die "ARRAY or HASH expected, found $ref";
150             }
151 0           return $entry;
152             }
153              
154              
155             =back
156              
157             =cut
158              
159             1;