diff options
-rw-r--r-- | src/Codec/Pesto.lhs | 2 | ||||
-rw-r--r-- | src/Codec/Pesto/Graph.lhs | 24 | ||||
-rw-r--r-- | src/Codec/Pesto/Lint.lhs | 6 | ||||
-rw-r--r-- | src/Codec/Pesto/Parse.lhs | 78 | ||||
-rw-r--r-- | src/Codec/Pesto/Parse.lhs-boot | 2 | ||||
-rw-r--r-- | src/Codec/Pesto/Serialize.lhs | 5 |
6 files changed, 59 insertions, 58 deletions
diff --git a/src/Codec/Pesto.lhs b/src/Codec/Pesto.lhs index 72fa14f..329b5da 100644 --- a/src/Codec/Pesto.lhs +++ b/src/Codec/Pesto.lhs @@ -136,7 +136,7 @@ through the Web Archive only. defines a Pascal-like language. Being so close to real programming languages Cordon Bleu is barely useable by anyone except programmers. Additionally the language is poorly-designed, since its syntax is inconsistent and the user is -limited to a set of predefined operations. +limited to a set of predefined functions. Finally there is RxOL_, created in 1985. It constructs a graph from recipes written down with a few operators and postfix notation. It does not separate diff --git a/src/Codec/Pesto/Graph.lhs b/src/Codec/Pesto/Graph.lhs index 7376c5f..fea51a7 100644 --- a/src/Codec/Pesto/Graph.lhs +++ b/src/Codec/Pesto/Graph.lhs @@ -20,7 +20,7 @@ Language semantics > > import Codec.Pesto.Parse hiding (test) -The parser’s output, a stream of operations, may contain multiple recipes. A +The parser’s output, a stream of instructions, 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. @@ -34,7 +34,7 @@ This function extracts all recipes from the stream and removes both directives. > (between, next) = break isEnd stream > extract (x:xs) = extract xs -Start and end directive are removed from the extracted operations. The +Start and end directive are removed from the extracted instructions. The directive “bonappetit” is optional at the end of a stream. > testExtract = [ @@ -43,7 +43,7 @@ directive “bonappetit” is optional at the end of a stream. > , extract [Directive "pesto"] ~?= [[]] > , extract [Directive "pesto", Directive "foobar"] ~?= [[Directive "foobar"]] -Operations surrounding the start and end directive are removed. +Instructions surrounding the start and end directive are removed. > , extract [Unknown "Something", Directive "pesto"] ~?= [[]] > , extract [Unknown "Something", Action "pour", Directive "pesto"] ~?= [[]] @@ -57,12 +57,12 @@ previous recipe and starts a new one. > , extract [Directive "pesto", Annotation "foobar", Directive "pesto", Directive "bonappetit"] ~?= [[Annotation "foobar"], []] > ] -Each recipe’s stream of operations drives a stack-based machine that transforms +Each recipe’s stream of instructions 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 +This function processes a list of nodes, that is instructions uniquely identified by an integer and returns the edges of the directed graph as a list of tuples. > toGraph nodes = edges @@ -105,14 +105,14 @@ workspace labeled with Result or Alternative. More on that `in the next section > f ctx (i, Reference _) = addToStack ctx i -Annotations add a description to any of the previous operations. They can be +Annotations add a description to any of the previous instructions. They can be used to provide more information about ingredients (so “hot water” becomes “+water (hot)”, tools (“&oven (200 °C)”) or actions (“[cook] (XXX)”). > 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 +Unused directives or unknown instructions are danging nodes with no connection to other nodes. > f ctx (_, Directive _) = ctx @@ -146,7 +146,7 @@ But Action, Alternative and Result do in combination with them: > , cmpGraph "&foobar [barbaz] [C] >D" [(0, 1), (1, 2), (2, 3)] If the stack is empty, i.e. it was cleared by a Result or Alternative -operation, consecutive results or alternatives operate on the *previous*, +instruction, consecutive results or alternatives operate on the *previous*, non-empty stack. > , cmpGraph "+foobar >barbaz >C" [(0, 1), (0, 2)] @@ -160,7 +160,7 @@ Unless that stack too is empty. Then they do nothing: > , cmpGraph "(foobar) (foobar)" [] > , cmpGraph "[foobar]" [] -The Annotation operation always creates an edge to the most-recently processed +The Annotation instruction always creates an edge to the most-recently processed node that was not an annotation. Thus two consecutive annotations create edges to the same node. @@ -171,7 +171,7 @@ to the same node. > , cmpGraph "+foobar |barbaz (C)" [(0, 1), (2, 1)] > , cmpGraph "*foobar (C)" [(1, 0)] -Unknown directives or operations are never connected to other nodes. +Unknown directives or instructions are never connected to other nodes. > , cmpGraph "%invalid" [] > , cmpGraph "invalid" [] @@ -180,7 +180,7 @@ Unknown directives or operations are never connected to other nodes. References ++++++++++ -Results and alternatives can be referenced with the Reference operation. +Results and alternatives can be referenced with the Reference instruction. Resolving these references does not happen while buiding the graph, but afterwards. This allows referencing an a result or alternative before its definition with regard to the their processing order. @@ -203,7 +203,7 @@ to the reference in question is created. > isTarget _ _ = False -References works before or after the result operation. +References works before or after the result instruction. > testRef = [ > cmpGraphRef ">foobar *foobar" [(0, 1)] diff --git a/src/Codec/Pesto/Lint.lhs b/src/Codec/Pesto/Lint.lhs index 1cce87c..0d1c848 100644 --- a/src/Codec/Pesto/Lint.lhs +++ b/src/Codec/Pesto/Lint.lhs @@ -14,7 +14,7 @@ Linting > import Codec.Pesto.Parse hiding (test) Not every graph generated in the previous section is a useful recipe, since -some combinations of operations just do not make sense. The linting test in +some combinations of instructions just do not make sense. The linting test in this section can detect common errors. Failing any of these tests does not render a recipe invalid, but *useless*. Thus implementations must not create such recipes. They may be accepted the user though. @@ -33,7 +33,7 @@ The graph must have exactly one root node (i.e. a node with incoming edges only) and it must be a result. The result’s object name is the recipe’s title. This also requires all results and alternatives to be referenced somewhere. Directives are either consumed when parsing, generating a graph and linting. -Otherwise they are dangling as well. Unknown operations are always dangling. +Otherwise they are dangling as well. Unknown instructions are always dangling. > rootIsResult nodes edges = case walkRoot nodes edges of > [] -> [LintResult NoRootNode []] @@ -51,7 +51,7 @@ This recipe’s title is “Pesto”. > , cmpLint "+foobar >Pesto" [] -Directives and unknown operations are dangling and thus root nodes. +Directives and unknown instructions are dangling and thus root nodes. > , cmpLint "invalid %invalid +foo >bar" [LintResult MoreThanOneRootNode [0,1,3]] > ] diff --git a/src/Codec/Pesto/Parse.lhs b/src/Codec/Pesto/Parse.lhs index 7deb511..0d4e981 100644 --- a/src/Codec/Pesto/Parse.lhs +++ b/src/Codec/Pesto/Parse.lhs @@ -6,7 +6,7 @@ Language syntax > module Codec.Pesto.Parse ( > parse > , test -> , Operation(..) +> , Instruction(..) > , Quantity(..) > , Unit(..) > , Object(..) @@ -34,23 +34,20 @@ Language syntax > > import Codec.Pesto.Serialize (serialize) -Pesto parses UTF-8_ encoded input files into a sequence of operations. - -- stream of operations -- utf8 encoded -Every -character within the Unicode whitespace class is considered a space. +Pesto parses UTF-8_ encoded input data consisting of space-delimited +instructions. Every character within the Unicode whitespace class is +considered a space. .. _UTF-8: https://tools.ietf.org/html/rfc3629 .. _spaces1: -> stream = ((,) <$> getPosition <*> operation) `sepEndBy` spaces1 +> stream = ((,) <$> getPosition <*> instruction) `sepEndBy` spaces1 > <?> "stream" > spaces1 = many1 space -The following operations are supported: +The following instructions are supported: -> data Operation = +> data Instruction = > Annotation String > | Ingredient Quantity > | Tool Quantity @@ -62,7 +59,7 @@ The following operations are supported: > | Unknown String > deriving (Show, Eq) > -> operation = +> instruction = > try annotation > <|> try ingredient > <|> try tool @@ -72,28 +69,27 @@ The following operations are supported: > <|> try reference > <|> try directive > <|> try unknown -> <?> "operation" +> <?> "instruction" -The pesto grammar has two kinds of operations: The first one begins with a -start character and consumes characters up to and including a terminating -symbol (``end``), which can be escaped with a backslash (``\``): +The pesto grammar has two instruction types: The first one begins with a +start symbol (``start``) and consumes any character up to and including a +terminating symbol (``end``), which can be escaped with a backslash (``\``). > betweenEscaped start end = > char start > *> many (try (char '\\' *> char end) <|> satisfy (/= end)) > <* char end -Annotations and Actions both are of this kind: +Annotations and actions both are of this kind: > annotation = Annotation <$> betweenEscaped '(' ')' > action = Action <$> betweenEscaped '[' ']' Here are examples for both: -> testOpterm = [cmpOperation "(skinless\nboneless)" (Right (Annotation "skinless\nboneless")) -> , cmpOperation "[stir together]" (Right (Action "stir together")) -> , cmpOperation "[stir\\]together]" (Right (Action "stir]together"))] - +> testOpterm = [cmpInstruction "(skinless\nboneless)" (Right (Annotation "skinless\nboneless")) +> , cmpInstruction "[stir together]" (Right (Action "stir together")) +> , cmpInstruction "[stir\\]together]" (Right (Action "stir]together"))] The second one starts with one identifying character, ignores the following whitespace characters and then consumes an object or a quantity. @@ -105,28 +101,34 @@ whitespace characters and then consumes an object or a quantity. > alternative = oparg '|' (Alternative <$> object) > reference = oparg '*' (Reference <$> quantity) -Additionally there are two special operations. Directives are similar to the -previous operations, but consume a qstr. +Additionally there are two special instructions. Directives are similar to the +previous instructions, but consume a qstr. > directive = oparg '%' (Directive <$> qstr) -Unknown operations are the fallthrough-case and accept anything. They must not -be discarded at this point. The point of accepting anything is to fail as late -as possible while processing Pesto documents. This gives us a chance to print -helpful mesages that provide additional aid to the user who can then fix the -problem. +Unknown instructions are the fallthrough-case and accept anything. They must +not be discarded at this point. The point of accepting anything is to fail as +late as possible while processing input. This gives the parser a chance to +print helpful mesages that provide additional aid to the user who can then fix +the problem. > unknown = Unknown <$> many1 notspace +Below are examples for these instructions: + > testOparg = [ -> cmpOperation "+100 g flour" (Right (Ingredient (Quantity (Exact (AmountRatio (100%1))) "g" "flour"))) - -> , cmpOperation "&oven" (Right (Tool (Quantity (Exact (AmountStr "")) "" "oven"))) -> , cmpOperation ">dough" (Right (Result "dough")) -> , cmpOperation "|trimmings" (Right (Alternative "trimmings")) -> , cmpOperation "*fish" (Right (Reference (Quantity (Exact (AmountStr "")) "" "fish"))) -> , cmpOperation3 "% invalid" (Right (Directive "invalid")) "%invalid" -> , cmpOperation3 "* \t\n 1 _ cheese" (Right (Reference (Quantity (Exact (AmountRatio (1%1))) "" "cheese"))) "*1 _ cheese" +> cmpInstruction "+100 g flour" +> (Right (Ingredient (Quantity (Exact (AmountRatio (100%1))) "g" "flour"))) +> , cmpInstruction "&oven" +> (Right (Tool (Quantity (Exact (AmountStr "")) "" "oven"))) +> , cmpInstruction ">dough" (Right (Result "dough")) +> , cmpInstruction "|trimmings" (Right (Alternative "trimmings")) +> , cmpInstruction "*fish" +> (Right (Reference (Quantity (Exact (AmountStr "")) "" "fish"))) +> , cmpInstruction3 "% invalid" (Right (Directive "invalid")) "%invalid" +> , cmpInstruction3 "* \t\n 1 _ cheese" +> (Right (Reference (Quantity (Exact (AmountRatio (1%1))) "" "cheese"))) +> "*1 _ cheese" > ] Qstr @@ -207,7 +209,7 @@ the usual escape codes like \\n, \\t, … will *not* be expanded. Quantity ++++++++ -The operations Ingredient, Tool and Reference accept a *quantity*, that is a +The instructions Ingredient, Tool and Reference accept a *quantity*, that is a triple of Approximately, Unit and Object as parameter. > data Quantity = Quantity Approximately Unit Object deriving (Show, Eq) @@ -363,8 +365,8 @@ Wrap qstr test in AmountStr to aid serialization test > cmpQuantity a b = cmpQuantity3 a b a > cmpQuantity3 = cmpParseSerialize quantity -> cmpOperation a b = cmpOperation3 a b a -> cmpOperation3 = cmpParseSerialize operation +> cmpInstruction a b = cmpInstruction3 a b a +> cmpInstruction3 = cmpParseSerialize instruction > exactQuantity a b c = Right (Quantity (Exact a) b c) diff --git a/src/Codec/Pesto/Parse.lhs-boot b/src/Codec/Pesto/Parse.lhs-boot index dab073c..50d1b2a 100644 --- a/src/Codec/Pesto/Parse.lhs-boot +++ b/src/Codec/Pesto/Parse.lhs-boot @@ -1,6 +1,6 @@ > module Codec.Pesto.Parse where -> data Operation = +> data Instruction = > Annotation String > | Ingredient Quantity > | Tool Quantity diff --git a/src/Codec/Pesto/Serialize.lhs b/src/Codec/Pesto/Serialize.lhs index b3cce7c..6b99b4b 100644 --- a/src/Codec/Pesto/Serialize.lhs +++ b/src/Codec/Pesto/Serialize.lhs @@ -17,13 +17,12 @@ Serializing - Add instance for graph - use :math:`\mathcal{O}(1)` string builder - -Finally transform linear stream of operations into a string again: +Finally transform linear stream of instructions into a string again: > instance Serializeable a => Serializeable [a] where > serialize ops = unlines $ map serialize ops -> instance Serializeable Operation where +> instance Serializeable Instruction where > serialize (Annotation s) = quote '(' ')' s > serialize (Ingredient q) = '+':serialize q > serialize (Tool q) = '&':serialize q |