aboutsummaryrefslogtreecommitdiff
path: root/bbcode
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2016-01-12 05:21:16 +0000
committerGregor Kleen <gkleen@yggdrasil.li>2016-01-12 05:21:16 +0000
commitfe17c720081798175c9936d1624f428b565e310f (patch)
tree8cb2b9520f90a21e54e5b6dac4588ef4ed6e3a9c /bbcode
parenta5d285a8b74d2278e8549909d29c01b62dc84424 (diff)
downloadthermoprint-fe17c720081798175c9936d1624f428b565e310f.tar
thermoprint-fe17c720081798175c9936d1624f428b565e310f.tar.gz
thermoprint-fe17c720081798175c9936d1624f428b565e310f.tar.bz2
thermoprint-fe17c720081798175c9936d1624f428b565e310f.tar.xz
thermoprint-fe17c720081798175c9936d1624f428b565e310f.zip
Rose-Tree labels now carry attributes
Diffstat (limited to 'bbcode')
-rw-r--r--bbcode/src/Text/BBCode.hs28
-rw-r--r--bbcode/src/Text/BBCode/Lexer.hs5
-rw-r--r--bbcode/thermoprint-bbcode.cabal1
-rw-r--r--bbcode/thermoprint-bbcode.nix6
4 files changed, 28 insertions, 12 deletions
diff --git a/bbcode/src/Text/BBCode.hs b/bbcode/src/Text/BBCode.hs
index a6de7b4..3828c22 100644
--- a/bbcode/src/Text/BBCode.hs
+++ b/bbcode/src/Text/BBCode.hs
@@ -3,6 +3,7 @@
3 3
4module Text.BBCode 4module Text.BBCode
5 ( TreeError(..) 5 ( TreeError(..)
6 , BBLabel
6 , rose 7 , rose
7 , matches 8 , matches
8 ) where 9 ) where
@@ -14,6 +15,7 @@ import Control.Exception (Exception)
14import Data.Typeable (Typeable) 15import Data.Typeable (Typeable)
15 16
16import Control.Monad (unless) 17import Control.Monad (unless)
18import Data.Function (on)
17 19
18import Text.BBCode.Lexer (BBToken(..), token) 20import Text.BBCode.Lexer (BBToken(..), token)
19 21
@@ -21,32 +23,42 @@ import Data.Tree
21import Data.Tree.Zipper (TreePos, Empty, Full) 23import Data.Tree.Zipper (TreePos, Empty, Full)
22import qualified Data.Tree.Zipper as Z 24import qualified Data.Tree.Zipper as Z
23 25
26import Data.Map (Map)
27import qualified Data.Map as Map
28
29import Data.CaseInsensitive (CI)
30import qualified Data.CaseInsensitive as CI
31
24data TreeError = ImbalancedTags Text Text 32data TreeError = ImbalancedTags Text Text
25 | LeftoverClose Text 33 | LeftoverClose Text
26 deriving (Show, Eq, Generic, Typeable) 34 deriving (Show, Eq, Generic, Typeable)
27 35
28instance Exception TreeError 36instance Exception TreeError
29 37
38type BBLabel = (Text, Map Text (Maybe Text))
39
30matches :: Text -> Text -> Bool 40matches :: Text -> Text -> Bool
31-- ^ @`matches` "open" "close"@ should be true iff @[/close]@ is a valid closing tag for @[open]@ 41-- ^ @`matches` "open" "close"@ should be true iff @[/close]@ is a valid closing tag for @[open]@
32-- 42--
33-- Until we allow for attributes this is equality according to `(==)` 43-- > (==) `on` CI.mk
34matches = (==) 44matches = (==) `on` CI.mk
35 45
36rose :: [BBToken] -> Either TreeError (Forest Text) 46rose :: [BBToken] -> Either TreeError (Forest BBLabel)
37-- ^ Assuming that both tags and content have the same type (we use 'Text') bbcode is a flat representation of a rose tree 47-- ^ Assuming that both tags and content have the same type (we use 'Text') bbcode is a flat representation of a rose tree
38rose = fmap Z.toForest . flip rose' (Z.fromForest []) 48rose = fmap Z.toForest . flip rose' (Z.fromForest [])
39 where 49 where
40 rose' :: [BBToken] -> TreePos Empty Text -> Either TreeError (TreePos Empty Text) 50 rose' :: [BBToken] -> TreePos Empty BBLabel -> Either TreeError (TreePos Empty BBLabel)
41 rose' [] = return 51 rose' [] = return
42 rose' (x:xs) = (>>= rose' xs) . rose'' x 52 rose' (x:xs) = (>>= rose' xs) . rose'' x
43 53
44 rose'' (BBStr t) = return . Z.nextSpace . Z.insert (Node t []) 54 rose'' (BBStr t) = return . Z.nextSpace . Z.insert (Node (t, Map.empty) [])
45 rose'' (BBOpen t _) = return . Z.children . Z.insert (Node t []) 55 rose'' (BBOpen t attrs) = return . Z.children . Z.insert (Node (t, Map.fromList attrs) [])
46 rose'' (BBClose t) = close t -- for more pointless 56 rose'' (BBClose t) = close t -- for more pointless
47 57
48 close :: Text -> TreePos Empty Text -> Either TreeError (TreePos Empty Text) 58 close :: Text -> TreePos Empty BBLabel -> Either TreeError (TreePos Empty BBLabel)
49 close tag pos = do 59 close tag pos = do
50 pos' <- maybe (Left $ LeftoverClose tag) Right $ Z.parent pos 60 pos' <- maybe (Left $ LeftoverClose tag) Right $ Z.parent pos
51 unless (Z.label pos' `matches` tag) . Left $ ImbalancedTags (Z.label pos') tag -- The structure shows that this mode of failure is not logically required -- it's just nice to have 61 let
62 pTag = fst $ Z.label pos'
63 unless (pTag `matches` tag) . Left $ ImbalancedTags pTag tag -- The structure shows that this mode of failure is not logically required -- it's just nice to have
52 return $ Z.nextSpace pos' 64 return $ Z.nextSpace pos'
diff --git a/bbcode/src/Text/BBCode/Lexer.hs b/bbcode/src/Text/BBCode/Lexer.hs
index ad26113..2eb0022 100644
--- a/bbcode/src/Text/BBCode/Lexer.hs
+++ b/bbcode/src/Text/BBCode/Lexer.hs
@@ -29,9 +29,12 @@ data BBToken = BBOpen Text [(Text, Maybe Text)] -- ^ Tag open with attributes
29token :: Parser BBToken 29token :: Parser BBToken
30-- ^ Tokenizer 30-- ^ Tokenizer
31token = BBClose <$> ("[/" *> escapedText' [']'] <* "]") 31token = BBClose <$> ("[/" *> escapedText' [']'] <* "]")
32 <|> BBOpen <$> ("[" *> escapedText' [']', ' ']) <*> (option [] attrs <* "]") 32 <|> uncurry BBOpen <$> openTag
33 <|> BBStr <$> escapedText ['['] 33 <|> BBStr <$> escapedText ['[']
34 34
35openTag :: Parser (Text, [(Text, Maybe Text)])
36openTag = (,) <$> ("[" *> escapedText' [']', ' ']) <*> (option [] attrs <* "]")
37
35attrs :: Parser [(Text, Maybe Text)] 38attrs :: Parser [(Text, Maybe Text)]
36attrs = (:) <$> (attrs' <* takeWhile isSpace) <*> (option [] $ attrs) 39attrs = (:) <$> (attrs' <* takeWhile isSpace) <*> (option [] $ attrs)
37 where 40 where
diff --git a/bbcode/thermoprint-bbcode.cabal b/bbcode/thermoprint-bbcode.cabal
index 80a9da5..f25ffdf 100644
--- a/bbcode/thermoprint-bbcode.cabal
+++ b/bbcode/thermoprint-bbcode.cabal
@@ -26,6 +26,7 @@ library
26 , text >=1.2.1 && <2 26 , text >=1.2.1 && <2
27 , containers >=0.4.0 && <1 27 , containers >=0.4.0 && <1
28 , rosezipper >=0.2 && <1 28 , rosezipper >=0.2 && <1
29 , case-insensitive >=1.2.0 && <2
29 hs-source-dirs: src 30 hs-source-dirs: src
30 default-language: Haskell2010 31 default-language: Haskell2010
31 32
diff --git a/bbcode/thermoprint-bbcode.nix b/bbcode/thermoprint-bbcode.nix
index c379053..896bb04 100644
--- a/bbcode/thermoprint-bbcode.nix
+++ b/bbcode/thermoprint-bbcode.nix
@@ -1,12 +1,12 @@
1{ mkDerivation, attoparsec, base, containers, hspec, QuickCheck 1{ mkDerivation, attoparsec, base, case-insensitive, containers
2, quickcheck-instances, rosezipper, stdenv, text 2, hspec, QuickCheck, quickcheck-instances, rosezipper, stdenv, text
3}: 3}:
4mkDerivation { 4mkDerivation {
5 pname = "thermoprint-bbcode"; 5 pname = "thermoprint-bbcode";
6 version = "0.0.0"; 6 version = "0.0.0";
7 src = ./.; 7 src = ./.;
8 libraryHaskellDepends = [ 8 libraryHaskellDepends = [
9 attoparsec base containers rosezipper text 9 attoparsec base case-insensitive containers rosezipper text
10 ]; 10 ];
11 testHaskellDepends = [ 11 testHaskellDepends = [
12 attoparsec base hspec QuickCheck quickcheck-instances text 12 attoparsec base hspec QuickCheck quickcheck-instances text