CSS parser implementation
[catagits/HTML-Zoom.git] / lib / HTML / Zoom / CSSParser.pm
1 package CSSParser;
2
3 use strict;
4 use Data::Dump::Streamer;
5
6 #############################################################################
7 #
8 # This thing is an array of hashes with these keys
9
10 # simple - a CSS simple selector
11 # slide - whether to slide the whole thing down to descendents
12 # match - where to pass the chain on match
13 #
14 #############################################################################
15
16 sub new {
17         my $string = shift;
18         # first split by aggregator
19         my $chains = [];
20         
21         my @selectors = split /\s*,\s*/, $string;
22         for my $selector (@selectors){
23                 push @$chains, parse_selector($selector);
24         }
25         return $chains;
26 }
27
28 # the universal selector is deliberately ignored, in Rezoom it is only 
29 # supported in its implied form
30 sub parse_selector {
31         my $string = shift;
32         my (@tokens, @chain);
33
34         # split on combinators
35         for my $match (split(/\s*([ >+~])\s*/, $string)){
36                 Dump($match);
37                 # split on simple selector modifiers
38                 push(@tokens, split(/([.#\[:])/, $match));
39         }
40         # now we got all selector modifiers, combinators and values separated
41         # convert them into our selector hashes
42         @tokens = grep !/\A\Z/, @tokens;
43
44         unshift @tokens, ' '; #add default combinator 
45         while (@tokens){
46                 my %selector;
47                 my $combinator = shift @tokens;
48
49                 if($combinator eq ' '){
50                         $selector{slide} = 1;
51                 }
52                 elsif($combinator =~ /[+~>]/){
53                         $selector{slide} = 0;
54                 }
55                 else{
56                         $selector{slide} = 0;
57                         unshift @tokens, $combinator;
58                 }
59                 
60                 my $simple = shift @tokens;
61                 
62                 # glue together selector modifiers with their values
63                 if($simple =~ m/[.\:\[#]/){
64                         $simple .= shift @tokens;
65                 }
66
67                 $selector{simple} = $simple;
68
69
70
71                 if($tokens[0] =~ /[ >]/){
72                         $selector{match} = 'children';
73                 }
74                 elsif($tokens[0] eq '+'){
75                         $selector{match} = 'nextsibling';
76                 }
77                 elsif($tokens[0] eq '~'){
78                         $selector{match} = 'siblings';
79                 }
80                 else{
81                         $selector{match} = 'self';
82                 }
83                 
84                 push @chain, \%selector;
85         }
86         return \@chain;
87 }
88
89 1;