File Coverage

blib/lib/PDA/Simple.pm
Criterion Covered Total %
statement 6 171 3.5
branch 0 64 0.0
condition 0 30 0.0
subroutine 2 12 16.6
pod 5 10 50.0
total 13 287 4.5


line stmt bran cond sub pod time code
1             package PDA::Simple;
2 1     1   1039 use 5.008005;
  1         4  
  1         48  
3 1     1   998 use Mouse;
  1         37193  
  1         6  
4              
5             our $VERSION = "0.01";
6              
7             has 'stack_init' => (
8             is => 'rw',
9             isa => 'Str',
10             default => '__INIT__'
11             );
12              
13             has 'init_state' => (
14             is => 'rw',
15             isa => 'Str',
16             default => '__INIT__'
17             );
18             has 'final_state' => (
19             is => 'rw',
20             isa => 'Str',
21             default => '__FINAL__'
22             );
23             has 'acceptable_state' => (
24             is => 'rw',
25             isa => 'Str',
26             default => '__ACCEPTABLE__'
27             );
28             has 'acceptable' => (
29             is => 'rw',
30             isa => 'Num',
31             default => 0
32             );
33             has 'stack_s' => (
34             is => 'rw',
35             isa => 'ArrayRef[Str]',
36             default => sub {[]}
37             );
38              
39             has 'stack_a' => (
40             is => 'rw',
41             isa => 'ArrayRef[Str]',
42             default => sub {[]}
43             );
44              
45             has 'stack_b' => (
46             is => 'rw',
47             isa => 'ArrayRef[Str]',
48             default => sub {[]}
49             );
50              
51             has 'model' => (
52             is => 'rw',
53             isa => 'HashRef',
54             default => sub {
55             {
56             '__INIT__' => {},
57             '__FINAL__' => {}
58             }
59             }
60             );
61              
62             has 'acceptables' => (
63             is => 'rw',
64             isa => 'HashRef',
65             default => sub {{}}
66             );
67              
68              
69              
70             sub add_state{
71 0     0 1   my $self = shift;
72 0           my $state_name = shift;
73 0           my $model = $self->model;
74 0 0         if(defined($model->{$state_name})){
75 0           warn "$state_name : Already exist\n";
76             }else{
77 0           $model->{$state_name} = {};
78 0           $self->model($model);
79             }
80             }
81              
82             sub add_acceptables{
83 0     0 0   my $self = shift;
84 0           my $state = shift;
85 0           my $acceptables = $self->acceptables;
86 0 0 0       if(($state eq $self->init_state) or ($state eq $self->final_state)){
87 0           warn "can't add acceptables\n";
88             }else{
89 0 0         unless(defined($acceptables->{$state})){
90 0           $acceptables->{$state} = 1;
91             }
92             }
93             }
94              
95              
96             sub add_trans{
97 0     0 1   my $self = shift;
98 0           my $from_state = shift;
99 0           my $to_state = shift;
100 0           my $input = shift;
101 0           my $push_or_pop = shift;
102 0 0         unless(defined($push_or_pop)){
103 0           $push_or_pop = 'no';
104             }
105 0 0 0       if(($push_or_pop ne 'push') and ($push_or_pop ne 'pop') and ($push_or_pop ne 'no')){
      0        
106 0           $push_or_pop = 'no';
107             }
108 0           my $model = $self->model;
109 0 0         if($from_state eq $self->final_state){
    0          
110 0           warn "can't add this transition: from final state\n";
111 0           return 0;
112             }elsif($to_state eq $self->init_state){
113 0           warn "can't add this transition: to initial state\n";
114 0           return 0;
115             }else{
116 0 0         if(defined($model->{$from_state})){
117 0           my $trans_func = $model->{$from_state};
118 0 0         if(defined($trans_func->{$input})){
119 0           warn "$input : $from_state : Already exists\n";
120 0           return 0;
121             }else{
122 0           $trans_func->{$input} = {
123             to_state => $to_state,
124             operation => $push_or_pop
125             };
126 0           $model->{$from_state} = $trans_func;
127 0           return 1;
128             }
129             }else{
130 0           warn "$from_state : No such state.\n";
131 0           return 0;
132             }
133             }
134             }
135              
136             sub add_trans_to_final{
137 0     0 1   my $self = shift;
138 0           my $from_state = shift;
139 0           my $input = shift;
140 0           my $push_or_pop = shift;
141 0 0         unless(defined($push_or_pop)){
142 0           $push_or_pop = 'push';
143             }
144 0 0 0       if(($push_or_pop ne 'push') and ($push_or_pop ne 'pop') and ($push_or_pop ne 'no')){
      0        
145 0           $push_or_pop = 'no';
146             }
147              
148 0           my $to_state = $self->final_state;
149 0           my $model = $self->model;
150 0 0         if($from_state eq $self->final_state){
151 0           warn "can't add this transition: from final state\n";
152 0           return 0;
153             }else{
154 0 0         if(defined($model->{$from_state})){
155 0           my $trans_func = $model->{$from_state};
156 0 0         if(defined($trans_func->{$input})){
157 0           warn "$input of $from_state : Already exist\n";
158 0           return 0;
159             }else{
160 0           $trans_func->{$input} = {
161             to_state => $to_state,
162             operation => $push_or_pop
163             };
164 0           $model->{$from_state} = $trans_func;
165 0           return 1;
166             }
167             }else{
168 0           warn "$from_state : No such state.\n";
169 0           return 0;
170             }
171             }
172             }
173              
174             sub add_trans_from_init{
175 0     0 1   my $self = shift;
176 0           my $to_state = shift;
177 0           my $input = shift;
178 0           my $push_or_pop = shift;
179 0 0         unless(defined($push_or_pop)){
180 0           $push_or_pop = 'push';
181             }
182 0 0 0       if(($push_or_pop ne 'push') and ($push_or_pop ne 'pop') and ($push_or_pop ne 'no')){
      0        
183 0           $push_or_pop = 'no';
184             }
185              
186 0           my $from_state = $self->init_state;
187 0           my $model = $self->model;
188 0 0         if($to_state eq $self->init_state){
189 0           warn "can't add this transition: to initial state\n";
190 0           return 0;
191             }else{
192 0 0         if(defined($model->{$self->init_state})){
193 0           my $trans_func = $model->{$self->init_state};
194 0 0         if(defined($trans_func->{$input})){
195 0           warn "$input of ".$self->init_state." : Already exist\n";
196 0           return 0;
197             }else{
198 0           $trans_func->{$input} = {
199             to_state => $to_state,
200             operation => $push_or_pop
201             };
202 0           $model->{$self->init_state} = $trans_func;
203 0           return 1;
204             }
205             }else{
206 0           warn $self->init_state." : No INIT state!!\n";
207 0           return 0;
208             }
209             }
210             }
211              
212             sub reset_state{
213 0     0 0   my $self = shift;
214 0           $self->stack_s([]);
215 0           $self->stack_a([]);
216 0           $self->stack_b([]);
217 0           $self->acceptable(0);
218 0           return 1;
219             }
220              
221             sub export_model{
222 0     0 0   my $self = shift;
223 0           return($self->model);
224             }
225              
226             sub import_model{
227 0     0 0   my $self = shift;
228 0           my $model = shift;
229 0 0 0       if(defined($model->{$self->init_state}) and
230             defined($model->{$self->final_state})){
231 0           $self->model($model);
232 0           return 1;
233             }else{
234 0           warn "import_model : this model has no init state or final state\n";
235 0           return;
236             }
237             }
238              
239             sub transit{
240 0     0 1   my $self = shift;
241 0           my $input = shift;
242 0           my $attr = shift;
243 0           my $model = $self->model;
244 0           my $acceptables = $self->acceptables;
245 0           my $stack_s = $self->stack_s;
246 0           my $stack_a = $self->stack_a;
247 0           my $stack_b = $self->stack_b;
248            
249 0           my $current_state = $self->init_state;
250 0 0         if(defined($stack_s->[$#$stack_s])){
251 0           $current_state = $stack_s->[$#$stack_s];
252             }else{
253 0           $stack_s = [$self->stack_init];
254 0           $self->stack_s($stack_s);
255             }
256 0           print "Current STATE : $current_state\n";
257 0           my $trans = $model->{$current_state};
258 0 0         if(defined($trans->{$input})){
259 0           my $next_state = $trans->{$input}->{to_state};
260 0           print "Next STATE : $next_state\n";
261 0 0         if(defined($acceptables->{$next_state})){
262 0           $self->acceptable(1);
263             }
264 0 0         if($next_state eq $self->final_state){
265 0 0         if($trans->{$input}->{operation} eq 'push'){
    0          
266 0           push(@$stack_s,$next_state);
267             }elsif($trans->{$input}->{operation} eq 'pop'){
268 0           pop(@$stack_s);
269             }
270 0           push(@$stack_a,$input);
271 0           push(@$stack_b,$attr);
272 0           $self->reset_state();
273             return ({
274 0           state => $next_state,
275             stack_s => $stack_s,
276             stack_a => $stack_a,
277             stack_b => $stack_b
278             });
279             }else{
280 0 0         if($trans->{$input}->{operation} eq 'push'){
    0          
281 0           push(@$stack_s,$next_state);
282             }elsif($trans->{$input}->{operation} eq 'pop'){
283 0           pop(@$stack_s);
284             }
285 0 0         if($stack_s->[$#$stack_s] eq $self->stack_init){
286 0           push(@$stack_a,$input);
287 0           push(@$stack_b,$attr);
288 0           $self->reset_state();
289             return ({
290 0           state => $next_state,
291             stack_s => $stack_s,
292             stack_a => $stack_a,
293             stack_b => $stack_b
294             });
295             }else{
296 0           push(@$stack_a,$input);
297 0           push(@$stack_b,$attr);
298 0           $self->stack_s($stack_s);
299 0           $self->stack_a($stack_a);
300 0           $self->stack_b($stack_b);
301 0           return;
302             }
303             }
304             }else{
305 0 0         if($self->acceptable == 1){
306 0           push(@$stack_s,$self->acceptable_state);
307 0           push(@$stack_a,$input);
308 0           push(@$stack_b,$attr);
309 0           $self->reset_state();
310             return ({
311 0           state => $self->acceptable,
312             stack_s => $stack_s,
313             stack_a => $stack_a,
314             stack_b => $stack_b
315             });
316             }else{
317 0           $self->reset_state();
318 0           return;
319             }
320             }
321             }
322              
323             sub delete_dead_state{
324 0     0 0   my $self = shift;
325 0           my $model = $self->model;
326 0           my $refered;
327 0           my $delete_count = 0;
328 0           foreach my $key (sort keys %$model){
329 0           my $state = $model->{$key};
330 0           foreach my $input (sort keys %$state){
331 0           $refered->{$state->{$input}->{to_state}} = 1;
332             }
333             }
334 0           foreach my $key (sort keys %$model){
335 0 0 0       if(($key ne $self->init_state) and ($key ne $self->final_state)){
336 0 0 0       unless(defined($model->{$key}) or defined($refered->{$key})){
337 0           delete $model->{$key};
338 0           $delete_count++;
339             }
340             }
341             }
342 0           $self->model($model);
343 0           return($delete_count);
344             }
345              
346              
347              
348              
349             1;
350             __END__