diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-01-18 11:38:31 +0000 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-01-18 11:38:31 +0000 |
commit | 1ec5c1cb2f118c906a27b3763c73c0098fe67b4a (patch) | |
tree | 7ea7fada2d7bf380cddb6e135b6af1f58cac31fd /bbcode | |
parent | f0ad3abb87d540c75a397a722ca5310d6d16cec9 (diff) | |
download | thermoprint-1ec5c1cb2f118c906a27b3763c73c0098fe67b4a.tar thermoprint-1ec5c1cb2f118c906a27b3763c73c0098fe67b4a.tar.gz thermoprint-1ec5c1cb2f118c906a27b3763c73c0098fe67b4a.tar.bz2 thermoprint-1ec5c1cb2f118c906a27b3763c73c0098fe67b4a.tar.xz thermoprint-1ec5c1cb2f118c906a27b3763c73c0098fe67b4a.zip |
Added failure mode: UnclosedTags
Diffstat (limited to 'bbcode')
-rw-r--r-- | bbcode/bbcode.cabal | 2 | ||||
-rw-r--r-- | bbcode/bbcode.nix | 2 | ||||
-rw-r--r-- | bbcode/src/Text/BBCode.hs | 17 |
3 files changed, 17 insertions, 4 deletions
diff --git a/bbcode/bbcode.cabal b/bbcode/bbcode.cabal index 49e7a01..ad8bb5a 100644 --- a/bbcode/bbcode.cabal +++ b/bbcode/bbcode.cabal | |||
@@ -2,7 +2,7 @@ | |||
2 | -- documentation, see http://haskell.org/cabal/users-guide/ | 2 | -- documentation, see http://haskell.org/cabal/users-guide/ |
3 | 3 | ||
4 | name: bbcode | 4 | name: bbcode |
5 | version: 2.0.0 | 5 | version: 3.0.0 |
6 | synopsis: A parser for bbcode | 6 | synopsis: A parser for bbcode |
7 | -- description: | 7 | -- description: |
8 | homepage: http://dirty-haskell.org/tags/thermoprint.html | 8 | homepage: http://dirty-haskell.org/tags/thermoprint.html |
diff --git a/bbcode/bbcode.nix b/bbcode/bbcode.nix index ddb055c..6426b0b 100644 --- a/bbcode/bbcode.nix +++ b/bbcode/bbcode.nix | |||
@@ -3,7 +3,7 @@ | |||
3 | }: | 3 | }: |
4 | mkDerivation { | 4 | mkDerivation { |
5 | pname = "bbcode"; | 5 | pname = "bbcode"; |
6 | version = "2.0.0"; | 6 | version = "3.0.0"; |
7 | src = ./.; | 7 | src = ./.; |
8 | libraryHaskellDepends = [ | 8 | libraryHaskellDepends = [ |
9 | attoparsec base case-insensitive containers rosezipper text | 9 | attoparsec base case-insensitive containers rosezipper text |
diff --git a/bbcode/src/Text/BBCode.hs b/bbcode/src/Text/BBCode.hs index ac56974..f3c9ca2 100644 --- a/bbcode/src/Text/BBCode.hs +++ b/bbcode/src/Text/BBCode.hs | |||
@@ -20,7 +20,7 @@ import GHC.Generics (Generic) | |||
20 | import Control.Exception (Exception) | 20 | import Control.Exception (Exception) |
21 | import Data.Typeable (Typeable) | 21 | import Data.Typeable (Typeable) |
22 | 22 | ||
23 | import Control.Monad (unless, join, foldM) | 23 | import Control.Monad (unless, join, foldM, (<=<)) |
24 | import Data.Function (on) | 24 | import Data.Function (on) |
25 | import Control.Applicative | 25 | import Control.Applicative |
26 | 26 | ||
@@ -39,6 +39,8 @@ import qualified Data.CaseInsensitive as CI | |||
39 | 39 | ||
40 | import Data.Bifunctor (Bifunctor(first)) | 40 | import Data.Bifunctor (Bifunctor(first)) |
41 | 41 | ||
42 | import Data.Maybe (catMaybes) | ||
43 | |||
42 | -- | Our target structure -- a rose tree with an explicit terminal constructor | 44 | -- | Our target structure -- a rose tree with an explicit terminal constructor |
43 | data DomTree = Element (CI Text) (Map (CI Text) Text) [DomTree] | 45 | data DomTree = Element (CI Text) (Map (CI Text) Text) [DomTree] |
44 | | Content Text | 46 | | Content Text |
@@ -75,6 +77,7 @@ bbcode t = fmap dom $ first LexerError (parseOnly (many token <* endOfInput) t) | |||
75 | -- | Errors in input encountered during parsing of lexed token-stream | 77 | -- | Errors in input encountered during parsing of lexed token-stream |
76 | data TreeError = MismatchedTags Text Text -- ^ Closing tags label does not match opening tags | 78 | data TreeError = MismatchedTags Text Text -- ^ Closing tags label does not match opening tags |
77 | | ImbalancedTags Text -- ^ We found an extraneous closing tag | 79 | | ImbalancedTags Text -- ^ We found an extraneous closing tag |
80 | | UnclosedTags [Text] -- ^ We found opened tags that were not closed | ||
78 | | ParagraphWithinTag -- ^ We found a paragraph-break within a tag | 81 | | ParagraphWithinTag -- ^ We found a paragraph-break within a tag |
79 | deriving (Show, Eq, Generic, Typeable) | 82 | deriving (Show, Eq, Generic, Typeable) |
80 | 83 | ||
@@ -98,7 +101,7 @@ rose :: [BBToken] -> Either TreeError (Forest BBLabel) | |||
98 | -- We use @'Tree' 'BBLabel'@ only as another intermediate structure because it carries no guarantee that the data is semantically valid -- a 'BBPlain'-value semantically has no children. | 101 | -- We use @'Tree' 'BBLabel'@ only as another intermediate structure because it carries no guarantee that the data is semantically valid -- a 'BBPlain'-value semantically has no children. |
99 | -- | 102 | -- |
100 | -- The use of 'Tree' was still deemed desirable because the morphism to a more sensible structure is straightforward and 'Data.Tree.Zipper' provides all the tools needed to implement 'rose' in a sensible fashion | 103 | -- The use of 'Tree' was still deemed desirable because the morphism to a more sensible structure is straightforward and 'Data.Tree.Zipper' provides all the tools needed to implement 'rose' in a sensible fashion |
101 | rose = fmap Z.toForest . foldM (flip rose') (Z.fromForest []) | 104 | rose = fmap Z.toForest . checkClosure <=< foldM (flip rose') (Z.fromForest []) |
102 | where | 105 | where |
103 | rose' (BBStr t) = return . Z.nextSpace . Z.insert (Node (BBPlain t) []) | 106 | rose' (BBStr t) = return . Z.nextSpace . Z.insert (Node (BBPlain t) []) |
104 | rose' BBNewPar = parBreak -- for more pointless | 107 | rose' BBNewPar = parBreak -- for more pointless |
@@ -129,3 +132,13 @@ rose = fmap Z.toForest . foldM (flip rose') (Z.fromForest []) | |||
129 | 132 | ||
130 | isPar (Node BBPar _) = True | 133 | isPar (Node BBPar _) = True |
131 | isPar _ = False | 134 | isPar _ = False |
135 | |||
136 | checkClosure :: TreePos Empty BBLabel -> Either TreeError (TreePos Empty BBLabel) | ||
137 | -- This failure mode isn't required either | ||
138 | checkClosure z | ||
139 | | null parentTags = Right z | ||
140 | | otherwise = Left . UnclosedTags $ parentTags | ||
141 | where | ||
142 | parentTags = catMaybes . map (getTag . (\(_, p, _) -> p)) $ Z.parents z | ||
143 | getTag (BBTag t _) = Just t | ||
144 | getTag _ = Nothing | ||