1 -----------------------------------------------------------------------------
3 -- Module : Text.ParserCombinators.Parsec.Error
4 -- Copyright : (c) Daan Leijen 1999-2001
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : daan@cs.uu.nl
8 -- Stability : provisional
9 -- Portability : portable
13 -----------------------------------------------------------------------------
15 module Text.ParserCombinators.Parsec.Error
16 ( Message(SysUnExpect,UnExpect,Expect,Message)
17 , messageString, messageCompare, messageEq
19 , ParseError, errorPos, errorMessages, errorIsUnknown
22 , newErrorMessage, newErrorUnknown
23 , addErrorMessage, setErrorPos, setErrorMessage
29 import Data.List (nub,sortBy)
30 import Text.ParserCombinators.Parsec.Pos
32 -----------------------------------------------------------
34 -----------------------------------------------------------
35 data Message = SysUnExpect !String --library generated unexpect
36 | UnExpect !String --unexpected something
37 | Expect !String --expecting something
38 | Message !String --raw message
41 = case msg of SysUnExpect _ -> 0
46 messageCompare msg1 msg2
47 = compare (messageToEnum msg1) (messageToEnum msg2)
50 = case msg of SysUnExpect s -> s
56 = (messageCompare msg1 msg2 == EQ)
59 -----------------------------------------------------------
61 -----------------------------------------------------------
62 data ParseError = ParseError !SourcePos [Message]
64 errorPos :: ParseError -> SourcePos
65 errorPos (ParseError pos msgs)
68 errorMessages :: ParseError -> [Message]
69 errorMessages (ParseError pos msgs)
70 = sortBy messageCompare msgs
72 errorIsUnknown :: ParseError -> Bool
73 errorIsUnknown (ParseError pos msgs)
77 -----------------------------------------------------------
78 -- Create parse errors
79 -----------------------------------------------------------
83 newErrorMessage msg pos
84 = ParseError pos [msg]
86 addErrorMessage msg (ParseError pos msgs)
87 = ParseError pos (msg:msgs)
89 setErrorPos pos (ParseError _ msgs)
92 setErrorMessage msg (ParseError pos msgs)
93 = ParseError pos (msg:filter (not . messageEq msg) msgs)
96 mergeError :: ParseError -> ParseError -> ParseError
97 mergeError (ParseError pos msgs1) (ParseError _ msgs2)
98 = ParseError pos (msgs1 ++ msgs2)
102 -----------------------------------------------------------
104 -----------------------------------------------------------
105 instance Show ParseError where
107 = show (errorPos err) ++ ":" ++
108 showErrorMessages "or" "unknown parse error"
109 "expecting" "unexpected" "end of input"
113 -- Language independent show function
114 showErrorMessages msgOr msgUnknown msgExpecting msgUnExpected msgEndOfInput msgs
115 | null msgs = msgUnknown
116 | otherwise = concat $ map ("\n"++) $ clean $
117 [showSysUnExpect,showUnExpect,showExpect,showMessages]
119 (sysUnExpect,msgs1) = span (messageEq (SysUnExpect "")) msgs
120 (unExpect,msgs2) = span (messageEq (UnExpect "")) msgs1
121 (expect,messages) = span (messageEq (Expect "")) msgs2
123 showExpect = showMany msgExpecting expect
124 showUnExpect = showMany msgUnExpected unExpect
125 showSysUnExpect | not (null unExpect) ||
126 null sysUnExpect = ""
127 | null firstMsg = msgUnExpected ++ " " ++ msgEndOfInput
128 | otherwise = msgUnExpected ++ " " ++ firstMsg
130 firstMsg = messageString (head sysUnExpect)
132 showMessages = showMany "" messages
136 showMany pre msgs = case (clean (map messageString msgs)) of
138 ms | null pre -> commasOr ms
139 | otherwise -> pre ++ " " ++ commasOr ms
143 commasOr ms = commaSep (init ms) ++ " " ++ msgOr ++ " " ++ last ms
145 commaSep = seperate ", " . clean
146 semiSep = seperate "; " . clean
150 seperate sep (m:ms) = m ++ sep ++ seperate sep ms
152 clean = nub . filter (not.null)