diff options
| author | Lars-Dominik Braun <lars@6xq.net> | 2015-06-28 16:42:19 +0200 | 
|---|---|---|
| committer | Lars-Dominik Braun <lars@6xq.net> | 2015-06-28 16:42:19 +0200 | 
| commit | 4c6c1bcf877017df98d4a5492a665eca12b8ba98 (patch) | |
| tree | f5743e9965aac4d71ad3bd54c9ddb2ea8cd3495d /src/Codec/Pesto/Graph.lhs | |
| parent | 87cccdd0d3159c8ac6730cb18dccb166653c58c5 (diff) | |
| download | pesto-4c6c1bcf877017df98d4a5492a665eca12b8ba98.tar.gz pesto-4c6c1bcf877017df98d4a5492a665eca12b8ba98.tar.bz2 pesto-4c6c1bcf877017df98d4a5492a665eca12b8ba98.zip  | |
Replace file magic with directives
Adds the %pesto and %bonappetit directives, switches to stream-based
operation.
Diffstat (limited to 'src/Codec/Pesto/Graph.lhs')
| -rw-r--r-- | src/Codec/Pesto/Graph.lhs | 65 | 
1 files changed, 57 insertions, 8 deletions
diff --git a/src/Codec/Pesto/Graph.lhs b/src/Codec/Pesto/Graph.lhs index 4ea2886..7376c5f 100644 --- a/src/Codec/Pesto/Graph.lhs +++ b/src/Codec/Pesto/Graph.lhs @@ -11,18 +11,56 @@ Language semantics  > 	, firstNodeId  > 	, resolveReferences  > 	, test +> 	, extract  > 	) where  > import Data.Char (isSpace, toLower, isLetter)  > import Data.List (sort, nub)  > import Test.HUnit hiding (test) +> import Control.Applicative ((<$>))  >  > import Codec.Pesto.Parse hiding (test) -Pesto’s syntax drives a stack-based machine that transforms the linear stream -of operations generated by the parser into a directed graph. Think of the stack -as your kitchen’s workspace that is used to prepare the food’s -components. You can add new ingredients, perform actions on them, put them -aside and add them again. +The parser’s output, a stream of operations, may contain multiple recipes. A +recipe must start with the directive “pesto” and may end with “bonappetit”. +This function extracts all recipes from the stream and removes both directives. + +- easily embed recipes into other documents + +> extract [] = [] +> extract (Directive "pesto":stream) = between:extract next +> 	where +> 		isEnd (Directive x) | x `elem` ["bonappetit", "pesto"] = True +> 		isEnd _ = False +> 		(between, next) = break isEnd stream +> extract (x:xs) = extract xs + +Start and end directive are removed from the extracted operations.  The +directive “bonappetit” is optional at the end of a stream. + +> testExtract = [ +> 	  extract [Directive "pesto", Directive "bonappetit"] ~?= [[]] +> 	, extract [Directive "pesto", Action "foobar", Directive "bonappetit"] ~?= [[Action "foobar"]] +> 	, extract [Directive "pesto"] ~?= [[]] +> 	, extract [Directive "pesto", Directive "foobar"] ~?= [[Directive "foobar"]] + +Operations surrounding the start and end directive are removed. + +> 	, extract [Unknown "Something", Directive "pesto"] ~?= [[]] +> 	, extract [Unknown "Something", Action "pour", Directive "pesto"] ~?= [[]] +> 	, extract [Directive "pesto", Directive "bonappetit", Annotation "something"] ~?= [[]] + +The stream may contain multiple recipes. The start directive also ends the +previous recipe and starts a new one. + +> 	, extract [Directive "pesto", Action "pour", Directive "bonappetit", Action "foobar", Directive "pesto", Annotation "something"] ~?= [[Action "pour"], [Annotation "something"]] +> 	, extract [Directive "pesto", Action "heat", Directive "pesto", Annotation "something"] ~?= [[Action "heat"], [Annotation "something"]] +> 	, extract [Directive "pesto", Annotation "foobar", Directive "pesto", Directive "bonappetit"] ~?= [[Annotation "foobar"], []] +> 	] + +Each recipe’s stream of operations drives a stack-based machine that transforms +it into a directed graph. Think of the stack as your kitchen’s workspace that +is used to prepare the food’s components. You can add new ingredients, perform +actions on them, put them aside and add them again.  This function processes a list of nodes, that is operations uniquely identified  by an integer and returns the edges of the directed graph as a list of tuples. @@ -74,6 +112,12 @@ used to provide more information about ingredients (so “hot water” becomes  > 		f ctx@(Nothing, s, edges) (_, Annotation _) = ctx  > 		f (Just prev, s, edges) (i, Annotation _) = (Just prev, s, (i, prev):edges) +Unused directives or unknown operations are danging nodes with no connection to +other nodes. + +> 		f ctx (_, Directive _) = ctx +> 		f ctx (_, Unknown _) = ctx +  These are helper functions:  > 		addToStack (_, stack:sx, edges) i = (Just i, (i:stack):sx, edges) @@ -126,6 +170,11 @@ to the same node.  > 	, cmpGraph "+foobar >barbaz (C)" [(0, 1), (2, 1)]  > 	, cmpGraph "+foobar |barbaz (C)" [(0, 1), (2, 1)]  > 	, cmpGraph "*foobar (C)" [(1, 0)] + +Unknown directives or operations are never connected to other nodes. + +> 	, cmpGraph "%invalid" [] +> 	, cmpGraph "invalid" []  > 	]  References @@ -183,8 +232,8 @@ Appendix  > runGraphWith f doc expect = sort edges ~?= sort expect  > 	where -> 		(Right op) = parse ("%pesto-1 " ++ doc) -> 		nodes = (zip [firstNodeId..] . map snd . operations) op +> 		(Right op) = (head . extract . snd . unzip) <$> parse ("%pesto " ++ doc) +> 		nodes = zip [firstNodeId..] op  > 		edges = f nodes  > cmpGraph = runGraphWith toGraph  > cmpGraphRef = runGraphWith resolveReferences @@ -202,5 +251,5 @@ Get all nodes with edges pointing towards nodeid  > outgoing edges (nodeid, _) = filter ((==) nodeid . fst) edges -> test = ["graph" ~: testGraph, "ref" ~: testRef] +> test = ["graph" ~: testGraph, "ref" ~: testRef, "extract" ~: testExtract]  | 
