diff --git a/Makefile b/Makefile
index 404517de9bad6f0e3e512c4283ccb26bbea00de0..d8cd24373e7418038cec2af596c4cd148cf5a272 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
 RESULT    := mincss
 PRE_TGTS  := types
-MODULES   := color_names util stringify parser lexer parse color shorthand main
+MODULES   := color_names util stringify parser lexer parse color \
+             shorthand main
 ALL_NAMES := $(PRE_TGTS) $(MODULES)
 
 OCAMLCFLAGS  := -g
diff --git a/parser.mly b/parser.mly
index 3dac561b11e0a2085ef5f17ef355ca86b3410dc1..4b05e3f4e93a17f5a2369b38d62424b93e1b0f6f 100644
--- a/parser.mly
+++ b/parser.mly
@@ -37,6 +37,18 @@
     | Unary ("-", Number (n, u)) -> Number (-.n, u)
     | Unary ("+", (Number _ as n)) -> n
     | value -> value
+
+  let rec append_addons base = function
+    | [] ->
+      base
+    | `Id id :: tl ->
+      append_addons (Id (base, id)) tl
+    | `Class cls :: tl ->
+      append_addons (Class (base, cls)) tl
+    | `Attribute (attr, value) :: tl ->
+      append_addons (Attribute (base, attr, value)) tl
+    | `Pseudo (f, args) :: tl ->
+      append_addons (Pseudo (base, f, args)) tl
 %}
 
 (* Tokens *)
@@ -207,39 +219,44 @@ ruleset:
 
 selector:
   | simple=simple_selector S*
-  { Simple simple }
+  { simple }
   | left=simple_selector S+ right=selector
-  { Combinator (Simple left, " ", right) }
+  { Combinator (left, " ", right) }
   | left=simple_selector S* com=combinator right=selector
-  { Combinator (Simple left, com, right) }
+  { Combinator (left, com, right) }
 %inline combinator:
   | PLUS S*          { "+" }
   | c=COMBINATOR S*  { c }
 
 simple_selector:
   | elem=element_name addons=element_addon*
-  { elem ^ String.concat "" addons }
+  { append_addons elem addons }
   | addons=element_addon+
-  { String.concat "" addons }
-%inline element_addon: a=HASH | a=cls | a=attrib | a=pseudo { a }
+  { append_addons No_element addons }
+%inline element_addon:
+  | id=HASH       { `Id id }
+  | addon=cls
+  | addon=attrib
+  | addon=pseudo  { addon }
 element_name:
-  | tag=IDENT  { String.lowercase tag }
-  | STAR       { "*" }
+  | tag=IDENT  { Element (String.lowercase tag) }
+  | STAR       { All_elements }
 cls:
   | DOT name=IDENT
-  { "." ^ name }
+  { `Class name }
 attrib:
-  | LBRACK S* left=IDENT S* right=pair(RELATION, rel_value)? RBRACK
-  { let right = match right with None -> "" | Some (op, term) -> op ^ term in
-    "[" ^ String.lowercase left ^ right ^ "]" }
+  | LBRACK S* left=IDENT S* RBRACK
+  { `Attribute (String.lowercase left, None) }
+  | LBRACK S* left=IDENT S* op=RELATION right=rel_value RBRACK
+  { `Attribute (String.lowercase left, Some (op, right)) }
 %inline rel_value:
-  | S* id=IDENT S*  { id }
-  | S* s=STRING S*  { "\"" ^ s ^ "\"" }
+  | S* id=IDENT S*  { Ident id }
+  | S* s=STRING S*  { Strlit s }
 pseudo:
   | COLON id=IDENT
-  { ":" ^ (String.lowercase id) }
+  { `Pseudo (String.lowercase id, None) }
   | COLON f=FUNCTION args=wslist(COMMA, simple_selector) RPAREN
-  { ":" ^ String.lowercase f ^ "(" ^ String.concat "," args ^ ")" }
+  { `Pseudo (String.lowercase f, Some args) }
 
 declaration:
   | name=property S* COLON S* value=expr important=boption(ig2(IMPORTANT_SYM, S*))
diff --git a/stringify.ml b/stringify.ml
index ad89086a00bbd13c269852945e7192c7e3e3c199..5e115d2c374c921fac7489040598437828f79ee2 100644
--- a/stringify.ml
+++ b/stringify.ml
@@ -39,12 +39,30 @@ let string_of_declaration (name, value, important) =
   let imp = if important then " !important" else "" in
   name ^ ": " ^ string_of_expr value ^ imp ^ ";"
 
