Earley.hs revision 71de4b92b1ca12890a9e7bc5b0301455da3e052f
e071fb22ea9923a2a4ff41184d80ca46b55ee932Till MossakowskiModule : $Header$
e85b224577b78d08ba5c39fe9dcc2e53995454a2Christian MaederCopyright : Christian Maeder and Uni Bremen 2003
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian MaederLicence : similar to LGPL, see HetCATS/LICENCE.txt or LIZENZ.txt
b4fbc96e05117839ca409f5f20f97b3ac872d1edTill MossakowskiMaintainer : hets@tzi.de
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus RoggenbachStability : experimental
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus RoggenbachPortability : portable
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett generic mixfix analysis
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach -- * special tokens for special ids
90047eafd2de482c67bcd13103c6064e9b0cb254Andy Gimblett , varTok, exprTok, typeTok
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett , applId, parenId, typeId, exprId, varId
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett , tupleId, unitId, unknownId, isUnknownId, unToken
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett , Knowns, protect, listRules, mixRule
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett , getTokenPlaceList
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett , endPlace, begPlace
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach -- * resolution chart
1538a6e8d77301d6de757616ffc69ee61f1482e4Andy Gimblett , Chart, mixDiags, ToExpr
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach , initChart, nextChart, getResolved)
04ceed96d1528b939f2e592d0656290d81d1c045Andy Gimblettimport qualified Common.Lib.Set as Set
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblettimport qualified Common.Lib.Map as Map
c4b2418421546a337f83332fe0db04742dcd735dAndy Gimblett-- | reconstruct the token list of an 'Id'.
41486a487c9b065d4d9d1a8adf63c00925cd455bAndy Gimblett-- Replace top-level places with the input String
41486a487c9b065d4d9d1a8adf63c00925cd455bAndy GimblettgetTokenList :: String -> Id -> [Token]
e771539425f4a0abef9f94cf4b63690f3603f682Andy GimblettgetTokenList placeStr (Id ts cs ps) =
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett let convert = map (\ t -> if isPlace t then t {tokStr = placeStr} else t)
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett in if null cs then convert ts else
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett let (toks, pls) = splitMixToken ts in
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett convert toks ++ getCompoundTokenList cs ps ++ convert pls
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett-- | update token positions.
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett-- return remaining positions
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy GimblettsetToksPos :: [Token] -> [Pos] -> ([Token], [Pos])
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy GimblettsetToksPos (h:ts) (p:ps) =
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett let (rt, rp) = setToksPos ts ps
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett in (h {tokPos = p} : rt, rp)
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettsetToksPos ts ps = (ts, ps)
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett-- | update positions in 'Id'.
41486a487c9b065d4d9d1a8adf63c00925cd455bAndy Gimblett-- return remaining positions
e771539425f4a0abef9f94cf4b63690f3603f682Andy GimblettsetPlainIdePos :: Id -> [Pos] -> (Id, [Pos])
e771539425f4a0abef9f94cf4b63690f3603f682Andy GimblettsetPlainIdePos (Id ts cs _) ps =
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett if null cs then
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett let (newTs, restPs) = setToksPos ts ps
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett in (Id newTs cs [], restPs)
61051521e4d82769a47f23aecb5fb477de47d534Andy Gimblett else let (toks, pls) = splitMixToken ts
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett ttail l = if null l then l else tail l
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett (front, ps2) = setToksPos toks ps
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett (newCs, ps3, ps4) = foldl ( \ (prevCs, seps, restPs) a ->
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett let (c1, qs) = setPlainIdePos a restPs
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett in (c1: prevCs, head qs : seps, ttail qs))
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblett ([], [head ps2], ttail ps2) cs
eeaf0a8a1dc535d105904a2190f26c0835ecf429Andy Gimblett (newPls, ps7) = setToksPos pls ps4
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett in (Id (front ++ newPls) (reverse newCs) (reverse ps3), ps7)
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett-- | a special index type for more type safety
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblettnewtype Index = Index Int deriving (Eq, Ord, Show)
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett-- deriving Num is also possible
e771539425f4a0abef9f94cf4b63690f3603f682Andy Gimblett-- but the following functions are sufficient
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett-- | the initial index
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettstartIndex :: Index
820947bd01ca952c3909eaa0366c6914c87cc1cbTill MossakowskistartIndex = Index 0
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimblettincrIndex :: Index -> Index
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimblettincrIndex (Index i) = Index (i + 1)
90047eafd2de482c67bcd13103c6064e9b0cb254Andy Gimblettdata Item a = Item
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett { rule :: Id -- the rule to match
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy Gimblett , info :: Int -- additional precedence info for 'rule'
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , lWeight :: Id -- weights for lower precedence pre- and postfixes
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , rWeight :: Id -- given by the 'Id's itself
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett , posList :: [Pos] -- positions of Id tokens
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , args :: [a] -- currently collected arguments
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett -- both in reverse order
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , ambigArgs :: [[a]] -- field for ambiguities
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , ambigs :: [[a]] -- field for ambiguities
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , rest :: [Token] -- part of the rule after the "dot"
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett , index :: Index -- index into the Table/input string
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblettinstance Show (Item a) where
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett showsPrec _ p =
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett let d = rest p
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett v = getPlainTokenList (rule p)
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett first = take (length v - length d) v
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett showToks = showSepList id showTok
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett Index i = index p
a79fe3aad8743ea57e473ea5f66a723244cb9c0eMarkus Roggenbach in showChar '['. showToks first
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett . showChar '.'
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett . showString ", "
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett . shows i . showChar ']'
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett-- | the non-terminal
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimbletttermStr :: String
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimbletttermStr = "(__)"
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett-- | builtin terminals
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy GimblettcommaTok, termTok, oParenTok, cParenTok, placeTok :: Token
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettcommaTok = mkSimpleId "," -- for list elements
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimbletttermTok = mkSimpleId termStr
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimblettplaceTok = mkSimpleId place
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettoParenTok = mkSimpleId "("
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettcParenTok = mkSimpleId ")"
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettlistTok :: Token
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettlistTok = mkSimpleId "[]" -- impossible token
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettprotectTok :: Token
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettprotectTok = mkSimpleId "()" -- impossible token
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett-- | token for type annotations
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimbletttypeTok :: Token
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimbletttypeTok = mkSimpleId ":"
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett-- | token for a fixed (or recursively resolved) operator expression
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettexprTok :: Token
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimblettexprTok = mkSimpleId "(op )"
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett-- | token for a fixed (or recursively resolved) argument expression
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimblettvarTok :: Token
d326dac41dadbe2b84bb7021cbfd91f4dd4a19bcAndy GimblettvarTok = mkSimpleId "(var )"
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett-- | token for an unknown variable (within patterns)
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettunknownTok :: Token
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimblettunknownTok = mkSimpleId "(?)"
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett-- | the invisible application rule with two places
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettapplId = mkId [placeTok, placeTok]
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett-- | parenthesis around one place
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettparenId = mkId [oParenTok, placeTok, cParenTok]
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett-- | id for tuples with at least two arguments
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimbletttupleId = mkId [oParenTok, placeTok, commaTok, placeTok, cParenTok]
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett-- | id for the emtpy tuple
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettunitId = mkId [oParenTok, cParenTok]
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy Gimblett-- | see 'typeTok'
d297a45fc73aa6c4a1f9d073c3170611415f324bAndy GimbletttypeId = mkId [placeTok, typeTok]
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett-- | see 'exprTok'
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy GimblettexprId = mkId [exprTok]
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblett-- | see 'varTok'
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy GimblettvarId = mkId [varTok]
e95030058b77cb83593c85aa4c506caf154f63b7Andy Gimblett-- | see 'unknownTok'
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunknownId :: Id
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunknownId = mkId [unknownTok]
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettlistId :: (Id, Id) -> Id
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettlistId (f,c) = Id [listTok] [f,c] []
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy GimblettisListId :: Id -> Bool
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy GimblettisListId (Id ts cs _) = not (null ts) && head ts == listTok
7caf9f99d426a25d56eb7473fea1f55ce4460762Andy Gimblett && assert (length cs == 2) True
8528886a04f14abe0ddf80f50c853cc25bc821cdAndy Gimblett-- | interpret placeholders as literal places
8528886a04f14abe0ddf80f50c853cc25bc821cdAndy Gimblettprotect :: Id -> Id
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy Gimblettprotect i = Id [protectTok] [i] []
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunProtect :: Id -> Id
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunProtect (Id _ [i] _) = i
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunProtect _ = error "unProtect"
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettisProtected :: Id -> Bool
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettisProtected (Id ts cs _) = not (null ts) && head ts == protectTok
e95030058b77cb83593c85aa4c506caf154f63b7Andy Gimblett && isSingle cs
e95030058b77cb83593c85aa4c506caf154f63b7Andy Gimblett-- | test if an 'unknownId' was matched
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettisUnknownId :: Id -> Bool
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettisUnknownId (Id ts _ _) = not (null ts) && head ts == unknownTok
e95030058b77cb83593c85aa4c506caf154f63b7Andy Gimblett-- | get unknown token from an 'unknownId'
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunToken :: Id -> Token
e95030058b77cb83593c85aa4c506caf154f63b7Andy GimblettunToken (Id [_,t] _ _) = t
e8c03c10d7987b223a9f6bfd5c0c54da21da5b86Andy GimblettunToken _ = error "unToken"
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimbletttype Rule = (Id, Int, [Token])
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettmkItem :: Index -> Rule -> Item a
06dd4e7c29f33f6122a910719e3bd9062256e397Andy GimblettmkItem ind (ide, inf, toks) =
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblett Item { rule = ide
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett , lWeight = ide
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett , rWeight = ide
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett , posList = []
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett , ambigArgs = []
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett , ambigs = []
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett , rest = toks
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett , index = ind }
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett-- | extract tokens with the non-terminal for places
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettgetTokenPlaceList :: Id -> [Token]
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettgetTokenPlaceList = getTokenList termStr
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett-- | construct a rule for a mixfix
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettmixRule :: b -> Id -> (Id, b, [Token])
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettmixRule b i = (i, b, getTokenPlaceList i)
06dd4e7c29f33f6122a910719e3bd9062256e397Andy GimblettasListAppl :: ToExpr a -> Id -> [a] -> [Pos] -> a
a731366827a80af216ce6bfd4aa6388260577791Andy GimblettasListAppl toExpr i ra br =
f5c948fd73698a64837609e1b60350126268beddAndy Gimblett if isListId i then
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett let Id _ [f, c] _ = i
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett mkList [] ps = toExpr c [] ps
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett mkList (hd:tl) ps = toExpr f [hd, mkList tl ps] ps
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett in mkList ra br
f5c948fd73698a64837609e1b60350126268beddAndy Gimblett else if i == typeId
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett || i == exprId
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett || i == parenId
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett || i == varId
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett then assert (isSingle ra) $ head ra
f5c948fd73698a64837609e1b60350126268beddAndy Gimblett else toExpr i ra br
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett-- | construct the list rules
06dd4e7c29f33f6122a910719e3bd9062256e397Andy GimblettlistRules :: b -> GlobalAnnos -> [(Id, b, [Token])]
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettlistRules inf g =
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett let lists = list_lit $ literal_annos g
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett listRule co toks = (listId co, inf, toks)
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett in concatMap ( \ (bs, (n, c)) ->
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett let (b1, b2, cs) = getListBrackets bs
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett e = Id (b1 ++ b2) cs [] in
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett (if e == n then [] -- add b1 ++ b2 if its not yet included by n
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett else [listRule (c, n) $ getPlainTokenList e])
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett ++ [listRule (c, n) (b1 ++ [termTok] ++ b2),
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett listRule (c, n) (b1 ++ [termTok, commaTok, termTok] ++ b2)]
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimbletttype Table a = Map.Map Index [Item a]
06dd4e7c29f33f6122a910719e3bd9062256e397Andy GimblettlookUp :: Table a -> Index -> [Item a]
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettlookUp ce k = Map.findWithDefault [] k ce
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett-- | a set of strings that do not match a 'unknownTok'
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimbletttype Knowns = Set.Set String
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett-- | recognize next token (possible introduce new tuple variable)
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettscanItem :: (a -> a -> a) -> Knowns -> (a, Token) -> Item a
06dd4e7c29f33f6122a910719e3bd9062256e397Andy GimblettscanItem addType ks (trm, t) p =
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett let ts = rest p
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett q = p { posList = tokPos t : posList p }
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett in if null ts then [] else
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett let tt = tail ts
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett r = q { rest = tt }
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett if head ts == t then
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett if t == commaTok then
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett assert (not $ null tt) $
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett if head tt == termTok then
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett -- tuple or list elements separator
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett [ r, q { rest = termTok : ts } ]
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett else if t == exprTok || t == varTok then
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett [r { args = trm : args p }]
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett else if t == typeTok then
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett assert (null tt && isSingle as) $
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett [q { rest = [], args = [addType trm $ head as] }]
784f137bcf1ab23b3b87d5506e586e59c383ba96Andy Gimblett else if Set.isEmpty ks then []
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett else if isUnknownId ide
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett && not (tokStr t `Set.member` ks) then
06dd4e7c29f33f6122a910719e3bd9062256e397Andy Gimblett [r { rule = mkId [unknownTok, t]}]
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblettscan :: (a -> a -> a) -> Knowns -> (a, Token) -> [Item a]
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblettscan f ks term = concatMap (scanItem f ks term)
06dd4e7c29f33f6122a910719e3bd9062256e397Andy GimblettmkAmbigs :: ToExpr a -> Item a -> [a]
784f137bcf1ab23b3b87d5506e586e59c383ba96Andy GimblettmkAmbigs toExpr p =
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett let l = args p in
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett map ( \ as -> fst $
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett mkExpr toExpr
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett p { args = take (length l - length as) l ++ as
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett } ) $ ambigArgs p
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettaddArg :: GlobalAnnos -> ToExpr a -> Item a -> Item a -> Item a
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettaddArg ga toExpr argItem p =
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett let (arg, q) = mkExpr toExpr argItem
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett ams = ambigs argItem
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett newAms = mkAmbigs toExpr argItem
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett in assert (not $ null $ rest p) $
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett p { rest = tail $ rest p
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett , lWeight = getLWeight ga argItem p
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblett , rWeight = getRWeight ga argItem p
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett , posList = q : posList p
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett , args = arg : args p
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett , ambigs = (if null newAms then ams else newAms : ams)
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett ++ ambigs p }
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettgetLWeight :: GlobalAnnos -> Item a -> Item a -> Id
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy GimblettgetLWeight ga argItem opItem =
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett let op = rule opItem
a09bfcbcb0fba5663fca1968aa82daebf2e092c4Andy Gimblett arg = lWeight argItem
d9e78002fb0bf01a9b72d3d3415fdf9790bdfee8Andy Gimblett num = length $ args opItem in
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett if isLeftArg op num then
fbc0c2baf563fe5b664f0152674a8d3acecca58cAndy Gimblett if begPlace arg then
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett case precRel (prec_annos ga) op arg of
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett Higher -> arg
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett else lWeight opItem
a731366827a80af216ce6bfd4aa6388260577791Andy GimblettgetRWeight :: GlobalAnnos -> Item a -> Item a -> Id
a731366827a80af216ce6bfd4aa6388260577791Andy GimblettgetRWeight ga argItem opItem =
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett let op = rule opItem
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett arg = rWeight argItem
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett num = length $ args opItem in
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett if isRightArg op num then
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett if endPlace arg then
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett case precRel (prec_annos ga) op arg of
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett Higher -> arg
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett else rWeight opItem
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett-- | shortcut for a function that constructs an expression
a731366827a80af216ce6bfd4aa6388260577791Andy Gimbletttype ToExpr a = Id -> [a] -> [Pos] -> a
31f039ffdb33d78cb31d24b71d3155b11a323975Andy GimblettmkExpr :: ToExpr a -> Item a -> (a, Pos)
a731366827a80af216ce6bfd4aa6388260577791Andy GimblettmkExpr toExpr itm =
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett let orig = rule itm
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett ps = posList itm
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett rs = reverse ps
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett (ide, qs) = if isListId orig then (orig, rs) else
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett if isProtected orig then
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett setPlainIdePos (unProtect orig) rs
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett else setPlainIdePos orig rs
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett as = reverse $ args itm
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett in (asListAppl toExpr ide as qs,
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett if null ps then nullPos else head ps)
a731366827a80af216ce6bfd4aa6388260577791Andy Gimbletttype Filt = Int -> Int -> Maybe Bool
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblettreduce :: GlobalAnnos -> Table a -> [Id] -> Filt
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett -> ToExpr a -> Item a -> [Item a]
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblettreduce ga table rs filt toExpr itm =
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett map (addArg ga toExpr itm)
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett $ filter ( \ oi -> let ts = rest oi in
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett if null ts then False
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett else if head ts == termTok
a731366827a80af216ce6bfd4aa6388260577791Andy Gimblett then checkPrecs filt ga rs itm oi
31f039ffdb33d78cb31d24b71d3155b11a323975Andy Gimblett $ lookUp table $ index itm
nextTable = Map.insert idx items table
Chart { prevTable = Map.empty