CSS parser implementation rox
Rok Ružič [Thu, 3 Jun 2010 13:37:04 +0000 (15:37 +0200)]
lib/HTML/Zoom/CSSParser.pm [new file with mode: 0644]

diff --git a/lib/HTML/Zoom/CSSParser.pm b/lib/HTML/Zoom/CSSParser.pm
new file mode 100644 (file)
index 0000000..b2daa13
--- /dev/null
@@ -0,0 +1,89 @@
+package CSSParser;
+
+use strict;
+use Data::Dump::Streamer;
+
+#############################################################################
+#
+# This thing is an array of hashes with these keys
+# 
+# simple - a CSS simple selector
+# slide - whether to slide the whole thing down to descendents
+# match - where to pass the chain on match
+#
+#############################################################################
+
+sub new {
+       my $string = shift;
+       # first split by aggregator
+       my $chains = [];
+       
+       my @selectors = split /\s*,\s*/, $string;
+       for my $selector (@selectors){
+               push @$chains, parse_selector($selector);
+       }
+       return $chains;
+}
+
+# the universal selector is deliberately ignored, in Rezoom it is only 
+# supported in its implied form
+sub parse_selector {
+       my $string = shift;
+       my (@tokens, @chain);
+
+       # split on combinators
+       for my $match (split(/\s*([ >+~])\s*/, $string)){
+               Dump($match);
+               # split on simple selector modifiers
+               push(@tokens, split(/([.#\[:])/, $match));
+       }
+       # now we got all selector modifiers, combinators and values separated
+       # convert them into our selector hashes
+       @tokens = grep !/\A\Z/, @tokens;
+
+       unshift @tokens, ' '; #add default combinator 
+       while (@tokens){
+               my %selector;
+               my $combinator = shift @tokens;
+
+               if($combinator eq ' '){
+                       $selector{slide} = 1;
+               }
+               elsif($combinator =~ /[+~>]/){
+                       $selector{slide} = 0;
+               }
+               else{
+                       $selector{slide} = 0;
+                       unshift @tokens, $combinator;
+               }
+               
+               my $simple = shift @tokens;
+               
+               # glue together selector modifiers with their values
+               if($simple =~ m/[.\:\[#]/){
+                       $simple .= shift @tokens;
+               }
+
+               $selector{simple} = $simple;
+
+
+
+               if($tokens[0] =~ /[ >]/){
+                       $selector{match} = 'children';
+               }
+               elsif($tokens[0] eq '+'){
+                       $selector{match} = 'nextsibling';
+               }
+               elsif($tokens[0] eq '~'){
+                       $selector{match} = 'siblings';
+               }
+               else{
+                       $selector{match} = 'self';
+               }
+               
+               push @chain, \%selector;
+       }
+       return \@chain;
+}
+
+1;