1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-|
Data types to represent Edifact values.
See "Text.Edifact.Parsing" to learn how to build parsers and use such parsers.
-}
module Text.Edifact.Types
( -- * Values
Value(..)
, Primitive(..)
, Position(..)
-- ** Element codes
, MessageCode(..)
, GroupCode(..)
, SegmentCode(..)
, CompositeCode(..)
, SimpleCode(..)
-- * Syntax
, Syntax(..)
, defaultSyntax
) where
import Data.Scientific (Scientific)
import Data.String (IsString (..))
import Data.Text (Text)
-- | Code for a message.
--
-- Content is expected to match this regexp: @[A-Z]{6}@.
newtype MessageCode = MessageCode { getMessageCode :: String } deriving newtype (Eq, Show, IsString)
-- | Code for a segment group.
--
-- It's a code local to the message definition.
newtype GroupCode = GroupCode { getGroupCode :: String } deriving newtype (Eq, Show, IsString)
-- | Code for a segment.
--
-- Content is expected to match this regexp: @[A-Z]{3}@.
--
-- Standard segment codes are expected to match this regexp: @UN[A-Z]@.
newtype SegmentCode = SegmentCode { getSegmentCode :: String } deriving newtype (Eq, Show, IsString)
-- | Code for a composite element.
--
-- Content is expected to match this regexp: @C[0-9]{3}@.
--
-- It can also be used for standalone composites, frequently in standard segment
-- definitions. In this case the codes are expected to match this regexp: @S[0-9]{3}@.
newtype CompositeCode = CompositeCode String deriving newtype (Eq, Show, IsString)
-- | Code for a simple element.
--
-- Content is expected to match this regexp: @[0-9]{4}@.
newtype SimpleCode = SimpleCode String deriving newtype (Eq, Show, IsString)
-- | Annotation of the position of the value relative to the parent value.
--
-- Content is expected to match this regexp: @[0-9]{3,4}@.
--
-- Example values:
--
-- > "010" :: Position
-- > "0210" :: Position
--
-- See 'Text.Edifact.Parsing.position' for how to parse one.
newtype Position = Position { getPosition :: String } deriving newtype (Eq, Show, IsString)
-- | Representation of a simple component.
--
-- When defined by the 'Text.Edifact.Parsing.numeric' combinator, the simple
-- component will produce a 'Number'.
--
-- When parsed by the 'Text.Edifact.Parsing.alphaNumeric' or
-- 'Text.Edifact.Parsing.alpha' combinators, the simple component will produce a
-- 'Text.Edifact.Types.String' from the raw textual representation.
data Primitive = String Text -- ^ Default representation of a simple component.
| Number Scientific -- ^ Representation of a numerical simple component.
deriving stock (Eq, Show)
-- | String like primitive values can be constructed via overloaded strings.
-- This is convenient, but might be removed.
instance IsString Primitive where
fromString = String . fromString
-- | Recursive data structure to represent parsed Edifact values.
data Value = Message MessageCode [(Position, [Value])]
| Group GroupCode [(Position, [Value])]
| Segment SegmentCode [(Position, Maybe Value)]
| Composite CompositeCode [(Position, Maybe Value)]
| Simple SimpleCode Primitive
deriving stock (Show, Eq)
-- | Defines the special charactors the parser should respect.
--
-- This is defined in every payload via the @UNA@ segment (first segment expected).
data Syntax = Syntax { compositeSeparator :: Char
, elementSeparator :: Char
, decimalSign :: Char
, escape :: Char
, segmentSeparator :: Char
}
-- | Default value to initialize the parser.
--
-- > Syntax { compositeSeparator = ':'
-- > , elementSeparator = '+'
-- > , decimalSign = '.'
-- > , escape = '?'
-- > , segmentSeparator = '\''
-- > }
--
-- Those default charactors should be considered as recommended values rather
-- than official default values.
defaultSyntax :: Syntax
defaultSyntax =
Syntax { compositeSeparator = ':'
, elementSeparator = '+'
, decimalSign = '.'
, escape = '?'
, segmentSeparator = '\''
}
|