packages feed

mangrove-0.1.0.0: src/Web/Mangrove/Parse/Tokenize/Comment.hs

{-|
Description:    Tokenization rules for characters within @\<!--@ ... @--\>@ sections.

Copyright:      (c) 2020 Sam May
License:        MPL-2.0
Maintainer:     ag.eitilt@gmail.com

Stability:      stable
Portability:    portable
-}
module Web.Mangrove.Parse.Tokenize.Comment
    ( tokenCommentStart
    , packCommentToken
    ) where


import qualified Data.Text as T

import Web.Mangrove.Parse.Common.Error
import Web.Mangrove.Parse.Tokenize.Common
import Web.Willow.Common.Encoding.Character


-- | Wrap a given span of 'Char's into the payload of a 'Comment'.
packCommentToken :: TokenizerOutput String -> TokenizerOutput Token
packCommentToken = fmap $ Comment . T.pack


-- | __HTML:__
--      @[comment start state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-start-state)@
-- 
-- The parsing instructions for after reading @"\<!--"@ in a section of the
-- state machine which allows markup declarations.
tokenCommentStart :: Tokenizer (TokenizerOutput String)
tokenCommentStart = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '-') tokenCommentStartDash
    , if_ (== '>') $ changeState DataState *> packToken ([AbruptClosingOfEmptyComment], "")
    , elsePush_ tokenComment
    ]

-- | __HTML:__
--      @[comment start dash state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-start-state)@
-- 
-- The parsing instructions for after reading @"\<!---"@ in a section of the
-- state machine which allows markup declarations.
tokenCommentStartDash :: Tokenizer (TokenizerOutput String)
tokenCommentStartDash = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '-') tokenCommentEnd
    , if_ (== '>') $ changeState DataState *> packToken ([AbruptClosingOfEmptyComment], "")
    , elsePush_ $ consOut '-' <$> tokenComment
    ]

-- | __HTML:__
--      @[comment state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-state)@
-- 
-- The parsing instructions rooted in the HTML comment section of the state
-- machine.
tokenComment :: Tokenizer (TokenizerOutput String)
tokenComment = tokenizer (Just ([EOFInComment], ""))
    [ ifChar (== '<') $ \c -> consOut c <$> tokenCommentLessThanSign
    , if_ (== '-') tokenCommentEndDash
    , if_ (== '\NUL') $ consTokenError UnexpectedNullCharacter . consOut replacementChar <$> tokenComment
    , elseChar $ \c -> consOut c <$> tokenComment
    ]

-- | __HTML:__
--      @[comment less-than sign state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-less-than-sign-state)@
-- 
-- The parsing instructions for after reading @"\<"@ in the HTML comment
-- section of the state machine.
tokenCommentLessThanSign :: Tokenizer (TokenizerOutput String)
tokenCommentLessThanSign = tokenizer (Just ([EOFInComment], ""))
    [ ifChar (== '!') $ \c -> consOut c <$> tokenCommentLessThanSignBang
    , ifChar (== '<') $ \c -> consOut c <$> tokenCommentLessThanSign
    , elsePush_ tokenComment
    ]

-- | __HTML:__
--      @[comment less-than sign bang state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-less-than-sign-bang-state)@
-- 
-- The parsing instructions for after reading @"\<!"@ in the HTML comment
-- section of the state machine.
tokenCommentLessThanSignBang :: Tokenizer (TokenizerOutput String)
tokenCommentLessThanSignBang = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '-') tokenCommentLessThanSignBangDash
    , elsePush_ tokenComment
    ]

-- | __HTML:__
--      @[comment less-than sign bang dash state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-less-than-sign-bang-dash-state)@
-- 
-- The parsing instructions for after reading @"\<!-"@ in the HTML comment
-- section of the state machine.
tokenCommentLessThanSignBangDash :: Tokenizer (TokenizerOutput String)
tokenCommentLessThanSignBangDash = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '-') tokenCommentLessThanSignBangDashDash
    , elsePush_ tokenCommentEndDash
    ]

-- | __HTML:__
--      @[comment less-than sign bang dash dash state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-less-than-sign-bang-dash-dash-state)@
-- 
-- The parsing instructions for after reading @"\<!--"@ in the HTML comment
-- section of the state machine.
tokenCommentLessThanSignBangDashDash :: Tokenizer (TokenizerOutput String)
tokenCommentLessThanSignBangDashDash = tokenizer (Just ([EOFInComment], ""))
    [ ifPush_ (== '>') tokenCommentEnd
    , elsePush_ $ consTokenError NestedComment <$> tokenCommentEnd
    ]

-- | __HTML:__
--      @[comment end dash state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-end-dash-state)@
-- 
-- The parsing instructions for after reading @"-"@ in the HTML comment section
-- of the state machine.
tokenCommentEndDash :: Tokenizer (TokenizerOutput String)
tokenCommentEndDash = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '-') tokenCommentEnd
    , elsePush_ $ consOut '-' <$> tokenComment
    ]

-- | __HTML:__
--      @[comment end state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-end-state)@
-- 
-- The parsing instructions for after reading @"--"@ in the HTML comment
-- section of the state machine.
tokenCommentEnd :: Tokenizer (TokenizerOutput String)
tokenCommentEnd = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '>') $ changeState DataState *> packToken ([], "")
    , if_ (== '!') tokenCommentEndBang
    , ifChar (== '-') $ \c -> consOut c <$> tokenCommentEnd
    , elsePush_ $ consOuts "--" <$> tokenComment
    ]

-- | __HTML:__
--      @[comment end bang state]
--      (https://html.spec.whatwg.org/multipage/parsing.html#comment-end-bang-state)@
-- 
-- The parsing instructions for after reading @"--!"@ in the HTML comment
-- section of the state machine.
tokenCommentEndBang :: Tokenizer (TokenizerOutput String)
tokenCommentEndBang = tokenizer (Just ([EOFInComment], ""))
    [ if_ (== '-') $ consOuts "--!" <$> tokenCommentEndDash
    , if_ (== '>') $ packToken ([IncorrectlyClosedComment], "")
    , elsePush_ $ consOuts "--!" <$> tokenComment
    ]