annotate Lib/IMPL/Text/Parser/Player.pm @ 41:c442eb67fa22

parser in progress
author Sergey
date Mon, 21 Dec 2009 17:40:09 +0300
parents ac21a032e7a9
children 16ada169ca75
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
1 package IMPL::Text::Parser::Player;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
2 use strict;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
3 use warnings;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
4
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
5 use base qw(IMPL::Object);
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
6 use IMPL::Class::Property;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
7 use IMPL::Class::Property::Direct;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
8
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
9 use IMPL::Text::Parser::Chunk;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
10
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
11 my %opCodesMap = (
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
12 IMPL::Text::Parser::Chunk::OP_REGEXP , &MatchRegexp ,
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
13 IMPL::Text::Parser::Chunk::OP_STRING , &MatchString ,
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
14 IMPL::Text::Parser::Chunk::OP_REFERENCE , &MatchReference ,
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
15 IMPL::Text::Parser::Chunk::OP_CHUNK , &PlayChunk ,
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
16 IMPL::Text::Parser::Chunk::OP_SWITCH , &MatchSwitch ,
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
17 IMPL::Text::Parser::Chunk::OP_REPEAT , &MatchRepeat
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
18 );
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
19
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
20 BEGIN {
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
21 private _direct property _data => prop_all;
40
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
22 private _direct property _current => prop_all;
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
23 private _direct property _states => prop_all;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
24 private _direct property _document => prop_all;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
25
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
26 public _direct property errorLast => prop_all;
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
27 public _direct property Punctuation => prop_all;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
28 public _direct property Delimier => prop_all;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
29 }
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
30
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
31 sub CTOR {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
32 my ($this,$document) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
33
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
34 $this->{$_document} = $document or die new IMPL::InvalidArgumentException("The first parameter must be a document");
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
35 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
36
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
37 sub LoadString {
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
38 my ($this,$string) = @_;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
39
40
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
40 my $rxDelim = /(\s+|[.,;!-+*~$^&|%()`@\\\/])/;
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
41
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
42 my $line = 0;
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
43
40
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
44 $this->{$_data} = [
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
45 map {
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
46 $line++;
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
47 map {
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
48 [$line,$_]
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
49 } split $rxDelim, $_
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
50 } split /\n/, $string
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
51 ]
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
52 }
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
53
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
54 sub Play {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
55 my ($this) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
56 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
57
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
58 sub PlayChunk {
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
59 my ($this,$chunk) = @_;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
60
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
61 my $end = 0;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
62
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
63 my $name = $chunk->chunkName;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
64
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
65 $this->enter($name) if $name;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
66
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
67 foreach my $op ( @{$chunk->opStream} ) {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
68 $this->leave(0) and return $this->error("no more data") if $end;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
69
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
70 $opCodesMap{shift @$op}->(@$op) || return $this->leave(0) ;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
71 $this->moveNext or $end = 1;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
72 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
73
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
74 return $this->leave(1);
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
75 }
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
76
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
77 sub MatchRegexp {
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
78 my ($this,$rx) = @_;
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
79
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
80 $this->{$_current}{token} =~ $rx ? ($this->data() and return 1) : return $this->error("Expected: $rx");
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
81 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
82
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
83 sub MatchString {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
84 my ($this,$string) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
85
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
86 $this->{$_current}{token} eq $string ? ($this->data() and return 1) : return $this->error("Expected: $string");
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
87 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
88
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
89 sub MatchReference {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
90 my ($this,$name) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
91
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
92 my $chunk = $this->ResolveChunk($name) || return $this->error("Invalid reference: $name");
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
93 return $this->PlayChunk($chunk);
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
94 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
95
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
96 sub MatchSwitch {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
97 my ($this,@chunks) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
98
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
99 foreach my $chunk (@chunks) {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
100 $this->save;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
101 if ( $this->PlayChunk($chunk) ) {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
102 $this->apply;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
103 return 1;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
104 } else {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
105 $this->restore;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
106 }
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
107 }
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
108
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
109 return 0; # passthrough last error
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
110 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
111
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
112 sub MatchRepeat {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
113 my ($this,$chunk, $min, $max) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
114
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
115 my $count = 0;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
116
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
117 $this->save;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
118 while (1) {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
119 $this->save;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
120 if ($this->PlayChunk($chunk)) {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
121 $count ++;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
122 $this->apply;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
123 $this->apply and return 1 if ($count >= $max)
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
124 } else {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
125 $this->restore;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
126 $count >= $min ?
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
127 ($this->apply() and return 1) :
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
128 ($this->restore() and return $this->error("Expected at least $min occurances, got only $count"));
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
129 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
130 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
131
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
132 # we should never get here
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
133 die new IMPL::InvalidOperationException("unexpected error");
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
134 }
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
135
40
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
136 sub moveNext {
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
137 my ($this) = @_;
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
138
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
139 my $pos = $this->{$_current}{pos};
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
140
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
141 $pos ++;
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
142
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
143 if ($pos < @{$this->{$_data}}) {
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
144
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
145 $this->{$_current} = {
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
146 pos => $pos,
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
147 token => $this->{$_data}[$pos][1],
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
148 line => $this->{$_data}
40
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
149 };
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
150
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
151 } else {
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
152 $this->{$_current} = {};
40
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
153 return undef;
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
154 }
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
155 }
ac21a032e7a9 bnf parser in progress
Sergey
parents: 39
diff changeset
156
41
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
157 sub ResolveChunk {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
158 my ($this,$name) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
159 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
160
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
161 sub save {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
162 my ($this) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
163
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
164 push @{$this->{$_states}}, $this->{$_current};
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
165 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
166
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
167 sub restore {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
168 my ($this) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
169
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
170 $this->{$_current} = pop @{$this->{$_states}};
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
171 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
172
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
173 sub apply {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
174 my ($this) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
175
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
176 pop @{$this->{$_states}};
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
177 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
178
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
179 sub error {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
180 my ($this,$message) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
181
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
182 $this->{$errorLast} = {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
183 message => $message,
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
184 line => $this->{$_current}{line},
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
185 token => $this->{$_current}{token}
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
186 };
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
187
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
188 return 0;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
189 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
190
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
191 sub __debug {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
192
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
193 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
194 sub enter {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
195 my ($this,$name) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
196
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
197 #always return true;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
198 return 1;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
199 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
200
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
201 sub leave {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
202 my ($this,$isEmpty) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
203
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
204 #always return true;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
205 return 1;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
206 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
207
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
208 sub data {
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
209 my ($this) = @_;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
210
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
211 my $data = $this->{$_current}{token};
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
212
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
213 # always return true;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
214 return 1;
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
215 }
c442eb67fa22 parser in progress
Sergey
parents: 40
diff changeset
216
39
4f5a6a1bfb0e Text parser
Sergey
parents:
diff changeset
217 1;