module Stylish.Parse ( parse, skipAtRule, StyleSheet, addRule, addAtRule, StyleRule, Selector(..), SimpleSelector(..), PropertyTest(..) ) where import Data.CSS.Syntax.Tokens import Stylish.Parse.Selector import Parse.Utils -------- ---- Output type class -------- class StyleSheet s where addRule :: s -> StyleRule -> s addAtRule :: s -> Text -> [Token] -> (s, [Token]) addAtRule self _ tokens = (self, skipAtRule tokens) data StyleRule = StyleRule [Selector] [(Text, [Token])] -------- ---- Basic parsing -------- parse :: StyleSheet s => s -> Text -> s parse stylesheet source = parse' stylesheet tokenize source -- Things to skip. parse' stylesheet Whitespace:tokens = parse' stylesheet tokens parse' stylesheet CDO:tokens = parse' stylesheet tokens parse' stylesheet CDC:tokens = parse' stylesheet tokens parse' stylesheet Comma:tokens = parse' stylesheet tokens -- TODO issue warnings. parse' stylesheet [] = stylesheet parse' stylesheet AtKeyword(kind):tokens = parse' stylesheet' tokens' where (stylesheet', tokens') = addAtRule stylesheet kind tokens parse' stylesheet tokens = parse' addRule stylesheet StyleRule selectors properties tokens' where (selectors, block) = parseSelectors tokens (properties, tokens') = parseProperties block parse' stylesheet tokens = parse' (addRule stylesheet rule) tokens' where (rule, tokens') = concatP (StyleRule) (parseSelector) (parseProperties) -------- ---- Property parsing -------- parseProperties LeftCurlyBracket:tokens = parseProperties' tokens parseProperties Whitespace:tokens = parseProperties tokens parseProperties' Whitespace:tokens = parseProperties' tokens parseProperties' (Ident name):tokens | Colon:tokens' <- skipSpace tokens = concatP (appendProp) (scanValue) (parseProperties') tokens' where appendProp value tail = (name, value):tail parseProperties' RightCurlyBracket:tokens = [], tokens parseProperties' tokens = parseProperties' skipValue tokens -------- ---- Skipping/Scanning utilities -------- skipAtRule Semicolon:tokens = tokens skipAtRule LeftCurlyBracket:tokens = skipBlock tokens skipAtRule LeftParen:tokens = skipAtRule skipBlock tokens skipAtRule LeftSquareBracket:tokens = skipAtRule skipBlock tokens -- To ensure parens are balanced, should already be handled. skipAtRule RightCurlyBracket:tokens = RightCurlyBracket:tokens skipAtRule RightParen:tokens = RightParen:tokens skipAtRule RightSquareBracket:tokens = RightSquareBracket:tokens skipAtRule _:tokens = skipAtRule tokens scanValue Semicolon:tokens = ([], tokens) scanValue Whitespace:tokens = scanValue tokens scanValue LeftCurlyBracket:tokens = scanInner tokens scanValue scanValue LeftParen:tokens = scanInner tokens scanValue scanValue LeftSquareBracket:tokens = scanInner tokens scanValue scanInner tokens cb = concatP (++) (scanBlock) (cb) -- To ensure parens are balanced, should already be handled. scanValue RightCurlyBracket:tokens = ([], RightCurlyBracket:tokens) scanValue RightParen:tokens = ([], RightParen:tokens) scanValue RightSquareBracket:tokens = ([], RightSquareBracket:tokens) scanValue tokens = capture scanValue tokens scanValue tokens = snd scanValue tokens -- TODO assert closing tags are correct -- But what should the error recovery be? scanBlock RightCurlyBracket:tokens = ([RightCurlyBracket], tokens) scanBlock RightParen:tokens = ([RightParen], tokens) scanBlock RightSquareBracket:tokens = ([RightSquareBracket], tokens) scanBlock LeftCurlyBracket:tokens = scanInner tokens scanBlock scanBlock LeftParen:tokens = scanInner tokens scanBlock scanBlock RightSquareBracket:tokens = scanInner tokens scanBlock scanBlock tokens = capture scanBlock tokens skipBlock tokens = snd scanBlock tokens