aboutsummaryrefslogtreecommitdiffhomepage
path: root/scaffolder/src/Text/Edifact/Scaffolder/Segments
diff options
context:
space:
mode:
Diffstat (limited to 'scaffolder/src/Text/Edifact/Scaffolder/Segments')
-rw-r--r--scaffolder/src/Text/Edifact/Scaffolder/Segments/Dependencies.hs47
-rw-r--r--scaffolder/src/Text/Edifact/Scaffolder/Segments/Elements.hs26
-rw-r--r--scaffolder/src/Text/Edifact/Scaffolder/Segments/Implementation.hs21
-rw-r--r--scaffolder/src/Text/Edifact/Scaffolder/Segments/Specification.hs99
-rw-r--r--scaffolder/src/Text/Edifact/Scaffolder/Segments/Types.hs27
5 files changed, 220 insertions, 0 deletions
diff --git a/scaffolder/src/Text/Edifact/Scaffolder/Segments/Dependencies.hs b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Dependencies.hs
new file mode 100644
index 0000000..acb9ea8
--- /dev/null
+++ b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Dependencies.hs
@@ -0,0 +1,47 @@
1{-# LANGUAGE OverloadedStrings #-}
2
3module Text.Edifact.Scaffolder.Segments.Dependencies
4 ( -- *
5 mkDependenciesHaddock
6 , mkDependenciesImports
7 , mkDependenciesReexports
8 ) where
9
10import Text.Edifact.Scaffolder.Commons
11import Text.Edifact.Scaffolder.Segments.Types
12
13import Data.List.NonEmpty as NE (nonEmpty, toList)
14import Data.Maybe (catMaybes, mapMaybe)
15import Formatting as F
16
17mkDependenciesReexports :: NonEmpty Element -> Scaffolding [Export]
18mkDependenciesReexports = reexportDependencies fElementFunction
19
20mkDependenciesImports :: NonEmpty Element -> Scaffolding [ImportGroup]
21mkDependenciesImports elements =
22 let filterElements optic = mapMaybe optic . NE.toList
23 in maybe [] (pure . ImportGroup) . nonEmpty . catMaybes <$>
24 sequence
25 [ mkCompositeDependenciesImports (filterElements getComposite elements)
26 , mkSimpleDependenciesImports (filterElements getSimple elements)
27 ]
28
29mkSimpleDependenciesImports :: [SimpleCode] -> Scaffolding (Maybe Import)
30mkSimpleDependenciesImports =
31 ifNonEmpty (importDependencies "Simples" fSimpleParserFunction)
32
33mkCompositeDependenciesImports :: [CompositeCode] -> Scaffolding (Maybe Import)
34mkCompositeDependenciesImports =
35 ifNonEmpty (importDependencies "Composites" fCompositeParserFunction)
36
37ifNonEmpty :: Applicative f => (NonEmpty input -> f output) -> [input] -> f (Maybe output)
38ifNonEmpty f = traverse f . nonEmpty
39
40mkDependenciesHaddock :: NonEmpty Element -> Scaffolding [Text]
41mkDependenciesHaddock = haddockDependencies fElementFunction
42
43fElementFunction :: Format r (Element -> r)
44fElementFunction =
45 let buildElementFunction (Simple code _ _ _ _) = bprint fSimpleParserFunction code
46 buildElementFunction (Composite code _ _) = bprint fCompositeParserFunction code
47 in later buildElementFunction
diff --git a/scaffolder/src/Text/Edifact/Scaffolder/Segments/Elements.hs b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Elements.hs
new file mode 100644
index 0000000..4e8b39c
--- /dev/null
+++ b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Elements.hs
@@ -0,0 +1,26 @@
1module Text.Edifact.Scaffolder.Segments.Elements
2 ( listSegments
3 ) where
4
5import Text.Edifact.Scaffolder.Commons
6
7import Data.Char (isLower, toUpper)
8import Text.Parsec (eof, lower, satisfy, string,
9 (<?>))
10import Text.Parsec.String (Parser)
11
12listSegments :: Scaffolding [ElementWithDefinition SegmentCode]
13listSegments = listElements "segments" segmentCodeParser
14
15segmentCodeParser :: Parser SegmentCode
16segmentCodeParser = do
17 c1 <- lowerExceptU
18 c2 <- lower
19 c3 <- lower
20 let code = SegmentCode (toUpper <$> [c1,c2,c3])
21 code <$ string ".txt"
22 <* eof
23 <?> "SegmentCode"
24
25lowerExceptU :: Parser Char
26lowerExceptU = satisfy (\ c -> isLower c && c /= 'u')
diff --git a/scaffolder/src/Text/Edifact/Scaffolder/Segments/Implementation.hs b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Implementation.hs
new file mode 100644
index 0000000..8535a17
--- /dev/null
+++ b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Implementation.hs
@@ -0,0 +1,21 @@
1{-# LANGUAGE OverloadedStrings #-}
2
3module Text.Edifact.Scaffolder.Segments.Implementation
4 ( -- *
5 toImplementation
6 ) where
7
8import Text.Edifact.Scaffolder.Commons
9import Text.Edifact.Scaffolder.Segments.Types
10
11import Data.List.NonEmpty as NE (toList)
12import Formatting
13
14toImplementation :: NonEmpty Dependency -> [Text]
15toImplementation = haskellList . fmap callDependency . NE.toList
16
17callDependency :: Dependency -> Text
18callDependency (Dependency pos (Simple code _ presence _ _)) =
19 sformat ( quoted fPosition % " .@ " % fPresence % " simple" % fSimpleCode) pos presence code
20callDependency (Dependency pos (Composite code _ presence)) =
21 sformat ( quoted fPosition % " .@ " % fPresence % " composite" % fCompositeCode) pos presence code
diff --git a/scaffolder/src/Text/Edifact/Scaffolder/Segments/Specification.hs b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Specification.hs
new file mode 100644
index 0000000..39a7ad4
--- /dev/null
+++ b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Specification.hs
@@ -0,0 +1,99 @@
1module Text.Edifact.Scaffolder.Segments.Specification
2 ( -- *
3 specificationParser
4 , listCompositesAndSimples
5 ) where
6
7import Text.Edifact.Scaffolder.Commons
8import Text.Edifact.Scaffolder.Segments.Types
9
10import Text.Parsec as P (anyChar, choice,
11 count, digit,
12 endOfLine, many,
13 many1, manyTill,
14 oneOf, skipMany,
15 string, try,
16 upper, (<?>))
17import Text.Parsec.String (Parser)
18
19specificationParser :: Parser ((SegmentCode, SegmentName), [Dependency])
20specificationParser = do
21 segmentInfo <- scanUntil [ segmentParser ]
22 dependencies <- scan [ inLine dependencyParser ] <?> "Segments specification"
23 pure (segmentInfo, dependencies)
24
25listCompositesAndSimples :: Parser (SegmentCode, [Element])
26listCompositesAndSimples = do
27 parsed <- specificationParser
28 pure (fst $ fst parsed, dependencyElement <$> snd parsed)
29
30segmentParser :: Parser (SegmentCode, SegmentName)
31segmentParser = do
32 _ <- count 6 (oneOf "+*#|X ")
33 skipMany (string " ")
34 code <- SegmentCode <$> count 3 upper
35 _ <- count 2 (string " ")
36 skipMany (string " ")
37 name <- SegmentName <$> manyTill anyChar (() <$ try endOfLine)
38 pure (code, name)
39
40dependencyParser :: Parser Dependency
41dependencyParser =
42 Dependency <$> positionParser
43 <* many1 (oneOf "+*#|-X ")
44 <*> elementParser
45 <?> "Dependency"
46
47inLine :: Parser a -> Parser [a]
48inLine p = single (many (string " ") *> p)
49
50positionParser :: Parser Position
51positionParser =
52 fromString <$> count 3 digit
53 <?> "Position"
54
55elementParser :: Parser Element
56elementParser =
57 choice [ compositeParser
58 , simpleParser
59 ]
60 <?> "Element"
61
62compositeParser :: Parser Element
63compositeParser = Composite <$> compositeCodeParser
64 <* many (string " ")
65 <*> stringToPresenceParser
66 <* many1 (string " ")
67 <*> presenceParser
68 <* string " "
69 <* many (oneOf " 0123456789")
70 <?> "Composite"
71
72simpleParser :: Parser Element
73simpleParser = Simple <$> (fromString <$> count 4 digit)
74 <* many1 (string " ")
75 <*> stringToPresenceParser
76 <* many1 (string " ")
77 <*> presenceParser
78 <* string " "
79 <* many (oneOf " 0123456789")
80 <*> simpleTypeParser
81 <*> simpleLengthParser
82 <?> "Simple"
83
84simpleTypeParser :: Parser SimpleType
85simpleTypeParser = choice [ Alphanumeric <$ string "an"
86 , Alphabetic <$ string "a"
87 , Numeric <$ string "n"
88 ] <?> "SimpleType"
89
90simpleLengthParser :: Parser SimpleLength
91simpleLengthParser = choice [ UpTo <$> fmap fromString (string ".." >> many1 digit)
92 , Exactly <$> (fromString <$> many1 digit)
93 ] <?> "SimpleLength"
94
95compositeCodeParser :: Parser CompositeCode
96compositeCodeParser = do
97 initial <- oneOf "CE"
98 rest <- count 3 digit
99 pure (fromString (initial : rest))
diff --git a/scaffolder/src/Text/Edifact/Scaffolder/Segments/Types.hs b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Types.hs
new file mode 100644
index 0000000..6a34cbc
--- /dev/null
+++ b/scaffolder/src/Text/Edifact/Scaffolder/Segments/Types.hs
@@ -0,0 +1,27 @@
1module Text.Edifact.Scaffolder.Segments.Types where
2
3import Text.Edifact.Scaffolder.Commons
4
5data Dependency = Dependency { dependencyPosition :: Position
6 , dependencyElement :: Element
7 } deriving Show
8
9data Element = Composite CompositeCode Text Presence
10 | Simple SimpleCode Text Presence SimpleType SimpleLength
11 deriving (Show, Eq, Ord)
12
13data SimpleType = Alphanumeric | Alphabetic | Numeric deriving (Show, Eq, Ord)
14
15data SimpleLength = Exactly Text | UpTo Text deriving (Show, Eq, Ord)
16
17getCode :: Element -> String
18getCode (Simple (SimpleCode c) _ _ _ _) = c
19getCode (Composite (CompositeCode c) _ _) = c
20
21getSimple :: Element -> Maybe SimpleCode
22getSimple (Simple c _ _ _ _) = Just c
23getSimple _ = Nothing
24
25getComposite :: Element -> Maybe CompositeCode
26getComposite (Composite c _ _) = Just c
27getComposite _ = Nothing