diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-01-18 11:38:44 +0000 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-01-18 11:38:44 +0000 |
commit | abb427bdccfe78649f5d75654a8179093201609c (patch) | |
tree | 3c2fbed64af3b1eb4a50a098655be1f109e743fa /spec | |
parent | 1ec5c1cb2f118c906a27b3763c73c0098fe67b4a (diff) | |
download | thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar.gz thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar.bz2 thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar.xz thermoprint-abb427bdccfe78649f5d75654a8179093201609c.zip |
Moved handling of lines in block context
Now allows arbitrary (instead of prefix only) switching between block
and line contexts
Diffstat (limited to 'spec')
-rw-r--r-- | spec/src/Thermoprint/Printout/BBCode.hs | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/spec/src/Thermoprint/Printout/BBCode.hs b/spec/src/Thermoprint/Printout/BBCode.hs index 8825732..ce2aa43 100644 --- a/spec/src/Thermoprint/Printout/BBCode.hs +++ b/spec/src/Thermoprint/Printout/BBCode.hs | |||
@@ -29,6 +29,8 @@ import Data.Typeable (Typeable) | |||
29 | import Data.Bifunctor (bimap, first) | 29 | import Data.Bifunctor (bimap, first) |
30 | import Control.Monad (join) | 30 | import Control.Monad (join) |
31 | 31 | ||
32 | import Data.List (groupBy) | ||
33 | |||
32 | import Text.BBCode (DomForest, DomTree(..), TreeError(..)) | 34 | import Text.BBCode (DomForest, DomTree(..), TreeError(..)) |
33 | import qualified Text.BBCode as Raw (bbcode, BBCodeError(..)) | 35 | import qualified Text.BBCode as Raw (bbcode, BBCodeError(..)) |
34 | 36 | ||
@@ -63,6 +65,7 @@ data ParseResult = RBlock Block -- ^ Parses only as 'Block' | |||
63 | | RLine Line -- ^ Parses only as 'Line' | 65 | | RLine Line -- ^ Parses only as 'Line' |
64 | | RAmbiguous Block Line -- ^ Parses as either 'Block' or 'Line' depending on context | 66 | | RAmbiguous Block Line -- ^ Parses as either 'Block' or 'Line' depending on context |
65 | | RNoParse SemanticError SemanticError -- ^ Does not parse as either 'Block' or 'Line' | 67 | | RNoParse SemanticError SemanticError -- ^ Does not parse as either 'Block' or 'Line' |
68 | deriving (Show) | ||
66 | 69 | ||
67 | -- | Current parser context | 70 | -- | Current parser context |
68 | data Context a where | 71 | data Context a where |
@@ -80,6 +83,16 @@ extract LineCtx (RNoParse _ lErr) = Left lErr | |||
80 | extract BlockCtx _ = Left LineInBlockContext | 83 | extract BlockCtx _ = Left LineInBlockContext |
81 | extract LineCtx _ = Left BlockInLineContext | 84 | extract LineCtx _ = Left BlockInLineContext |
82 | 85 | ||
86 | hasBlockCtx :: ParseResult -> Bool | ||
87 | -- ^ Result can be 'extract'ed in a 'Block' 'Context' | ||
88 | hasBlockCtx (RLine _) = False | ||
89 | hasBlockCtx _ = True | ||
90 | |||
91 | hasLineCtx :: ParseResult -> Bool | ||
92 | -- ^ Result can be 'extract'ed in a 'Line' 'Context' | ||
93 | hasLineCtx (RBlock _) = False | ||
94 | hasLineCtx _ = True | ||
95 | |||
83 | bbcode :: Text -> Either BBCodeError Printout | 96 | bbcode :: Text -> Either BBCodeError Printout |
84 | -- ^ Parse BBCode | 97 | -- ^ Parse BBCode |
85 | bbcode = join . fmap (first SemanticError) . bimap morph' morph . Raw.bbcode | 98 | bbcode = join . fmap (first SemanticError) . bimap morph' morph . Raw.bbcode |
@@ -88,7 +101,7 @@ morph :: DomForest -> Either SemanticError Printout | |||
88 | -- ^ Parse a list of paragraphs | 101 | -- ^ Parse a list of paragraphs |
89 | -- | 102 | -- |
90 | -- Since we permit only cooked input via 'Raw' 'Paragraph' is identical to 'Block' | 103 | -- Since we permit only cooked input via 'Raw' 'Paragraph' is identical to 'Block' |
91 | morph f = Seq.fromList <$> mapM (\t -> Seq.singleton . Cooked <$> parse BlockCtx t) f | 104 | morph = fmap Seq.fromList . mapM (\t -> Seq.singleton . Cooked <$> parse BlockCtx t) |
92 | 105 | ||
93 | parseDom :: DomTree -> ParseResult | 106 | parseDom :: DomTree -> ParseResult |
94 | -- ^ Invoke 'asLine' and 'asBlock' to parse a single 'DomTree' | 107 | -- ^ Invoke 'asLine' and 'asBlock' to parse a single 'DomTree' |
@@ -107,7 +120,6 @@ parseDom (Element t attrs cs) | |||
107 | mergeResult :: Monoid a => Context a -> [ParseResult] -> Either SemanticError a | 120 | mergeResult :: Monoid a => Context a -> [ParseResult] -> Either SemanticError a |
108 | -- ^ Merge a list of 'ParseResults' in a certain 'Context' | 121 | -- ^ Merge a list of 'ParseResults' in a certain 'Context' |
109 | mergeResult _ [] = Right mempty | 122 | mergeResult _ [] = Right mempty |
110 | mergeResult BlockCtx xs@((RLine _):_) = bimap (const LineInBlockContext) Line $ mergeResult LineCtx xs | ||
111 | mergeResult ctx (amb@(RAmbiguous _ _):xs) = mappend <$> extract ctx amb <*> mergeResult ctx xs | 123 | mergeResult ctx (amb@(RAmbiguous _ _):xs) = mappend <$> extract ctx amb <*> mergeResult ctx xs |
112 | mergeResult ctx (err@(RNoParse _ _):_) = extract ctx err | 124 | mergeResult ctx (err@(RNoParse _ _):_) = extract ctx err |
113 | mergeResult ctx (x:xs) = mappend <$> extract ctx x <*> mergeResult ctx xs | 125 | mergeResult ctx (x:xs) = mappend <$> extract ctx x <*> mergeResult ctx xs |
@@ -116,7 +128,13 @@ parse :: Monoid a => Context a -> [DomTree] -> Either SemanticError a | |||
116 | -- ^ Parse a list of 'DomTree's in a certain 'Context' | 128 | -- ^ Parse a list of 'DomTree's in a certain 'Context' |
117 | -- | 129 | -- |
118 | -- @parse ctx = 'mergeResult' ctx . map 'parseDom'@ | 130 | -- @parse ctx = 'mergeResult' ctx . map 'parseDom'@ |
119 | parse ctx = mergeResult ctx . map parseDom | 131 | parse BlockCtx = fmap mconcat . mapM mergeResult' . groupBy sameCtx . map parseDom |
132 | where | ||
133 | sameCtx a b = (hasLineCtx a && hasLineCtx b) || (hasBlockCtx a && hasBlockCtx b) | ||
134 | mergeResult' xs | ||
135 | | hasLineCtx `all` xs = Line <$> mergeResult LineCtx xs | ||
136 | | otherwise = mergeResult BlockCtx xs | ||
137 | parse ctx = mergeResult ctx . map parseDom | ||
120 | 138 | ||
121 | asBlock :: CI Text -> [DomTree] -> Map (CI Text) Text -> Either SemanticError Block | 139 | asBlock :: CI Text -> [DomTree] -> Map (CI Text) Text -> Either SemanticError Block |
122 | asBlock "VSpace" _ = Right . VSpace . lookupAttr "height" True 1 | 140 | asBlock "VSpace" _ = Right . VSpace . lookupAttr "height" True 1 |