aboutsummaryrefslogtreecommitdiff
path: root/bbcode
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2016-01-12 04:35:47 +0000
committerGregor Kleen <gkleen@yggdrasil.li>2016-01-12 04:35:47 +0000
commited629414fbc3af1700f7ed6829744f0fb30417c9 (patch)
treee83e6280607bba4cec25778741ead3f466976809 /bbcode
parentc2e72615a166e1cfa479e44283b5f7f9ecdeb942 (diff)
downloadthermoprint-ed629414fbc3af1700f7ed6829744f0fb30417c9.tar
thermoprint-ed629414fbc3af1700f7ed6829744f0fb30417c9.tar.gz
thermoprint-ed629414fbc3af1700f7ed6829744f0fb30417c9.tar.bz2
thermoprint-ed629414fbc3af1700f7ed6829744f0fb30417c9.tar.xz
thermoprint-ed629414fbc3af1700f7ed6829744f0fb30417c9.zip
Morph [BBNode] (Forest Text)
Diffstat (limited to 'bbcode')
-rw-r--r--bbcode/src/Text/BBCode.hs48
-rw-r--r--bbcode/thermoprint-bbcode.cabal2
-rw-r--r--bbcode/thermoprint-bbcode.nix10
3 files changed, 51 insertions, 9 deletions
diff --git a/bbcode/src/Text/BBCode.hs b/bbcode/src/Text/BBCode.hs
index 7a328a8..dfa1db7 100644
--- a/bbcode/src/Text/BBCode.hs
+++ b/bbcode/src/Text/BBCode.hs
@@ -1,14 +1,52 @@
1{-# LANGUAGE OverloadedStrings #-} 1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE DeriveGeneric #-}
2 3
3module Text.BBCode 4module Text.BBCode
4 ( 5 ( TreeError(..)
6 , rose
7 , matches
5 ) where 8 ) where
6 9
7import Data.Attoparsec.Text
8
9import Data.Text (Text) 10import Data.Text (Text)
10import qualified Data.Text as T (singleton, head, tail)
11 11
12import Control.Applicative 12import GHC.Generics (Generic)
13import Control.Exception (Exception)
14import Data.Typeable (Typeable)
15
16import Control.Monad (unless)
13 17
14import Text.BBCode.Lexer (BBToken(..), token) 18import Text.BBCode.Lexer (BBToken(..), token)
19
20import Data.Tree
21import Data.Tree.Zipper (TreePos, Empty, Full)
22import qualified Data.Tree.Zipper as Z
23
24data TreeError = ImbalancedTags Text Text
25 | LeftoverClose Text
26 deriving (Show, Eq, Generic, Typeable)
27
28instance Exception TreeError
29
30matches :: Text -> Text -> Bool
31-- ^ @`matches` "open" "close"@ should be true iff @[/close]@ is a valid closing tag for @[open]@
32--
33-- Until we allow for attributes this is equality according to `(==)`
34matches = (==)
35
36rose :: [BBToken] -> Either TreeError (Forest Text)
37-- ^ 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 [])
39 where
40 rose' :: [BBToken] -> TreePos Empty Text -> Either TreeError (TreePos Empty Text)
41 rose' [] = return
42 rose' (x:xs) = (>>= rose' xs) . rose'' x
43
44 rose'' (BBStr t) = return . Z.nextSpace . Z.insert (Node t [])
45 rose'' (BBOpen t) = return . Z.children . Z.insert (Node t [])
46 rose'' (BBClose t) = close t -- for more pointless
47
48 close :: Text -> TreePos Empty Text -> Either TreeError (TreePos Empty Text)
49 close tag pos = do
50 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
52 return $ Z.nextSpace pos'
diff --git a/bbcode/thermoprint-bbcode.cabal b/bbcode/thermoprint-bbcode.cabal
index f1018a5..80a9da5 100644
--- a/bbcode/thermoprint-bbcode.cabal
+++ b/bbcode/thermoprint-bbcode.cabal
@@ -24,6 +24,8 @@ library
24 build-depends: base >=4.8 && <4.9 24 build-depends: base >=4.8 && <4.9
25 , attoparsec >=0.13.0 && <1 25 , attoparsec >=0.13.0 && <1
26 , text >=1.2.1 && <2 26 , text >=1.2.1 && <2
27 , containers >=0.4.0 && <1
28 , rosezipper >=0.2 && <1
27 hs-source-dirs: src 29 hs-source-dirs: src
28 default-language: Haskell2010 30 default-language: Haskell2010
29 31
diff --git a/bbcode/thermoprint-bbcode.nix b/bbcode/thermoprint-bbcode.nix
index 5521b10..c379053 100644
--- a/bbcode/thermoprint-bbcode.nix
+++ b/bbcode/thermoprint-bbcode.nix
@@ -1,14 +1,16 @@
1{ mkDerivation, attoparsec, base, hspec, QuickCheck 1{ mkDerivation, attoparsec, base, containers, hspec, QuickCheck
2, quickcheck-instances, stdenv, text 2, 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 QuickCheck quickcheck-instances text 9 attoparsec base containers rosezipper text
10 ];
11 testHaskellDepends = [
12 attoparsec base hspec QuickCheck quickcheck-instances text
10 ]; 13 ];
11 testHaskellDepends = [ attoparsec base hspec QuickCheck text ];
12 homepage = "http://dirty-haskell.org/tags/thermoprint.html"; 14 homepage = "http://dirty-haskell.org/tags/thermoprint.html";
13 description = "A parser for a subset of bbcode compatible with thermoprint-spec"; 15 description = "A parser for a subset of bbcode compatible with thermoprint-spec";
14 license = stdenv.lib.licenses.publicDomain; 16 license = stdenv.lib.licenses.publicDomain;