58
58
-- | `fun' [`pure'] [`unsafe'] idalias parms
61
-- | `pointer' ['*'] idalias ptrkind
61
-- | `pointer' ['*'] idalias ptrkind ['nocode']
62
62
-- | `class' [ident `=>'] ident ident
63
63
-- ctxt -> [`lib' `=' string] [prefix]
64
64
-- idalias -> ident [`as' (ident | `^')]
71
71
-- | apath `.' ident
72
72
-- | apath `->' ident
73
73
-- trans -> `{' alias_1 `,' ... `,' alias_n `}'
74
-- alias -> `underscoreToCase' | `upcaseFirstLetter'
75
-- | `downcaseFirstLetter'
74
76
-- | ident `as' ident
75
77
-- ptrkind -> [`foreign' | `stable'] ['newtype' | '->' ident]
79
-- If `underscoreToCase', `upcaseFirstLetter', or `downcaseFirstLetter'
80
-- occurs in a translation table, it must be the first entry, or if two of
81
-- them occur the first two entries.
78
83
-- Remark: Optional Haskell names are normalised during structure tree
79
84
-- construction, ie, associations that associated a name with itself
86
88
--- TODO ----------------------------------------------------------------------
89
module CHS (CHSModule(..), CHSFrag(..), CHSHook(..), CHSTrans(..), CHSParm(..),
90
CHSArg(..), CHSAccess(..), CHSAPath(..), CHSPtrType(..),
91
loadCHS, dumpCHS, hssuffix, chssuffix, loadCHI, dumpCHI,
92
chisuffix, showCHSParm)
91
module CHS (CHSModule(..), CHSFrag(..), CHSHook(..), CHSTrans(..),
92
CHSChangeCase(..), CHSParm(..), CHSArg(..), CHSAccess(..),
93
CHSAPath(..), CHSPtrType(..),
94
loadCHS, dumpCHS, hssuffix, chssuffix, loadCHI, dumpCHI, chisuffix,
95
98
-- standard libraries
209
213
posOf (CHSCall _ _ _ _ pos) = pos
210
214
posOf (CHSFun _ _ _ _ _ _ _ pos) = pos
211
215
posOf (CHSField _ _ pos) = pos
212
posOf (CHSPointer _ _ _ _ _ _ pos) = pos
216
posOf (CHSPointer _ _ _ _ _ _ _ pos) = pos
213
217
posOf (CHSClass _ _ _ pos) = pos
215
219
-- two hooks are equal if they have the same Haskell name and reference the
233
237
oalias1 == oalias2 && ide1 == ide2
234
238
(CHSField acc1 path1 _) == (CHSField acc2 path2 _) =
235
239
acc1 == acc2 && path1 == path2
236
(CHSPointer _ ide1 oalias1 _ _ _ _)
237
== (CHSPointer _ ide2 oalias2 _ _ _ _) =
240
(CHSPointer _ ide1 oalias1 _ _ _ _ _)
241
== (CHSPointer _ ide2 oalias2 _ _ _ _ _) =
238
242
ide1 == ide2 && oalias1 == oalias2
239
243
(CHSClass _ ide1 _ _) == (CHSClass _ ide2 _ _) =
243
247
-- translation table (EXPORTED)
245
249
data CHSTrans = CHSTrans Bool -- underscore to case?
250
CHSChangeCase -- upcase or downcase?
246
251
[(Ident, Ident)] -- alias list
253
data CHSChangeCase = CHSSameCase
248
258
-- marshalling descriptor for function hooks (EXPORTED)
250
260
-- * a marshaller consists of a function name and flag indicating whether it
493
503
(True , _ ) -> showString " newtype"
494
504
(False, Just ide) -> showString " -> " . showCHSIdent ide
495
505
(False, Nothing ) -> showString "")
507
True -> showString ""
508
False -> showString " nocode")
496
509
showCHSHook (CHSClass oclassIde classIde typeIde _) =
497
510
showString "class "
498
511
. (case oclassIde of
537
550
showHsVerb str = showChar '`' . showString str . showChar '\''
539
showCHSTrans :: CHSTrans -> ShowS
540
showCHSTrans (CHSTrans _2Case assocs) =
552
showCHSTrans :: CHSTrans -> ShowS
553
showCHSTrans (CHSTrans _2Case chgCase assocs) =
542
555
. (if _2Case then showString ("underscoreToCase" ++ maybeComma) else id)
556
. showCHSChangeCase chgCase
543
557
. foldr (.) id (intersperse (showString ", ") (map showAssoc assocs))
550
564
. showString " as "
551
565
. showCHSIdent ide2
567
showCHSChangeCase :: CHSChangeCase -> ShowS
568
showCHSChangeCase CHSSameCase = id
569
showCHSChangeCase CHSUpCase = showString "upcaseFirstLetter"
570
showCHSChangeCase CHSDownCase = showString "downcaseFirstLetter"
553
572
showCHSAPath :: CHSAPath -> ShowS
554
573
showCHSAPath (CHSRoot ide) =
755
774
parseImport pos toks = do
756
775
(qual, modid, toks') <-
758
CHSTokIdent _ ide :toks -> return (False, ide, toks)
759
CHSTokQualif _: CHSTokIdent _ ide:toks -> return (True , ide, toks)
777
CHSTokIdent _ ide :toks ->
778
let (ide', toks') = rebuildModuleId ide toks
779
in return (False, ide', toks')
780
CHSTokQualif _: CHSTokIdent _ ide:toks ->
781
let (ide', toks') = rebuildModuleId ide toks
782
in return (True , ide', toks')
760
783
_ -> syntaxError toks
761
chi <- loadCHI . identToLexeme $ modid
784
chi <- loadCHI . moduleNameToFileName . identToLexeme $ modid
762
785
toks'' <- parseEndHook toks'
763
786
frags <- parseFrags toks''
764
787
return $ CHSHook (CHSImport qual modid chi pos) : frags
789
-- Qualified module names do not get lexed as a single token so we need to
790
-- reconstruct it from a sequence of identifer and dot tokens.
792
rebuildModuleId ide (CHSTokDot _ : CHSTokIdent _ ide' : toks) =
793
let catIdent ide ide' = onlyPosIdent (posOf ide) --FIXME: unpleasent hack
794
(identToLexeme ide ++ '.' : identToLexeme ide')
795
in rebuildModuleId (catIdent ide ide') toks
796
rebuildModuleId ide toks = (ide, toks)
798
moduleNameToFileName :: String -> FilePath
799
moduleNameToFileName = map dotToSlash
800
where dotToSlash '.' = '/'
766
803
parseContext :: Position -> [CHSToken] -> CST s [CHSFrag]
767
804
parseContext pos toks = do
768
805
(olib , toks'' ) <- parseOptLib toks
916
953
CHSTokNewtype _ :toks' -> (True , Nothing , toks' )
917
954
CHSTokArrow _:CHSTokIdent _ ide:toks' -> (False, Just ide, toks' )
918
955
_ -> (False, Nothing , toks'3)
919
toks'5 <- parseEndHook toks'4
920
frags <- parseFrags toks'5
959
CHSTokNocode _ :toks' -> (False, toks' )
960
_ -> (True , toks'4 )
961
toks'6 <- parseEndHook toks'5
962
frags <- parseFrags toks'6
923
(CHSPointer isStar ide (norm ide oalias) ptrType isNewtype oRefType pos)
966
isStar ide (norm ide oalias) ptrType isNewtype oRefType emit pos)
926
969
parsePtrType :: [CHSToken] -> CST s (CHSPtrType, [CHSToken])
974
1017
parseOptPrefix _ toks = return (Nothing, toks)
976
1019
-- first argument is the identifier that is to be used when `^' is given and
1020
-- the second indicates whether the first character has to be upper case
978
1022
parseOptAs :: Ident -> Bool -> [CHSToken] -> CST s (Maybe Ident, [CHSToken])
979
1023
parseOptAs _ _ (CHSTokAs _:CHSTokIdent _ ide:toks) =
1041
1084
parseTrans :: [CHSToken] -> CST s (CHSTrans, [CHSToken])
1042
1085
parseTrans (CHSTokLBrace _:toks) =
1044
(_2Case, toks' ) <- parse_2Case toks
1087
(_2Case, chgCase, toks' ) <- parse_2CaseAndChange toks
1046
(CHSTokRBrace _:toks'') -> return (CHSTrans _2Case [], toks'')
1089
(CHSTokRBrace _:toks'') -> return (CHSTrans _2Case chgCase [], toks'')
1049
1092
-- if there was no `underscoreToCase', we add a comma token to meet
1050
1093
-- the invariant of `parseTranss'
1052
(transs, toks'') <- if _2Case
1095
(transs, toks'') <- if (_2Case || chgCase /= CHSSameCase)
1053
1096
then parseTranss toks'
1054
1097
else parseTranss (CHSTokComma nopos:toks')
1055
return (CHSTrans _2Case transs, toks'')
1098
return (CHSTrans _2Case chgCase transs, toks'')
1057
parse_2Case (CHSTok_2Case _:toks) = return (True, toks)
1058
parse_2Case toks = return (False, toks)
1100
parse_2CaseAndChange (CHSTok_2Case _:CHSTokComma _:CHSTokUpper _:toks) =
1101
return (True, CHSUpCase, toks)
1102
parse_2CaseAndChange (CHSTok_2Case _:CHSTokComma _:CHSTokDown _ :toks) =
1103
return (True, CHSDownCase, toks)
1104
parse_2CaseAndChange (CHSTok_2Case _ :toks) =
1105
return (True, CHSSameCase, toks)
1106
parse_2CaseAndChange (CHSTokUpper _:CHSTokComma _:CHSTok_2Case _:toks) =
1107
return (True, CHSUpCase, toks)
1108
parse_2CaseAndChange (CHSTokUpper _ :toks) =
1109
return (False, CHSUpCase, toks)
1110
parse_2CaseAndChange (CHSTokDown _:CHSTokComma _:CHSTok_2Case _:toks) =
1111
return (True, CHSDownCase, toks)
1112
parse_2CaseAndChange (CHSTokDown _ :toks) =
1113
return (False, CHSDownCase, toks)
1114
parse_2CaseAndChange toks =
1115
return (False, CHSSameCase, toks)
1060
1117
parseTranss (CHSTokRBrace _:toks) = return ([], toks)
1061
1118
parseTranss (CHSTokComma _:toks) = do