1 package HTML::Zoom::SelectorParser;
4 use warnings FATAL => 'all';
5 use base qw(HTML::Zoom::SubObject);
9 my $sel_re = qr/([$sel_char]+)/;
11 sub new { bless({}, shift) }
13 sub _raw_parse_simple_selector {
14 for ($_[1]) { # same pos() as outside
16 # '*' - match anything
21 # 'element' - match on tag name
26 sub { $_[0]->{name} && $_[0]->{name} eq $name }
29 # '#id' - match on id attribute
34 sub { $_[0]->{attrs}{id} && $_[0]->{attrs}{id} eq $id }
37 # '.class1.class2' - match on intersection of classes
39 /\G((?:\.$sel_re)+)/gc and
41 my $cls = $1; $cls =~ s/^\.//;
42 my @cl = split(/\./, $cls);
45 && !grep $_[0]->{attrs}{class} !~ /(^|\s+)$_($|\s+)/, @cl
49 # 'el.class1' - element + class
51 /\G$sel_re\.$sel_re/gc and
56 $_[0]->{name} && $_[0]->{name} eq $name and
57 $_[0]->{attrs}{class} && $_[0]->{attrs}{class} eq $cls
61 # 'el#id' - element + id
63 /\G$sel_re#$sel_re/gc and
68 $_[0]->{name} && $_[0]->{name} eq $name and
69 $_[0]->{attrs}{id} && $_[0]->{attrs}{id} eq $id
73 confess "Couldn't parse $_ as starting with simple selector";
79 my $sel = $_[1]; # my pos() only please
80 die "No selector provided" unless $sel;
85 push(@sub, $self->_raw_parse_simple_selector($_));
86 last PARSE if (pos == length);
87 /\G\s*,\s*/gc or confess "Selectors not comma separated";
88 } until (pos == length) };
89 return $sub[0] if (@sub == 1);
91 foreach my $inner (@sub) {
92 if (my $r = $inner->(@_)) { return $r }