0N/ADescription : Mixfix analysis of terms
0N/ACopyright : Christian Maeder and Uni Bremen 2002-2006
2362N/AMaintainer : Christian.Maeder@dfki.de
0N/AStability : experimental
0N/AMixfix analysis of terms
0N/A ( resolveFormula, resolveMixfix, MixResolve
0N/A , resolveMixTrm, resolveMixFrm
0N/A , IdSets, mkIdSets, emptyIdSets, unite, single
0N/A , makeRules, Mix(..), emptyMix
0N/A , ids_BASIC_SPEC, ids_SIG_ITEMS, ids_OP_ITEM, ids_PRED_ITEM)
0N/Adata Mix b s f e = MixRecord
0N/A { getBaseIds :: b -> IdSets -- ^ ids of extra basic items
0N/A , getSigIds :: s -> IdSets -- ^ ids of extra sig items
0N/A , getExtIds :: e -> IdSets -- ^ ids of signature extensions
0N/A , mixRules :: (Token -> [Rule], Rules) -- ^ rules for Earley
0N/A , putParen :: f -> f -- ^ parenthesize extended formula
0N/A , mixResolve :: MixResolve f -- ^ resolve extended formula
0N/A , checkMix :: (f -> Bool) -- ^ post check extended formula
0N/A , putInj :: f -> f -- ^ insert injections in extended formula
0N/A-- | an initially empty record
0N/AemptyMix :: Mix b s f e
0N/A { getBaseIds = const emptyIdSets
0N/A , getSigIds = const emptyIdSets
0N/A , getExtIds = const emptyIdSets
0N/A , mixRules = error "emptyMix"
0N/A , mixResolve = const $ const return
0N/A , checkMix = const True
0N/A-- precompute non-simple op and pred identifier for mixfix rules
0N/A-- | the precomputed sets of op and pred (non-simple) identifiers
0N/A-- | the empty 'IdSets'
0N/AemptyIdSets :: IdSets
0N/Aunite :: [IdSets] -> IdSets
0N/A-- | get all ids of a basic spec
0N/Aids_BASIC_SPEC :: (b -> IdSets) -> (s -> IdSets) -> BASIC_SPEC b s f -> IdSets
0N/Aids_BASIC_SPEC f g (Basic_spec al) =
0N/A unite $ map (ids_BASIC_ITEMS f g . item) al
0N/Aids_BASIC_ITEMS :: (b -> IdSets) -> (s -> IdSets)
0N/A -> BASIC_ITEMS b s f -> IdSets
0N/Aids_BASIC_ITEMS f g bi = case bi of
0N/A Sig_items sis -> ids_SIG_ITEMS g sis
0N/A Free_datatype al _ -> ids_anDATATYPE_DECLs al
0N/A Sort_gen al _ -> unite $ map (ids_SIG_ITEMS g . item) al
0N/A Ext_BASIC_ITEMS b -> f b
0N/Aids_anDATATYPE_DECLs :: [Annoted DATATYPE_DECL] -> IdSets
0N/Aids_anDATATYPE_DECLs al =
0N/A-- | get all ids of a sig items
0N/Aids_SIG_ITEMS :: (s -> IdSets) -> SIG_ITEMS s f -> IdSets
0N/Aids_SIG_ITEMS f si = case si of
0N/A Sort_items _ _ _ -> emptyIdSets
0N/A Datatype_items al _ -> ids_anDATATYPE_DECLs al
0N/A Ext_SIG_ITEMS s -> f s
0N/A-- | get all op ids of an op item
0N/Aids_OP_ITEM o = case o of
0N/A Op_defn i _ _ _ -> single i
0N/A-- | same as singleton but empty for a simple id
0N/A-- | get all pred ids of a pred item
0N/Aids_PRED_ITEM p = case p of
0N/A Pred_defn i _ _ _ -> single i
0N/Aids_DATATYPE_DECL (Datatype_decl _ al _) =
0N/Aids_ALTERNATIVE a = case a of
0N/A Alt_construct _ i cs _ ->
Set.unions $ single i : map ids_COMPONENTS cs
0N/Aids_COMPONENTS c = case c of
0N/A-- predicates get lower precedence
0N/AmkSingleArgRule :: Int -> Id -> Rule
0N/AmkSingleArgRule b ide = (protect ide, b, getPlainTokenList ide ++ [varTok])
0N/AmkArgsRule :: Int -> Id -> Rule
0N/AmkArgsRule b ide = (protect ide, b, getPlainTokenList ide
0N/A ++ getTokenPlaceList tupleId)
0N/AsingleArgId = mkId [exprTok, varTok]
0N/AmultiArgsId = mkId (exprTok : getPlainTokenList tupleId)
0N/A-- | additional scan rules
0N/AaddRule :: GlobalAnnos -> [Rule] -> IdSets -> Token -> [Rule]
0N/AaddRule ga uRules (ops, preds) tok =
0N/A [mixRule p i, mkSingleArgRule p i, mkArgsRule p i])
0N/A [varR, mkRule singleArgId, mkRule multiArgsId]
0N/A $ addR 0 (addR 1 lm ops) preds
0N/A in (if isSimpleToken tok &&
in not (mem ops || mem preds)
then let i = mkId [tok] in
[mkRule i, mkSingleArgRule 1 i, mkArgsRule 1 i]
-- insert only identifiers starting with a place
initRules :: IdSets -> Rules
let addR p =
Set.fold ( \ i l -> mixRule p i : l)
in (addR 1 (addR 0 [mkRule typeId] predS) opS, [])
-- | construct rules from 'IdSets' to be put into a 'Mix' record
makeRules :: GlobalAnnos -> IdSets -> (Token -> [Rule], Rules)
makeRules ga (opS, predS) = let
mkSingleArgRule p i : mkArgsRule p i : l)
uRules = addR 0 (addR 1 [] cOps) cPreds
in (addRule ga uRules (sOps, sPreds), initRules (cOps, cPreds))
-- | meaningful position of a term
posOfTerm :: TERM f -> Range
Qual_var v _ ps -> if isNullRange ps then tokPos v else ps
Mixfix_token t -> tokPos t
Mixfix_term ts -> concatMapRange posOfTerm ts
Mixfix_qual_pred p -> case p of
Qual_pred_name i _ _ -> posOfId i
Application o _ ps -> if isNullRange ps then
Qual_op_name i _ _ -> posOfId i) else ps
Conditional t1 _ t2 ps ->
if isNullRange ps then concatMapRange posOfTerm [t1, t2] else ps
Mixfix_parenthesized ts ps ->
if isNullRange ps then concatMapRange posOfTerm ts else ps
Mixfix_bracketed ts ps ->
if isNullRange ps then concatMapRange posOfTerm ts else ps
if isNullRange ps then concatMapRange posOfTerm ts else ps
-- | construct application
asAppl :: Id -> [TERM f] -> Range -> TERM f
asAppl f args ps = Application (Op_name f) args
$ if isNullRange ps then posOfId f else ps
-- | constructing the parse tree from (the final) parser state(s)
toAppl :: Id -> [TERM f] -> Range -> TERM f
if ide == singleArgId || ide == multiArgsId
then assert (length ar > 1) $
Application q ts p -> assert (null ts) $
Application q tar $ appRange ps p
Mixfix_term [har, Mixfix_parenthesized tar ps]
addType :: TERM f -> TERM f -> TERM f
Mixfix_sorted_term s ps -> Sorted_term t s ps
Mixfix_cast s ps -> Cast t s ps
-- | the type for mixfix resolution
type MixResolve f = GlobalAnnos -> (Token -> [Rule], Rules) -> f -> Result f
iterateCharts :: Pretty f => (f -> f)
-> MixResolve f -> GlobalAnnos -> [TERM f]
-> Chart (TERM f) -> Chart (TERM f)
iterateCharts par extR g terms c =
let self = iterateCharts par extR g
expand = expandPos Mixfix_token
oneStep = nextChart addType toAppl g c
resolveTerm = resolveMixTrm par extR g (adder, ruleS)
Mixfix_term ts -> self (ts ++ tail terms) c
Mixfix_bracketed ts ps ->
self (expand ("[", "]") ts ps ++ tail terms) c
self (expand ("{", "}") ts ps ++ tail terms) c
Mixfix_parenthesized ts ps ->
[h] -> let Result mds v = resolveTerm h
c2 = self (tail terms) (oneStep (tNew, varTok))
_ -> self (expand ("(", ")") ts ps ++ tail terms) c
h@(Conditional t1 f2 t3 ps) ->
f5 <- resolveMixFrm par extR g (adder, ruleS) f2
return (Conditional t4 f5 t6 ps)
(oneStep (tNew, varTok {tokPos = posOfTerm tNew}))
Mixfix_token t -> let (ds1, trm) = convertMixfixToken
(literal_annos g) asAppl Mixfix_token t
c2 = self (tail terms) $ oneStep $
Mixfix_token tok -> (trm, tok)
t@(Mixfix_sorted_term _ ps) -> self (tail terms)
(oneStep (t, typeTok {tokPos = ps}))
t@(Mixfix_cast _ ps) -> self (tail terms)
(oneStep (t, typeTok {tokPos = ps}))
t@(Qual_var _ _ ps) -> self (tail terms)
(oneStep (t, varTok {tokPos = ps}))
t@(Application (Qual_op_name _ _ ps) _ _) ->
self (tail terms) (oneStep (t, exprTok{tokPos = ps} ))
t@(Mixfix_qual_pred (Qual_pred_name _ _ ps)) ->
self (tail terms) (oneStep (t, exprTok{tokPos = ps} ))
let Result mds v = resolveTerm t
tNew = Sorted_term (case v of
c2 = self (tail terms) (oneStep (tNew, varTok))
_ -> error "iterateCharts"
-- | construct 'IdSets' from op and pred identifiers
-- | top-level resolution like 'resolveMixTrm' that fails in case of diags
resolveMixfix :: Pretty f => (f -> f)
-> MixResolve f -> MixResolve (TERM f)
resolveMixfix par extR g ruleS t =
let r@(Result ds _) = resolveMixTrm par extR g ruleS t
in if null ds then r else Result ds Nothing
-- | basic term resolution that supports recursion without failure
resolveMixTrm :: Pretty f => (f -> f)
-> MixResolve f -> MixResolve (TERM f)
resolveMixTrm par extR ga (adder, ruleS) trm =
getResolved (showTerm par ga) (posOfTerm trm) toAppl
$ iterateCharts par extR ga [trm] $ initChart adder ruleS
showTerm :: Pretty f => (f -> f) -> GlobalAnnos -> TERM f -> ShowS
showTerm par ga = showGlobalDoc ga . mapTerm par
-- | top-level resolution like 'resolveMixFrm' that fails in case of diags
resolveFormula :: Pretty f => (f -> f)
-> MixResolve f -> MixResolve (FORMULA f)
resolveFormula par extR g ruleS f =
let r@(Result ds _) = resolveMixFrm par extR g ruleS f
in if null ds then r else Result ds Nothing
-- | basic formula resolution that supports recursion without failure
resolveMixFrm :: Pretty f => (f -> f)
-> MixResolve f -> MixResolve (FORMULA f)
resolveMixFrm par extR g ids frm =
let self = resolveMixFrm par extR g ids
resolveTerm = resolveMixTrm par extR g ids in
Quantification q vs fOld ps ->
do fNew <- resolveMixFrm par extR g ids fOld
return $ Quantification q vs fNew ps
do fsNew <- mapM self fsOld
return $ Conjunction fsNew ps
do fsNew <- mapM self fsOld
return $ Disjunction fsNew ps
Implication f1 f2 b ps ->
return $ Implication f3 f4 b ps
return $ Equivalence f3 f4 ps
return $ Negation fNew ps
Predication sym tsOld ps ->
do tsNew <- mapM resolveTerm tsOld
return $ Predication sym tsNew ps
do tNew <- resolveTerm tOld
return $ Definedness tNew ps
Existl_equation t1 t2 ps ->
return $ Existl_equation t3 t4 ps
Strong_equation t1 t2 ps ->
return $ Strong_equation t3 t4 ps
do tNew <- resolveTerm tOld
return $ Membership tNew s ps
do tNew <- resolveTerm tOld
Application (Op_name ide) args ps ->
return $ Predication (Pred_name ide) args ps
return $ Predication qide [] nullRange
Mixfix_term [Mixfix_qual_pred qide,
Mixfix_parenthesized ts ps] ->
return $ Predication qide ts ps
("not a formula: " ++ showTerm par g tNew "")