-let rec string_of_selector = function
-  | Simple simple -> simple
+let rec stringify_selector w selector =
+  let str = stringify_selector w in
+  match selector with
+  | No_element   -> ""
+  | All_elements -> "*"
+  | Element elem -> elem
+  | Id (base, id) ->
+    str base ^ "#" ^ id
+  | Class (base, cls) ->
+    str base ^ "." ^ cls
+  | Attribute (base, attr, None) ->
+    str base ^ "[" ^ attr ^ "]"
+  | Attribute (base, attr, Some (op, value)) ->
+    str base ^ "[" ^ attr ^ w ^ op ^ w ^ string_of_expr value ^ "]"
+  | Pseudo (base, sel, None) ->
+    str base ^ ":" ^ sel
+  | Pseudo (base, fn, Some args) ->
+    str base ^ ":" ^ fn ^ "(" ^ cat ("," ^ w) str args ^ ")"
   | Combinator (left, " ", right) ->
-    string_of_selector left ^ " " ^ string_of_selector right
+    str left ^ " " ^ str right
   | Combinator (left, com, right) ->
-    string_of_selector left ^ " " ^ com ^ " " ^ string_of_selector right
+    str left ^ w ^ com ^ w ^ str right
+
+let string_of_selector = stringify_selector " "
 
 let string_of_media_expr = function
   | (feature, None) -> "(" ^ feature ^ ")"
@@ -140,10 +158,7 @@ let minify_declaration (name, value, important) =
   let imp = if important then "!important" else "" in
   name ^ ":" ^ minify_expr value ^ imp
 
-let rec minify_selector = function
-  | Simple simple -> simple
-  | Combinator (left, com, right) ->
-    minify_selector left ^ com ^ minify_selector right
+let rec minify_selector = stringify_selector ""
 
 let minify_media_feature = function
   | (feature, None) -> "(" ^ feature ^ ")"
diff --git a/types.ml b/types.ml
index fd2c87a0330ee9e3132cf3650543e213f3b04bac..657e5b70c310219f1f1649a87e89eb85ae5a4554 100644
--- a/types.ml
+++ b/types.ml
@@ -11,9 +11,21 @@ type expr =
 
 type declaration = string * expr * bool
 
+type selector =
+  | No_element
+  | All_elements
+  | Element of string
+  | Id of selector * string
+  | Class of selector * string
+  | Pseudo of selector * string * selector list option
+  | Attribute of selector * string * (string * expr) option
+  | Combinator of selector * string * selector
+
+  (*
 type selector =
   | Simple of string
   | Combinator of selector * string * selector
+  *)
 
 type media_expr = string * expr option
 type media_query = string option * string option * media_expr list
diff --git a/util.ml b/util.ml
index c4cd3e8a83e44018f2f2eb120340a6d2e06ab6b6..8d88d82804c998ead11b9417ed7fc0b0c61f2ced 100644
--- a/util.ml
+++ b/util.ml
@@ -132,12 +132,26 @@ let transform_stylesheet f stylesheet =
   in
   let TRAV_ALL(declaration, Declaration) in
 
-  let trav_selector = function
-    | Simple _ as s -> f (Selector s)
+  let rec trav_selector = function
+    | (No_element | All_elements | Element _) as elem ->
+      f (Selector elem)
+    | Id (base, id) ->
+      f (Selector (Id (expect_selector base, id)))
+    | Class (base, cls) ->
+      f (Selector (Class (expect_selector base, cls)))
+    | Attribute (base, attr, value) ->
+      f (Selector (Attribute (expect_selector base, attr, value)))
+    | Pseudo (base, sel, None) ->
+      f (Selector (Pseudo (expect_selector base, sel, None)))
+    | Pseudo (base, fn, Some args) ->
+      let args = trav_all_selector args in
+      f (Selector (Pseudo (expect_selector base, fn, Some args)))
     | Combinator (left, com, right) ->
+      let left = expect_selector left in
+      let right = expect_selector right in
       f (Selector (Combinator (left, com, right)))
-  in
-  let TRAV_ALL(selector, Selector) in
+  and EXPECT(selector, Selector)
+  and TRAV_ALL(selector, Selector) in
 
   let trav_media_expr = function
     | (_, None) as value ->