fix inject_after_scope again
[p5sagit/Filter-Keyword.git] / lib / Filter / Keyword / Parser.pm
CommitLineData
c46d1069 1package Filter::Keyword::Parser;
c46d1069 2use Moo;
3
c46d1069 4has reader => (is => 'ro', required => 1);
5
6has re_add => (is => 'ro', required => 1);
7
c15f7959 8has keywords => (is => 'ro', default => sub { [] });
c46d1069 9
c15f7959 10sub add_keyword {
11 push @{$_[0]->keywords}, $_[1];
c46d1069 12}
c15f7959 13sub remove_keyword {
14 my ($self, $keyword) = @_;
15 my $keywords = $self->keywords;
16 for my $idx (0 .. $#$keywords) {
17 if ($keywords->[$idx] eq $keyword) {
18 splice @$keywords, $idx, 1;
19 last;
20 }
21 }
c46d1069 22}
23
24has current_match => (is => 'rw');
25
26has short_circuit => (is => 'rw');
27
28has code => (is => 'rw', default => sub { '' });
29
ba6b83aa 30has current_keyword => (is => 'rw', clearer => 1);
31has keyword_matched => (is => 'rw');
b40e1ccd 32
c46d1069 33sub get_next {
34 my ($self) = @_;
35 if ($self->short_circuit) {
36 $self->short_circuit(0);
37 $self->${\$self->re_add};
38 return ('', 0);
39 }
ba6b83aa 40 if (my $keyword = $self->current_keyword) {
41 if ($self->keyword_matched) {
42 $keyword->clear_globref;
43 $self->clear_current_keyword;
44 $self->short_circuit(1);
45 return $keyword->parse($self);
46 }
47 elsif ($keyword->have_match) {
48 $self->keyword_matched(1);
b40e1ccd 49 $self->short_circuit(1);
18001adc 50 my $match = $self->current_match;
b40e1ccd 51 my $end = $match eq '{' ? '}'
52 : $match eq '(' ? ')'
53 : '';
54 return ("$end;", 1);
c15f7959 55 }
ba6b83aa 56 else {
57 $keyword->restore_shadow;
58 $self->clear_current_keyword;
59 }
c46d1069 60 }
61 return $self->check_match;
62}
63
64sub fetch_more {
65 my ($self) = @_;
66 my $code = $self->code||'';
c15f7959 67 my ($extra_code, $not_eof) = $self->reader->();
c46d1069 68 $code .= $extra_code;
69 $self->code($code);
70 return $not_eof;
71}
72
73sub match_source {
74 my ($self, $first, $second) = @_;
87f45e42 75 $self->fetch_more while $self->code =~ /\A$first\s+\z/;
76 if (my @match = ($self->code =~ /(.*?${first}\s+${second})(.*\n?)\z/)) {
77 my $code = pop @match;
78 $self->code($code);
c46d1069 79 my $found = shift(@match);
80 return ($found, \@match);
81 }
82 return;
83}
84
85sub check_match {
86 my ($self) = @_;
87 unless ($self->code) {
88 $self->fetch_more
89 or return ('', 0);
90 }
c15f7959 91 for my $keyword (@{ $self->keywords }) {
92 if (
93 my ($stripped, $matches)
94 = $self->match_source(
95 $keyword->keyword_name, qr/(\(|[A-Za-z][A-Za-z_0-9]*|{)/
96 )
97 ) {
68363889 98 $keyword->install_matcher($matches->[0]);
18001adc 99 $self->current_match($matches->[0]);
ba6b83aa 100 $self->current_keyword($keyword);
101 $self->keyword_matched(0);
c15f7959 102 $self->short_circuit(1);
103 return ($stripped, 1);
104 }
c46d1069 105 }
106 my $code = $self->code;
107 $self->code('');
108 return ($code, 1);
109}
110
1111;