1 {-# LANGUAGE StandaloneDeriving #-}
2 {-# LANGUAGE NoMonomorphismRestriction #-}
3 {-# LANGUAGE UndecidableInstances #-}
4 {-# OPTIONS_GHC -fno-warn-orphans #-}
5 {-# OPTIONS_GHC -O0 #-}
9 import Test.Tasty.HUnit
11 import Control.Applicative (Applicative(..), Alternative(..))
12 import Control.Arrow (first)
13 import Control.Monad (Monad(..), MonadPlus(..))
14 import Control.Monad.Trans.Class (MonadTrans(..))
16 import Data.Char (Char)
18 import Data.Decimal (DecimalRaw(..))
19 import Data.Either (Either(..), rights)
21 import Data.Fixed (Pico)
22 import Data.Function (($), (.), const, flip)
23 import Data.Functor (Functor(..), (<$>))
24 import Data.Functor.Identity (Identity(..))
26 import Data.List.NonEmpty (NonEmpty(..))
27 import Data.Map.Strict (Map)
28 import Data.Maybe (Maybe(..), fromMaybe)
29 import Data.Monoid (Monoid(..), (<>))
30 import Data.Ord (Ord(..))
32 import Data.String (String)
33 import Data.Text (Text)
34 import Data.Type.Equality ((:~:)(..))
35 import Data.Word (Word)
36 import Prelude (Integer)
37 import System.FilePath.Posix (FilePath)
38 import Text.Show (Show(..))
39 import qualified Control.Exception.Safe as Exn
40 import qualified Control.Monad.Classes as MC
41 import qualified Control.Monad.Trans.State.Strict as SS
42 import qualified Data.Char as Char
43 import qualified Data.Foldable as Foldable
44 import qualified Data.List as List
45 import qualified Data.List.NonEmpty as NonEmpty
46 import qualified Data.Map.Strict as Map
47 import qualified Data.NonNull as NonNull
48 import qualified Data.Set as Set
49 import qualified Data.Strict as S
50 import qualified Data.Text as Text
51 import qualified Data.Time.Calendar as Time
52 import qualified Data.Time.LocalTime as Time
53 import qualified Data.TreeMap.Strict as TreeMap
54 import qualified Data.TreeMap.Strict.Zipper as TreeMap
55 import qualified Language.Symantic as Sym
56 import qualified Language.Symantic.Lib as Sym
57 -- import qualified Language.Symantic.Parsing as Sym
58 import qualified System.FilePath.Posix as FilePath
59 import qualified System.IO.Error as IO
60 import qualified Text.Megaparsec as P
61 import qualified Text.Megaparsec.Prim as P
63 import qualified Hcompta as H
64 import qualified Hcompta.LCC as LCC
65 import qualified Hcompta.LCC.Lib.Strict as S
66 import qualified Hcompta.LCC.Sym as Sym
68 import Prelude (Bounded)
69 import Control.Applicative (Alternative)
70 import Data.NonNull (NonNull)
72 test :: Text -> Assertion -> TestTree
73 test = testCase . elide . Foldable.foldMap escapeChar . Text.unpack
75 escapeChar :: Char -> String
76 escapeChar c | Char.isPrint c = [c]
77 escapeChar c = Char.showLitChar c ""
79 elide :: String -> String
80 elide s | List.length s > 42 = List.take 42 s <> ['…']
83 account :: [Text] -> LCC.Account
84 account = LCC.Account . NonNull.impureNonNull . (LCC.Name <$>)
86 tag :: [Text] -> Text -> LCC.Tag
88 (LCC.Tag_Path $ NonNull.impureNonNull (LCC.Name <$> p))
91 account_ref :: [Text] -> LCC.Tag_Path
92 account_ref p = LCC.Tag_Path $ NonNull.impureNonNull $ LCC.Name <$> p
94 account_refs :: [([Text], [[Text]])] -> Map LCC.Tag_Path (Map LCC.Account ())
97 (<$> l) $ \(anch, accts) ->
98 ( LCC.Tag_Path $ NonNull.impureNonNull $ LCC.Name <$> anch
99 , Map.fromList $ (,()) . account <$> accts
102 tags :: [([Text], Text)] -> LCC.Tags
105 TreeMap.from_List (flip (<>)) $
107 (NonNull.impureNonNull (LCC.Name <$> p), [LCC.Tag_Data v])
109 amounts :: [(Text, LCC.Quantity)] -> LCC.Amounts
116 postings :: [LCC.Posting] -> LCC.Postings
119 Map.fromListWith (flip (<>)) $
121 (LCC.posting_account p, [p])
123 comments :: [Text] -> [LCC.Comment]
124 comments = (LCC.Comment <$>)
126 sourcePos :: FilePath -> Word -> Word -> P.SourcePos
127 sourcePos fp l c = P.SourcePos fp (P.unsafePos l) (P.unsafePos c)
129 date :: Integer -> Int -> Int -> Int -> Int -> Pico -> Time.TimeZone -> LCC.Date
130 date y m d h m' s tz =
131 Time.zonedTimeToUTC $
134 (Time.fromGregorian y m d)
135 (Time.TimeOfDay h m' s))
139 newtype Parsec e s m a
140 = Parsec { unParsec :: P.ParsecT e s m a }
141 deriving (Functor, Applicative, Monad, MonadTrans, Alternative, MonadPlus, P.MonadParsec e s)
143 type instance MC.CanDo (Parsec e s m) (MC.EffState a) = 'False
144 type instance MC.CanDo (Parsec e s m) (MC.EffReader P.SourcePos) = 'True
145 type instance MC.CanDo (Parsec e s m) (MC.EffReader (S.Either Exn.IOException LCC.CanonFile)) = 'True
147 instance -- Gram_File
150 , MC.MonadState Context_Test (Parsec e s m)
151 , P.MonadParsec e s (P.ParsecT e s m)
152 , P.MonadParsec e s (Parsec e s m)
154 ) => LCC.Gram_IO (Parsec e Text m) where
157 return (fp, Right $ LCC.CanonFile fp)
162 S.Left e -> return $ \at -> S.Left $ at e
164 db <- context_test_files <$> MC.get
165 case Map.lookup fp db of
166 Nothing -> return $ \at -> S.Left $ at $
167 LCC.Error_Journal_Read fp $
168 IO.userError $ show db
169 Just txt -> return $ const $ S.Right (fp, txt)
171 S.Left e -> return $ S.Left [e]
172 S.Right (LCC.PathFile fp_new, s_new) -> do
173 P.pushPosition $ P.initialPos fp_new
174 s_old <- P.getInput; P.setInput s_new
182 deriving instance LCC.ParsecC e s => Sym.Alter (Parsec e s m)
183 deriving instance LCC.ParsecC e s => Sym.Alt (Parsec e s m)
184 deriving instance LCC.ParsecC e s => Sym.App (Parsec e s m)
185 deriving instance LCC.ParsecC e s => Sym.Try (Parsec e s m)
186 deriving instance LCC.ParsecC e s => Sym.Gram_Rule (Parsec e s m)
187 deriving instance LCC.ParsecC e s => Sym.Gram_Terminal (Parsec e s m)
188 deriving instance LCC.ParsecC e s => Sym.Gram_RegR (Parsec e s m)
189 deriving instance LCC.ParsecC e s => Sym.Gram_RegL (Parsec e s m)
190 deriving instance LCC.ParsecC e s => Sym.Gram_CF (Parsec e s m)
191 deriving instance LCC.ParsecC e s => Sym.Gram_Meta P.SourcePos (Parsec e s m)
192 deriving instance LCC.ParsecC e s => Sym.Gram_Lexer (Parsec e s m)
193 deriving instance LCC.ParsecC e s => Sym.Gram_Op (Parsec e s m)
194 deriving instance LCC.ParsecC e s => LCC.Gram_Count (Parsec e s m)
195 deriving instance LCC.ParsecC e s => LCC.Gram_At (Parsec e s m)
196 deriving instance LCC.ParsecC e s => LCC.Gram_Char (Parsec e s m)
197 deriving instance LCC.ParsecC e s => LCC.Gram_Comment (Parsec e s m)
198 deriving instance LCC.ParsecC e s => LCC.Gram_Tag (Parsec e s m)
199 deriving instance LCC.ParsecC e s => LCC.Gram_Account (Parsec e s m)
200 deriving instance LCC.ParsecC e s => LCC.Gram_Amount (Parsec e s m)
201 deriving instance -- Gram_Posting
203 , LCC.Gram_Posting (P.ParsecT e s m)
204 , MC.MonadState (S.Maybe LCC.Unit) m
205 , MC.MonadState LCC.Chart m
206 , MC.MonadState LCC.Style_Amounts m
207 , MC.MonadState LCC.Year m
208 ) => LCC.Gram_Posting (Parsec e s m)
209 deriving instance -- Gram_Date
211 , LCC.Gram_Date (P.ParsecT e s m)
212 , MC.MonadState LCC.Year m
213 ) => LCC.Gram_Date (Parsec e s m)
214 deriving instance -- Gram_Transaction
216 , LCC.Gram_Transaction (P.ParsecT e s m)
217 , MC.MonadState (S.Maybe LCC.Unit) m
218 , MC.MonadState LCC.Chart m
219 , MC.MonadState LCC.Section m
220 , MC.MonadState LCC.Style_Amounts m
221 , MC.MonadState LCC.Year m
222 ) => LCC.Gram_Transaction (Parsec e s m)
223 deriving instance -- Gram_Chart
225 , LCC.Gram_Chart (P.ParsecT e s m)
226 , MC.MonadState LCC.Chart m
227 , MC.MonadState LCC.Section m
228 ) => LCC.Gram_Chart (Parsec e s m)
229 deriving instance (LCC.ParsecC e s, LCC.Gram_File (P.ParsecT e s m))
230 => LCC.Gram_File (Parsec e s m)
231 instance -- Gram_Journal
237 , LCC.Gram_Reader (S.Either Exn.IOException LCC.CanonFile) g
238 , LCC.Gram_State Context_Test g
239 , LCC.Gram_State (LCC.Context_Read j) g
240 , LCC.Gram_State (LCC.Journal j) g
241 , LCC.Gram_State (LCC.Journals j) g
242 , LCC.Gram_State (LCC.Env cs is) g
243 , LCC.Gram_Transaction g
244 , LCC.Gram_Term cs is (Parsec e Text m)
249 , g ~ Parsec e Text m
250 ) => LCC.Gram_Journal cs is j (Parsec e Text m)
251 deriving instance -- Gram_Term
252 ( Sym.Gram_Term is LCC.Meta (P.ParsecT e s m)
253 , Sym.Gram_Term_AtomsR LCC.Meta is is (Parsec e s m)
255 ) => Sym.Gram_Term is LCC.Meta (Parsec e s m)
256 deriving instance LCC.ParsecC e s => Sym.Gram_Meta LCC.Meta (Parsec e s m)
257 deriving instance LCC.ParsecC e s => Sym.Gram_Error (Parsec e s m)
258 deriving instance LCC.ParsecC e s => Sym.Gram_Name (Parsec e s m)
259 deriving instance LCC.ParsecC e s => Sym.Gram_Term_Type LCC.Meta (Parsec e s m)
260 deriving instance LCC.ParsecC e s => Sym.Gram_Type LCC.Meta (Parsec e s m)
261 deriving instance -- Gram_Term
262 ( LCC.Gram_Term cs is (P.ParsecT e s m)
263 , Sym.Gram_Term is LCC.Meta (Parsec e s m)
264 , MC.MonadState (LCC.Env cs is) m
266 ) => LCC.Gram_Term cs is (Parsec e s m)
267 instance -- Gram_State
269 , MC.MonadState ctx (Parsec e s m)
270 ) => LCC.Gram_State ctx (Parsec e s m) where
285 instance -- Gram_Reader
287 , MC.MonadReader ctx (Parsec e s m)
288 ) => LCC.Gram_Reader ctx (Parsec e s m) where
297 instance LCC.ParsecC e s => MC.MonadReaderN 'MC.Zero
298 P.SourcePos (Parsec e s m) where
299 askN _px = Parsec P.getPosition
300 instance LCC.ParsecC e s => MC.MonadReaderN 'MC.Zero
301 (NonEmpty P.SourcePos) (Parsec e s m) where
302 askN _px = Parsec $ P.statePos <$> P.getParserState
303 instance LCC.ParsecC e s => MC.MonadReaderN 'MC.Zero
304 (S.Either Exn.IOException LCC.CanonFile) (Parsec e s m) where
305 askN _px = Parsec $ S.Right . LCC.CanonFile . LCC.PathFile . P.sourceName <$> P.getPosition
307 -- * Type 'Context_Test'
310 { context_test_files :: Map LCC.PathFile Text
311 } deriving (Eq, Show)
312 type instance MC.CanDo (S.StateT (LCC.Context_Read j) m) (MC.EffState Context_Test) = 'False
313 type instance MC.CanDo (S.StateT Context_Test m) (MC.EffState Context_Test) = 'True
314 type instance MC.CanDo (S.StateT (LCC.Context_Sym cs is) m) (MC.EffState Context_Test) = 'False
315 instance Monad m => MC.MonadStateN 'MC.Zero Context_Test (S.StateT Context_Test m) where
316 stateN _px = S.StateT . SS.state
318 type instance MC.CanDo (S.StateT Context_Test m) (MC.EffState (Sym.Tokenizers meta is)) = 'False
321 :: forall is j cs e m a.
323 , LCC.Gram_File (P.ParsecT P.Dec Text m)
324 , Sym.Tokenize LCC.Meta is
325 , m ~ S.StateT (LCC.Context_Read j)
326 (S.StateT (LCC.Context_Sym cs is)
327 (S.StateT Context_Test Identity))
328 , e ~ P.ParseError Char P.Dec
329 , cs ~ Sym.TyConsts_of_Ifaces is
330 ) => Sym.CF (Parsec P.Dec Text m) a
331 -> [(LCC.PathFile, Text)]
334 -> Either (P.ParseError Char P.Dec) a
335 read g files fp inp =
337 S.evalState Context_Test{ context_test_files = Map.fromList files } $
338 S.evalState LCC.context_sym $
339 S.evalState LCC.context_read $
340 P.runParserT (unParsec . Sym.unCF $ g <* Sym.eoi)
341 (case fp of "" -> ""; _ -> FilePath.normalise fp) inp
344 = S.StateT (LCC.Context_Read j)
345 (S.StateT (LCC.Context_Sym cs is)
346 (S.StateT Context_Test Identity))
349 :: forall is is' cs h j.
351 , is ~ (Proxy Bool ': Proxy LCC.Journal ': Proxy LCC.Transaction ': Proxy [] ': is')
352 , Sym.Tokenize LCC.Meta is
353 , Sym.Inj_Token LCC.Meta is (->)
354 , Sym.Inj_TyConst cs Bool
355 , Sym.Inj_TyConst cs LCC.Journal
356 , Sym.Inj_TyConst cs LCC.Transaction
357 , Sym.Inj_TyConst cs []
358 -- , Sym.Inj_TyConst cs Show
359 -- , Sym.Inj_TyConst cs Eq
361 , Sym.Show_Token LCC.Meta is
362 , Sym.Show_TyConst cs
364 , Sym.Eq_Token LCC.Meta is
365 , Sym.Gram_Term is LCC.Meta (P.ParsecT P.Dec Text (M cs is j))
366 , Sym.Sym_of_Ifaces is Sym.HostI
367 , Sym.Gram_Term_AtomsR LCC.Meta is is (P.ParsecT P.Dec Text (M cs is j))
368 , Sym.Gram_Term_AtomsR LCC.Meta is is (Parsec P.Dec Text (M cs is j))
369 , cs ~ Sym.TyConsts_of_Ifaces is
375 , Either (Either (P.ParseError Char P.Dec)
376 (LCC.At (Sym.Error_Term LCC.Meta cs is)))
380 test_compile _j i (n_exp, ty_exp, lr_exp) =
381 let inp = Text.intercalate "\n" i in
382 let env :: LCC.Env cs is = Map.fromList
383 [ ("j" , Sym.ETerm (Sym.ty @Bool) $ Sym.Term $ Sym.bool True)
384 , ("jnl", Sym.ETerm (Sym.ty @LCC.Journal Sym.:$ (Sym.ty @[] Sym.:$ Sym.ty @LCC.Transaction)) $ Sym.Term $ Sym.journal LCC.journal)
387 case read @is @j (LCC.g_put (pure (env, ())) *> LCC.g_term) [] "" inp of
388 Left err_syn -> Left (Left err_syn) @?= lr_exp
389 Right (n_got, lr_sem) ->
391 Left err_sem -> Left (Right err_sem) @?= lr_exp
392 Right (Sym.ETerm ty_got t@(Sym.Term te_got)) ->
395 Left err -> Right ("…"::Text) @?= Left err
396 Right (_te_exp::h) ->
397 (>>= (@?= (n_exp, lr_exp))) $
399 case ty_got `Sym.eq_Type` ty_exp of
403 LCC.At (P.initialPos "" :| []) (P.initialPos "") $
404 Sym.Error_Term_Con_Type $ Right $
406 (Right $ Sym.At Nothing $ Sym.EType ty_got)
407 (Sym.At Nothing $ Sym.EType ty_exp)
411 Right $ Sym.host_from_term te_got
414 :: forall is cs j e m a.
416 , LCC.Gram_File (P.ParsecT P.Dec Text m)
417 , Sym.Tokenize LCC.Meta is
418 , m ~ S.StateT (LCC.Context_Read j)
419 (S.StateT (LCC.Context_Sym cs is)
420 (S.StateT Context_Test Identity))
421 , e ~ P.ParseError Char P.Dec
422 , j ~ [LCC.Transaction]
423 , cs ~ Sym.TyConsts_of_Ifaces is
426 => Sym.CF (Parsec P.Dec Text m) a
428 -> Either (P.ParseError Char P.Dec) a
431 S.evalState Context_Test{ context_test_files = Map.fromList [] } $
432 S.evalState LCC.context_sym $
433 S.evalState LCC.context_read $
434 P.runParserT (unParsec . Sym.unCF $ g <* Sym.eoi) "" inp
437 tests = testGroup "Read"
438 [{- testGroup "Date" $
441 read_gram LCC.g_date inp @?= Right (S.Right exp) in
442 [ "2000-01-13" ==> date 2000 01 13 0 0 0 Time.utc
443 , "2000-01-13_12:34" ==> date 2000 01 13 12 34 0 Time.utc
444 , "2000-01-13_12:34:56" ==> date 2000 01 13 12 34 56 Time.utc
445 , "2000-01-13_12:34_CET" ==> date 2000 01 13 12 34 0 (Time.TimeZone 60 True "CET")
446 , "2000-01-13_12:34+01:30" ==> date 2000 01 13 12 34 0 (Time.TimeZone 90 False "+01:30")
447 , "2000-01-13_12:34:56_CET" ==> date 2000 01 13 12 34 56 (Time.TimeZone 60 True "CET")
448 , "01-01" ==> date 1970 01 01 0 0 0 Time.utc
449 , testGroup "Parsing errors" $
452 read_gram LCC.g_date inp @?= Left exp in
453 [ "2000/01/13" !=> P.ParseError
454 { P.errorPos = sourcePos "" 1 5 :| []
455 , P.errorUnexpected = Set.fromList [P.Tokens ('/' :| "")]
456 , P.errorExpected = Set.fromList [P.Tokens ('-' :| "")]
457 , P.errorCustom = Set.fromList []
460 , testGroup "Semantic errors" $
463 read_gram LCC.g_date inp @?= Right (S.Left exp) in
464 [ "2000-13-01" =!> LCC.At
465 { LCC.atBegin = pure $ sourcePos "" 1 1
466 , LCC.atEnd = sourcePos "" 1 11
467 , LCC.atItem = LCC.Error_Date_Day_invalid (2000, 13, 01) }
468 , "2001-02-29" =!> LCC.At
469 { LCC.atBegin = pure $ sourcePos "" 1 1
470 , LCC.atEnd = sourcePos "" 1 11
471 , LCC.atItem = LCC.Error_Date_Day_invalid (2001, 2, 29) }
472 , "2000-01-13_12:60" =!> LCC.At
473 { LCC.atBegin = pure $ sourcePos "" 1 12
474 , LCC.atEnd = sourcePos "" 1 17
475 , LCC.atItem = LCC.Error_Date_TimeOfDay_invalid (12, 60, 0) }
478 , testGroup "Account_Section" $
481 rights [read_gram LCC.g_account_section inp]
482 @?= [LCC.Name inp | exp] in
490 , testGroup "Parsing errors"
509 , testGroup "Account" $
512 read_gram LCC.g_account inp
513 @?= Right (account exp) in
515 , "/A/B" ==> ["A", "B"]
516 , "/A/B/C" ==> ["A", "B","C"]
517 , "/Aa/Bbb/Cccc" ==> ["Aa", "Bbb", "Cccc"]
518 , "/A/B/(C)" ==> ["A", "B", "(C)"]
519 , testGroup "Parsing errors" $
522 rights [read_gram LCC.g_account inp]
531 , "/A a / B b b / C c c c" !=> []
534 , testGroup "Amount" $
537 read_gram LCC.g_amount inp @?= Right exp in
540 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )
543 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )
545 ( LCC.style_amount { LCC.style_amount_fractioning = pure '.' }
546 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )
548 ( LCC.style_amount { LCC.style_amount_fractioning = pure ',' }
549 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )
551 ( LCC.style_amount { LCC.style_amount_fractioning = pure '.' }
552 , LCC.amount { LCC.amount_quantity = Decimal 1 0 } )
554 ( LCC.style_amount { LCC.style_amount_fractioning = pure '.' }
555 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )
557 ( LCC.style_amount { LCC.style_amount_fractioning = pure ',' }
558 , LCC.amount { LCC.amount_quantity = Decimal 1 0 } )
560 ( LCC.style_amount { LCC.style_amount_fractioning = pure ',' }
561 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )
563 ( LCC.style_amount { LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [1] }
564 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )
566 ( LCC.style_amount { LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [2] }
567 , LCC.amount { LCC.amount_quantity = Decimal 0 0 } )
570 { LCC.style_amount_fractioning = pure '.'
571 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping ',' [3] }
572 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )
575 { LCC.style_amount_fractioning = pure ','
576 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '.' [3] }
577 , LCC.amount { LCC.amount_quantity = Decimal 2 0 } )
580 { LCC.style_amount_fractioning = pure '.'
581 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping ',' [3] }
582 , LCC.amount { LCC.amount_quantity = Decimal 2 100000 } )
585 { LCC.style_amount_fractioning = pure ','
586 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '.' [3] }
587 , LCC.amount { LCC.amount_quantity = Decimal 2 100000 } )
590 , LCC.amount { LCC.amount_quantity = Decimal 0 123 } )
592 ( LCC.style_amount { LCC.style_amount_fractioning = pure '.' }
593 , LCC.amount { LCC.amount_quantity = Decimal 1 12 } )
595 ( LCC.style_amount { LCC.style_amount_fractioning = pure ',' }
596 , LCC.amount { LCC.amount_quantity = Decimal 1 12 } )
598 ( LCC.style_amount { LCC.style_amount_fractioning = pure '.' }
599 , LCC.amount { LCC.amount_quantity = Decimal 2 1234 } )
601 ( LCC.style_amount { LCC.style_amount_fractioning = pure ',' }
602 , LCC.amount { LCC.amount_quantity = Decimal 2 1234 } )
604 ( LCC.style_amount { LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [1] }
605 , LCC.amount { LCC.amount_quantity = Decimal 0 12 } )
607 ( LCC.style_amount { LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [2] }
608 , LCC.amount { LCC.amount_quantity = Decimal 0 123 } )
610 ( LCC.style_amount { LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [3, 2] }
611 , LCC.amount { LCC.amount_quantity = Decimal 0 123456 } )
612 , "1_23_456,7890_12345_678901" ==>
614 { LCC.style_amount_fractioning = pure ','
615 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [3, 2]
616 , LCC.style_amount_grouping_fractional = pure $ LCC.Style_Amount_Grouping '_' [4, 5, 6] }
617 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )
618 , "1_23_456.7890_12345_678901" ==>
620 { LCC.style_amount_fractioning = pure '.'
621 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [3, 2]
622 , LCC.style_amount_grouping_fractional = pure $ LCC.Style_Amount_Grouping '_' [4, 5, 6] }
623 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )
624 , "1,23,456.7890_12345_678901" ==>
626 { LCC.style_amount_fractioning = pure '.'
627 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping ',' [3, 2]
628 , LCC.style_amount_grouping_fractional = pure $ LCC.Style_Amount_Grouping '_' [4, 5, 6] }
629 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )
630 , "1.23.456,7890_12345_678901" ==>
632 { LCC.style_amount_fractioning = pure ','
633 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '.' [3, 2]
634 , LCC.style_amount_grouping_fractional = pure $ LCC.Style_Amount_Grouping '_' [4, 5, 6] }
635 , LCC.amount { LCC.amount_quantity = Decimal 15 123456789012345678901 } )
636 , "123456_78901_2345.678_90_1" ==>
638 { LCC.style_amount_fractioning = pure '.'
639 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '_' [4, 5, 6]
640 , LCC.style_amount_grouping_fractional = pure $ LCC.Style_Amount_Grouping '_' [3, 2] }
641 , LCC.amount { LCC.amount_quantity = Decimal 6 123456789012345678901 } )
644 { LCC.style_amount_unit_side = pure LCC.L
645 , LCC.style_amount_unit_spaced = pure False }
647 { LCC.amount_quantity = Decimal 0 1
648 , LCC.amount_unit = "$" } )
651 { LCC.style_amount_unit_side = pure LCC.R
652 , LCC.style_amount_unit_spaced = pure False }
654 { LCC.amount_quantity = Decimal 0 1
655 , LCC.amount_unit = "$" } )
658 { LCC.style_amount_unit_side = pure LCC.L
659 , LCC.style_amount_unit_spaced = pure True }
661 { LCC.amount_quantity = Decimal 0 1
662 , LCC.amount_unit = "$" } )
665 { LCC.style_amount_unit_side = pure LCC.R
666 , LCC.style_amount_unit_spaced = pure True }
668 { LCC.amount_quantity = Decimal 0 1
669 , LCC.amount_unit = "$" } )
672 { LCC.style_amount_unit_side = pure LCC.L
673 , LCC.style_amount_unit_spaced = pure False }
675 { LCC.amount_quantity = Decimal 0 (-1)
676 , LCC.amount_unit = "$" } )
679 { LCC.style_amount_fractioning = pure ','
680 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '.' [3]
681 , LCC.style_amount_unit_side = pure LCC.L
682 , LCC.style_amount_unit_spaced = pure False }
684 { LCC.amount_quantity = Decimal 2 100000
685 , LCC.amount_unit = "$" } )
688 { LCC.style_amount_fractioning = pure ','
689 , LCC.style_amount_grouping_integral = pure $ LCC.Style_Amount_Grouping '.' [3]
690 , LCC.style_amount_unit_side = pure LCC.R
691 , LCC.style_amount_unit_spaced = pure False }
693 { LCC.amount_quantity = Decimal 2 100000
694 , LCC.amount_unit = "$" } )
695 , testGroup "Parsing errors" $
698 rights [read_gram LCC.g_amount inp] @?= [] in
709 , testGroup "Comment" $
710 let (==>) (inp, post) exp =
712 rights [read_gram (LCC.g_comment <* post) inp]
713 @?= (LCC.Comment <$> exp) in
714 [ ("; a b c" , Sym.eoi) ==> [ "a b c" ]
715 , ("; #a" , Sym.eoi) ==> [ "#a" ]
716 , ("; a b c \n" , Sym.string " \n") ==> [ "a b c" ]
717 , ("; a b c \r\n", Sym.string " \r\n") ==> [ "a b c" ]
718 -- , ("; a b c\n ; d e f", Sym.eoi) ==> [ ["a b c", "d e f"] ]
719 -- , ("; a b c \n", Sym.string " \n") ==> [ ["a b c"] ]
721 , testGroup "Transaction_Tag" $
724 read_gram LCC.g_transaction_tag inp
725 @?= Right (LCC.Transaction_Tag exp) in
726 [ "#Name" ==> tag ["Name"] ""
727 , "#Name:name" ==> tag ["Name", "name"] ""
728 , "#Name=Value" ==> tag ["Name"] "Value"
729 , "#Name = Value" ==> tag ["Name"] "Value"
730 , "#Name=Val ue" ==> tag ["Name"] "Val ue"
731 , "#Name=," ==> tag ["Name"] ","
732 , "#Name=Val,ue" ==> tag ["Name"] "Val,ue"
733 , "#Name=Val,ue:" ==> tag ["Name"] "Val,ue:"
734 , "#Name=Val,ue :" ==> tag ["Name"] "Val,ue :"
735 , testGroup "Parsing errors" $
738 rights [read_gram LCC.g_transaction_tag inp] @?= [] in
740 , "#Name=Value\n" !=> []
743 , testGroup "Posting" $
746 read_gram LCC.g_posting inp @?= Right (S.Right exp) in
747 [ "/A/B/C" ==> LCC.posting (account ["A", "B", "C"])
748 , "/A/B/C $1" ==> (LCC.posting $ account ["A", "B", "C"])
749 { LCC.posting_amounts = amounts [("$", 1)] }
750 , "/A/B/C $1" ==> (LCC.posting $ account ["A", "B", "C"])
751 { LCC.posting_amounts = amounts [("$", 1)] }
752 , "/A/B/C 1€" ==> (LCC.posting $ account ["A", "B", "C"])
753 { LCC.posting_amounts = amounts [("€", 1)] }
754 , "/A/B/C $1; some comment" ==> (LCC.posting $ account ["A", "B", "C"])
755 { LCC.posting_amounts = amounts [("$", 1)]
756 , LCC.posting_comments = comments ["some comment"] }
757 , "/A/B/C; some comment" ==>
758 (LCC.posting $ account ["A", "B", "C"])
759 { LCC.posting_comments = comments ["some comment"] }
760 , "/A/B/C ; some comment" ==> (LCC.posting $ account ["A", "B", "C"])
761 { LCC.posting_amounts = amounts []
762 , LCC.posting_comments = comments ["some comment"] }
763 , "/A/B/C ; some comment\n ; some other comment" ==>
764 (LCC.posting $ account ["A", "B", "C"])
765 { LCC.posting_amounts = amounts []
766 , LCC.posting_comments = comments ["some comment", "some other comment"] }
767 , "/A/B/C $1 ; some comment" ==>
768 (LCC.posting $ account ["A", "B", "C"])
769 { LCC.posting_amounts = amounts [("$", 1)]
770 , LCC.posting_comments = comments ["some comment"] }
772 (LCC.posting $ account ["A", "B", "C"])
773 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V") ] }
774 , "/A/B/C #N:O=V" ==>
775 (LCC.posting $ account ["A", "B", "C"])
776 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N", "O"], "V") ] }
777 , "/A/B/C #N=Val;ue" ==>
778 (LCC.posting $ account ["A", "B", "C"])
779 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "Val;ue") ] }
780 , "/A/B/C #N=Val#ue" ==>
781 (LCC.posting $ account ["A", "B", "C"])
782 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "Val#ue") ] }
783 , "/A/B/C #N=V ; not a comment" ==>
784 (LCC.posting $ account ["A", "B", "C"])
785 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V ; not a comment") ] }
786 , "/A/B/C #N=V #O" ==>
787 (LCC.posting $ account ["A", "B", "C"])
788 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V #O") ] }
790 (LCC.posting $ account ["A", "B", "C"])
791 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (,) ["N"] "", (,) ["O"] "" ] }
792 , "/A/B/C #N; #O" ==>
793 (LCC.posting $ account ["A", "B", "C"])
794 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "") ]
795 , LCC.posting_comments = comments ["#O"] }
797 (LCC.posting $ account ["A", "B", "C"])
798 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (,) ["N"] "", (,) ["O"] "" ] }
799 , "/A/B/C \n #N=V" ==>
800 (LCC.posting $ account ["A", "B", "C"])
801 { LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V") ] }
802 , "/A/B/C ; some comment\n #N=V" ==>
803 (LCC.posting $ account ["A", "B", "C"])
804 { LCC.posting_comments = comments ["some comment"]
805 , LCC.posting_tags = LCC.Posting_Tags $ tags [ (["N"], "V") ] }
806 , "/A/B/C ; some comment\n #N=V v\n #N2=V2 v2" ==>
807 (LCC.posting $ account ["A", "B", "C"])
808 { LCC.posting_comments = comments ["some comment"]
809 , LCC.posting_tags = LCC.Posting_Tags $ tags
811 , (["N2"], "V2 v2") ] }
812 , "/A/B/C\n #N=V\n #N=V2" ==>
813 (LCC.posting $ account ["A", "B", "C"])
814 { LCC.posting_tags = LCC.Posting_Tags $ tags
818 , "/A/B/C\n #N=V\n #N2=V" ==>
819 (LCC.posting $ account ["A", "B", "C"])
820 { LCC.posting_tags = LCC.Posting_Tags $ tags
825 , testGroup "Transaction" $
827 let inp = Text.intercalate "\n" i in
829 read_gram LCC.g_transaction inp @?= Right (S.Right e) in
830 [ [ "2000-01-01 some wording"
833 ] ==> LCC.transaction
834 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
835 , LCC.transaction_wording = "some wording"
836 , LCC.transaction_postings = postings
837 [ (LCC.posting $ account ["A", "B", "C"])
838 { LCC.posting_amounts = amounts [ ("$", 1) ]
839 , LCC.posting_sourcepos = sourcePos "" 2 2 }
840 , (LCC.posting $ account ["D", "E", "F"])
841 { LCC.posting_amounts = amounts [ ("$", -1) ]
842 , LCC.posting_sourcepos = sourcePos "" 3 2 }
845 , [ "2000-01-01 some wording ; not a comment"
846 , "; some other;comment"
847 , " ; some last comment"
850 ] ==> LCC.transaction
851 { LCC.transaction_comments = comments
852 [ "some other;comment"
853 , "some last comment"
855 , LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
856 , LCC.transaction_wording = "some wording ; not a comment"
857 , LCC.transaction_postings = postings
858 [ (LCC.posting $ account ["A", "B", "C"])
859 { LCC.posting_amounts = amounts [ ("$", 1) ]
860 , LCC.posting_sourcepos = sourcePos "" 4 2 }
861 , (LCC.posting $ account ["D", "E", "F"])
862 { LCC.posting_amounts = amounts [ ("$", -1) ]
863 , LCC.posting_sourcepos = sourcePos "" 5 2 }
866 , testGroup "Semantic errors" $
868 let inp = Text.intercalate "\n" i in
870 read_gram LCC.g_transaction inp @?= Right (S.Left e) in
871 [ [ "2000-01-01 wording"
875 { LCC.atBegin = pure $ sourcePos "" 1 1
876 , LCC.atEnd = sourcePos "" 3 12
877 , LCC.atItem = LCC.Error_Transaction_not_equilibrated
879 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
880 , LCC.transaction_wording = "wording"
881 , LCC.transaction_postings = postings
882 [ (LCC.posting $ account ["A", "B", "C"])
883 { LCC.posting_amounts = amounts [ ("$", 1) ]
884 , LCC.posting_sourcepos = sourcePos "" 2 2 }
885 , (LCC.posting $ account ["D", "E", "F"])
886 { LCC.posting_amounts = amounts [ ("$", -2) ]
887 , LCC.posting_sourcepos = sourcePos "" 3 2 }
892 { H.sumByUnit_quantity = H.Polarized_Both (-2) 1
893 , H.sumByUnit_accounts = Map.fromList []
898 ,-} testGroup "Term" $
899 let (==>) = test_compile
902 , Proxy LCC.Transaction
904 -- , Proxy LCC.Postings
921 , Proxy TreeMap.Zipper
923 ] (Proxy @[LCC.Transaction]) in
924 [ [ "x = 42" ] ==> ("x", Sym.ty @LCC.Quantity, Right 42.0)
925 , [ "x = 40 + 2" ] ==> ("x", Sym.ty @LCC.Quantity, Right 42.0)
926 , [ "x = $4.2" ] ==> ("x", Sym.ty @LCC.Amounts, Right $ amounts [ ("$", 4.2) ])
927 , [ "x = 4,2€" ] ==> ("x", Sym.ty @LCC.Amounts, Right $ amounts [ ("€", 4.2) ])
928 , [ "x = 4,2€ + $2.4" ] ==> ("x", Sym.ty @LCC.Amounts, Right $ amounts [ ("$", 2.4), ("€", 4.2) ])
929 , [ "x = 4,0€ + 0.2€" ] ==> ("x", Sym.ty @LCC.Amounts, Right $ amounts [ ("€", 4.2) ])
930 , [ "x = j" ] ==> ("x", Sym.ty @Bool, Right $ True )
931 , testGroup "Semantic errors" $
933 let inp = Text.intercalate "\n" i in
935 read_gram LCC.g_transaction inp @?= Right (S.Left e) in
939 {-, testGroup "Chart" $
941 let inp = Text.intercalate "\n" i in
944 LCC.g_get $ (\_txn ch -> ch) <$>
945 LCC.g_journal @(Sym.TyConsts_of_Ifaces '[Proxy (->)]) @'[Proxy (->)] (:)
947 let acct_path = NonEmpty.fromList . (LCC.Name <$>) in
948 let acct_tags = LCC.Account_Tags . tags in
953 { LCC.chart_accounts = TreeMap.from_List (<>)
954 [ (acct_path ["A", "B", "C"], acct_tags [])
955 , (acct_path ["D", "E", "F"], acct_tags [])
957 , LCC.chart_tags = Map.empty
967 { LCC.chart_accounts = TreeMap.from_List (<>)
968 [ (acct_path ["A", "B", "C"], acct_tags
970 , (["a0", "a1", "a2"], "")
972 , (acct_path ["D", "E", "F"], acct_tags
973 [ (["t0", "t1"], "v0")
974 , (["t0", "t1"], "v1") ])
976 , LCC.chart_tags = account_refs
980 , (,) ["a0", "a1", "a2"]
985 , testGroup "Journal" $
987 let inp = (Text.intercalate "\n" <$>) <$> i in
988 let jnl = fromMaybe "" $ List.lookup "" inp in
989 let exp = ((LCC.Journals . Map.fromList . (first LCC.CanonFile <$>)) <$>) <$> fe e in
991 read @'[Proxy (->)] @[LCC.Transaction] (
992 LCC.g_get $ (\j (js::LCC.Journals [LCC.Transaction]) -> const js <$> j) <$>
994 @(Sym.TyConsts_of_Ifaces '[Proxy (->)])
997 ) inp "" jnl @?= exp in
998 let (==>) = run (Right . S.Right) ; infixr 0 ==> in
999 let jnl :: LCC.Journal [LCC.Transaction] = LCC.journal in
1001 [ "2000-01-01 wording"
1007 { LCC.journal_content =
1009 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
1010 , LCC.transaction_wording = "wording"
1011 , LCC.transaction_sourcepos = sourcePos "" 1 1
1012 , LCC.transaction_postings = postings
1013 [ (LCC.posting $ account ["A", "B", "C"])
1014 { LCC.posting_amounts = amounts [ ("$", 1) ]
1015 , LCC.posting_sourcepos = sourcePos "" 2 2
1017 , (LCC.posting $ account ["D", "E", "F"])
1018 { LCC.posting_amounts = amounts [ ("$", -1) ]
1019 , LCC.posting_sourcepos = sourcePos "" 3 2
1024 {-, LCC.journal_amount_styles = LCC.Amount_Styles $ Map.fromList
1027 { LCC.amount_style_unit_side = Just LCC.L
1028 , LCC.amount_style_unit_spaced = Just False }
1035 [ "2000-01-01 1° wording"
1038 , "2000-01-02 2° wording"
1044 { LCC.journal_content =
1046 { LCC.transaction_dates = date 2000 01 02 0 0 0 Time.utc `NonNull.ncons` []
1047 , LCC.transaction_wording = "2° wording"
1048 , LCC.transaction_sourcepos = sourcePos "" 4 1
1049 , LCC.transaction_postings = postings
1050 [ (LCC.posting $ account ["A", "B", "C"])
1051 { LCC.posting_amounts = amounts [ ("$", 1) ]
1052 , LCC.posting_sourcepos = sourcePos "" 5 2
1054 , (LCC.posting $ account ["x", "y", "z"])
1055 { LCC.posting_amounts = amounts [ ("$", -1) ]
1056 , LCC.posting_sourcepos = sourcePos "" 6 2
1061 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
1062 , LCC.transaction_wording = "1° wording"
1063 , LCC.transaction_sourcepos = sourcePos "" 1 1
1064 , LCC.transaction_postings = postings
1065 [ (LCC.posting $ account ["A", "B", "C"])
1066 { LCC.posting_amounts = amounts [ ("$", 1) ]
1067 , LCC.posting_sourcepos = sourcePos "" 2 2
1069 , (LCC.posting $ account ["D", "E", "F"])
1070 { LCC.posting_amounts = amounts [ ("$", -1) ]
1071 , LCC.posting_sourcepos = sourcePos "" 3 2
1081 , "2000-01-01 wording"
1087 { LCC.journal_content =
1089 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
1090 , LCC.transaction_wording = "wording"
1091 , LCC.transaction_sourcepos = sourcePos "" 3 1
1092 , LCC.transaction_postings = postings
1093 [ (LCC.posting $ account ["A", "B", "C"])
1094 { LCC.posting_amounts = amounts [ ("$", 1) ]
1095 , LCC.posting_account_ref = S.Just $ account_ref ["AB"] S.:!: S.Just (account ["C"])
1096 , LCC.posting_sourcepos = sourcePos "" 4 2
1098 , (LCC.posting $ account ["D", "E", "F"])
1099 { LCC.posting_amounts = amounts [ ("$", -1) ]
1100 , LCC.posting_sourcepos = sourcePos "" 5 2
1110 , "2000-01-01 wording"
1122 { LCC.journal_includes =
1123 [ LCC.CanonFile "chart"
1125 , LCC.journal_content =
1127 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
1128 , LCC.transaction_wording = "wording"
1129 , LCC.transaction_sourcepos = sourcePos "" 3 1
1130 , LCC.transaction_postings = postings
1131 [ (LCC.posting $ account ["A", "B", "C"])
1132 { LCC.posting_amounts = amounts [ ("$", 1) ]
1133 , LCC.posting_account_ref = S.Just $ account_ref ["AB"] S.:!: S.Just (account ["C"])
1134 , LCC.posting_sourcepos = sourcePos "" 4 2
1136 , (LCC.posting $ account ["D", "E", "F"])
1137 { LCC.posting_amounts = amounts [ ("$", -1) ]
1138 , LCC.posting_account_ref = S.Just $ account_ref ["D"] S.:!: S.Just (account ["E", "F"])
1139 , LCC.posting_sourcepos = sourcePos "" 5 2
1146 { LCC.journal_file = "chart"
1168 { LCC.journal_includes =
1172 , LCC.journal_content =
1174 { LCC.transaction_dates = date 2000 01 01 0 0 0 Time.utc `NonNull.ncons` []
1175 , LCC.transaction_wording = "w"
1176 , LCC.transaction_sourcepos = sourcePos "" 1 1
1177 , LCC.transaction_postings = postings
1178 [ (LCC.posting $ account ["A", "B", "C"])
1179 { LCC.posting_amounts = amounts [ ("$", 1) ]
1180 , LCC.posting_sourcepos = sourcePos "" 2 2
1182 , (LCC.posting $ account ["D", "E", "F"])
1183 { LCC.posting_amounts = amounts [ ("$", -1) ]
1184 , LCC.posting_sourcepos = sourcePos "" 3 2
1191 { LCC.journal_file = "0"
1192 , LCC.journal_content =
1194 { LCC.transaction_dates = date 2000 01 02 0 0 0 Time.utc `NonNull.ncons` []
1195 , LCC.transaction_wording = "w0"
1196 , LCC.transaction_sourcepos = sourcePos "0" 1 1
1197 , LCC.transaction_postings = postings
1198 [ (LCC.posting $ account ["A", "B", "C"])
1199 { LCC.posting_amounts = amounts [ ("$", 2) ]
1200 , LCC.posting_sourcepos = sourcePos "0" 2 2
1202 , (LCC.posting $ account ["D", "E", "F"])
1203 { LCC.posting_amounts = amounts [ ("$", -2) ]
1204 , LCC.posting_sourcepos = sourcePos "0" 3 2
1211 { LCC.journal_file = "1"
1212 , LCC.journal_content =
1214 { LCC.transaction_dates = date 2000 01 03 0 0 0 Time.utc `NonNull.ncons` []
1215 , LCC.transaction_wording = "w1"
1216 , LCC.transaction_sourcepos = sourcePos "1" 1 1
1217 , LCC.transaction_postings = postings
1218 [ (LCC.posting $ account ["A", "B", "C"])
1219 { LCC.posting_amounts = amounts [ ("$", 3) ]
1220 , LCC.posting_sourcepos = sourcePos "1" 2 2
1222 , (LCC.posting $ account ["D", "E", "F"])
1223 { LCC.posting_amounts = amounts [ ("$", -3) ]
1224 , LCC.posting_sourcepos = sourcePos "1" 3 2
1231 , testGroup "Parsing errors" $
1232 let (!=>) = run Left ; infixr 0 !=> in
1237 [ "2000-01_01 wording"
1242 { P.errorPos = sourcePos "j" 1 8 :| [sourcePos "" 1 4]
1243 , P.errorUnexpected = Set.fromList [P.Tokens ('_' :| "")]
1244 , P.errorExpected = Set.fromList [P.Tokens ('-' :| "")]
1245 , P.errorCustom = Set.fromList []
1248 , testGroup "Semantic errors" $
1249 let (=!>) = run (Right . S.Left) ; infixr 0 =!> in
1251 [ "2000-01-01 wording"
1257 , "2000-01-01 wording"
1266 { LCC.atBegin = sourcePos "chart" 1 1 :| [sourcePos "" 5 8]
1267 , LCC.atEnd = sourcePos "chart" 1 9
1269 LCC.Error_Journal_Section
1270 LCC.Section_Transaction
1274 { LCC.atBegin = sourcePos "" 8 2 :| []
1275 , LCC.atEnd = sourcePos "" 8 5
1277 LCC.Error_Journal_Transaction $
1278 LCC.Error_Transaction_Posting $
1279 LCC.Error_Posting_Account_Ref_unknown $
1287 [ "2000-01-01 wording"
1295 { LCC.atBegin = sourcePos "j" 5 1 :| [sourcePos "" 1 4]
1296 , LCC.atEnd = sourcePos "j" 5 4
1297 , LCC.atItem = LCC.Error_Journal_Include_loop $ LCC.CanonFile "j"