@@ 0,0 1,59 @@
+module Stylish.Style.Index (
+        StyleIndex
+    ) where
+
+-- TODO do performance tests to decide beside between strict/lazy.
+import Data.HashMap.Strict
+import Stylish.Parse
+
+import Data.Hashable
+import Data.Text (unpack)
+
+data StyleIndex = StyleIndex {
+    indexed :: HashMap SimpleSelector [StyleRule],
+    unindexed :: [StyleRule]
+}
+
+styleIndex = StyleIndex {indexed = empty, unindexed = []}
+
+lookup' :: SimpleSelector -> HashMap SimpleSelector [a] -> [a]
+lookup' = lookupDefault []
+
+instance StyleSheet StyleIndex where
+    addRule self (StyleRule _ []) = self
+    addRule self rule@(StyleRule selector _) = addRuleForSelector self rule $ simpleSelector selector
+
+simpleSelector (Element s) = s
+simpleSelector (Child _ s) = s
+simpleSelector (Descendant _ s) = s
+simpleSelector (Adjacent _ s) = s
+simpleSelector (Sibling _ s) = s
+
+addRuleForSelector self rule [] = self {unindexed = rule : unindexed self}
+addRuleForSelector self rule selector = self {
+        indexed = insert key (rule : lookup' key index) index
+    } where
+        key = selectorKey selector
+        index = indexed self
+
+selectorKey (tok@(Tag _) : _) = tok
+selectorKey (tok@(Id _) : _) = tok
+selectorKey (tok@(Class _) : _) = tok
+selectorKey (Property prop _ : _) = Property prop Exists
+
+-- Implement hashable for SimpleSelector here because it proved challenging to automatically derive it.
+instance Hashable SimpleSelector where
+    hashWithSalt seed (Tag tag) = seed `hashWithSalt` (0::Int) `hashWithSalt` unpack tag
+    hashWithSalt seed (Id id) = seed `hashWithSalt` (1::Int) `hashWithSalt` unpack id
+    hashWithSalt seed (Class class_) = seed `hashWithSalt` (2::Int) `hashWithSalt` unpack class_
+    hashWithSalt seed (Property prop test) =
+        seed `hashWithSalt` (3::Int) `hashWithSalt` unpack prop `hashWithSalt` test
+
+instance Hashable PropertyTest where
+    hashWithSalt seed Exists = seed `hashWithSalt` (0::Int)
+    hashWithSalt seed (Equals val) = seed `hashWithSalt` (1::Int) `hashWithSalt` unpack val
+    hashWithSalt seed (Suffix val) = seed `hashWithSalt` (2::Int) `hashWithSalt` unpack val
+    hashWithSalt seed (Prefix val) = seed `hashWithSalt` (3::Int) `hashWithSalt` unpack val
+    hashWithSalt seed (Substring val) = seed `hashWithSalt` (4::Int) `hashWithSalt` unpack val
+    hashWithSalt seed (Include val) = seed `hashWithSalt` (5::Int) `hashWithSalt` unpack val
+    hashWithSalt seed (Dash val) = seed `hashWithSalt` (6::Int) `hashWithSalt` unpack val
 
@@ 57,7 57,7 @@ library
   -- other-extensions:    
   
   -- Other library packages from which modules are imported.
-  build-depends:       base >=4.9 && <4.10, css-syntax, text
+  build-depends:       base >=4.9 && <4.10, css-syntax, text, unordered-containers, hashable
   
   -- Directories containing source files.
   hs-source-dirs:      src
@@ 71,4 71,4 @@ test-suite test-stylish
   type:     exitcode-stdio-1.0
   main-is:              Test.hs
   other-modules:        Stylish.Parse
-  build-depends:       base >=4.9 && <4.10, css-syntax, text, hspec, QuickCheck
+  build-depends:       base >=4.9 && <4.10, css-syntax, text, unordered-containers, hashable, hspec, QuickCheck