1 {-# LANGUAGE DerivingStrategies #-}
2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4 module Text.Edifact.Scaffolder.Messages.Specification
11 import Text.Edifact.Scaffolder.Commons
12 import Text.Edifact.Scaffolder.Messages.Types
14 import Data.Maybe (mapMaybe)
17 type Parser = Parsec String GroupTrail
19 newtype GroupTrail = GroupTrail [GroupCode]
21 deriving newtype (Semigroup, Monoid)
23 messageNameParser :: Parser MessageCode
24 messageNameParser = scanUntil [
25 manyTill anyChar (string "Message Type : ") >> MessageCode <$> count 6 upper
28 specificationParser :: Parser [Dependency]
30 let scanElements = scan [ segmentInLine segmentElementParser
31 , groupInLine groupStartElementParser
33 in interpretDependencies <$> scanElements <?> "Messages specification"
35 listSegments :: Parser [SegmentCode]
36 listSegments = mapMaybe (getSegment . getElement) <$> specificationParser
38 interpretDependencies :: [Element] -> [Dependency]
39 interpretDependencies = fmap Dependency
41 groupInLine :: Parser a -> Parser [a]
42 groupInLine p = single (many (string " ") *> p <* countClosingGroups)
44 countClosingGroups :: Parser Int
46 let parser = many1 (char '-')
51 closingGroupTrail :: Parser [Element]
53 let groupEndParser = GroupEnd <$> popFromTrail
54 in countClosingGroups >>= flip count groupEndParser
56 groupStartElementParser :: Parser Element
57 groupStartElementParser =
58 let parseStart pos code rep = GroupStart code (Positional pos rep)
59 in parseStart <$> positionParser
60 <* many1 (choice [ () <$ try (oneOf "+*#|X "), () <$ try (string "- ") ])
66 groupCodeParser :: Parser GroupCode
68 let parser = manyTill (char '-') (try $ string "-- Segment group")
73 group = GroupCode <$> parser
74 in group >>= appendToTrail <?> "GroupCodeParser"
76 appendToTrail :: GroupCode -> Parser GroupCode
78 let append (GroupTrail trail) = GroupTrail (code : trail)
79 in code <$ modifyState append
81 popFromTrail :: Parser GroupCode
85 GroupTrail (current : trail) -> current <$ putState (GroupTrail trail)
86 GroupTrail [] -> unexpected "GroupEnd, when state is currently clear"
88 segmentTrail :: Parser [a]
89 segmentTrail = [] <$ (many1 (char ' ') <* many (char '|'))
91 segmentInLine :: Parser Element -> Parser [Element]
93 segment <- many (string " ") *> p
94 trail <- choice [ try closingGroupTrail
97 pure (segment : trail)
99 repetitionParser :: Parser Repetition
101 Repetition <$> presenceParser
102 <* many1 (string " ")
103 <*> cardinalityParser
106 positionParser :: Parser Position
108 fromString <$> many1 digit
111 segmentElementParser :: Parser Element
112 segmentElementParser =
113 let parseSegment pos code rep = Segment code (Positional pos rep)
114 in parseSegment <$> positionParser
115 <* many1 (oneOf "+*#|-X ")
116 <*> segmentCodeParser
117 <* many1 (string " ")
118 <* stringToPresenceParser
119 <* many1 (string " ")
123 segmentCodeParser :: Parser SegmentCode
125 fromString <$> count 3 upper
128 cardinalityParser :: Parser Cardinality
129 cardinalityParser = Cardinality . read <$> many1 digit