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
75 /\G$sel_re\[$sel_re="$sel_re"\]/gc and
81 $_[0]->{name} && $_[0]->{name} eq $name and
82 $_[0]->{attrs}{$attr} && $_[0]->{attrs}{$attr} eq $val
86 confess "Couldn't parse $_ as starting with simple selector";
92 my $sel = $_[1]; # my pos() only please
93 die "No selector provided" unless $sel;
98 push(@sub, $self->_raw_parse_simple_selector($_));
99 last PARSE if (pos == length);
100 #/\G\s*,\s*/gc or confess "Selectors not comma separated";
101 } until (pos == length) };
102 return $sub[0] if (@sub == 1);
104 foreach my $inner (@sub) {
105 if (my $r = $inner->(@_)) { return $r }