1module Language.PureScript.CST.Errors
2  ( ParserErrorInfo(..)
3  , ParserErrorType(..)
4  , ParserWarningType(..)
5  , ParserError
6  , ParserWarning
7  , prettyPrintError
8  , prettyPrintErrorMessage
9  , prettyPrintWarningMessage
10  ) where
11
12import Prelude
13
14import qualified Data.Text as Text
15import Data.Char (isSpace, toUpper)
16import Language.PureScript.CST.Layout
17import Language.PureScript.CST.Print
18import Language.PureScript.CST.Types
19import Text.Printf (printf)
20
21data ParserErrorType
22  = ErrWildcardInType
23  | ErrConstraintInKind
24  | ErrHoleInType
25  | ErrExprInBinder
26  | ErrExprInDeclOrBinder
27  | ErrExprInDecl
28  | ErrBinderInDecl
29  | ErrRecordUpdateInCtr
30  | ErrRecordPunInUpdate
31  | ErrRecordCtrInUpdate
32  | ErrTypeInConstraint
33  | ErrElseInDecl
34  | ErrInstanceNameMismatch
35  | ErrUnknownFundep
36  | ErrImportInDecl
37  | ErrGuardInLetBinder
38  | ErrKeywordVar
39  | ErrKeywordSymbol
40  | ErrQuotedPun
41  | ErrToken
42  | ErrLineFeedInString
43  | ErrAstralCodePointInChar
44  | ErrCharEscape
45  | ErrNumberOutOfRange
46  | ErrLeadingZero
47  | ErrExpectedFraction
48  | ErrExpectedExponent
49  | ErrExpectedHex
50  | ErrReservedSymbol
51  | ErrCharInGap Char
52  | ErrModuleName
53  | ErrQualifiedName
54  | ErrEmptyDo
55  | ErrLexeme (Maybe String) [String]
56  | ErrEof
57  | ErrCustom String
58  deriving (Show, Eq, Ord)
59
60data ParserWarningType
61  = WarnDeprecatedRowSyntax
62  | WarnDeprecatedForeignKindSyntax
63  | WarnDeprecatedConstraintInForeignImportSyntax
64  | WarnDeprecatedKindImportSyntax
65  | WarnDeprecatedKindExportSyntax
66  deriving (Show, Eq, Ord)
67
68data ParserErrorInfo a = ParserErrorInfo
69  { errRange :: SourceRange
70  , errToks :: [SourceToken]
71  , errStack :: LayoutStack
72  , errType :: a
73  } deriving (Show, Eq)
74
75type ParserError = ParserErrorInfo ParserErrorType
76type ParserWarning = ParserErrorInfo ParserWarningType
77
78prettyPrintError :: ParserError -> String
79prettyPrintError pe@ParserErrorInfo { errRange } =
80  prettyPrintErrorMessage pe <> " at " <> errPos
81  where
82  errPos = case errRange of
83    SourceRange (SourcePos line col) _ ->
84      "line " <> show line <> ", column " <> show col
85
86prettyPrintErrorMessage :: ParserError -> String
87prettyPrintErrorMessage ParserErrorInfo {..} = case errType of
88  ErrWildcardInType ->
89    "Unexpected wildcard in type; type wildcards are only allowed in value annotations"
90  ErrConstraintInKind ->
91    "Unsupported constraint in kind; constraints are only allowed in value annotations"
92  ErrHoleInType ->
93    "Unexpected hole in type; type holes are only allowed in value annotations"
94  ErrExprInBinder ->
95    "Expected pattern, saw expression"
96  ErrExprInDeclOrBinder ->
97    "Expected declaration or pattern, saw expression"
98  ErrExprInDecl ->
99    "Expected declaration, saw expression"
100  ErrBinderInDecl ->
101    "Expected declaration, saw pattern"
102  ErrRecordUpdateInCtr ->
103    "Expected ':', saw '='"
104  ErrRecordPunInUpdate ->
105    "Expected record update, saw pun"
106  ErrRecordCtrInUpdate ->
107    "Expected '=', saw ':'"
108  ErrTypeInConstraint ->
109    "Expected constraint, saw type"
110  ErrElseInDecl ->
111    "Expected declaration, saw 'else'"
112  ErrInstanceNameMismatch ->
113    "All instances in a chain must implement the same type class"
114  ErrUnknownFundep ->
115    "Unknown type variable in functional dependency"
116  ErrImportInDecl ->
117    "Expected declaration, saw 'import'"
118  ErrGuardInLetBinder ->
119    "Unexpected guard in let pattern"
120  ErrKeywordVar ->
121    "Expected variable, saw keyword"
122  ErrKeywordSymbol ->
123    "Expected symbol, saw reserved symbol"
124  ErrQuotedPun ->
125    "Unexpected quoted label in record pun, perhaps due to a missing ':'"
126  ErrEof ->
127    "Unexpected end of input"
128  ErrLexeme (Just (hd : _)) _ | isSpace hd ->
129    "Illegal whitespace character " <> displayCodePoint hd
130  ErrLexeme (Just a) _ ->
131    "Unexpected " <> a
132  ErrLineFeedInString ->
133    "Unexpected line feed in string literal"
134  ErrAstralCodePointInChar ->
135    "Illegal astral code point in character literal"
136  ErrCharEscape ->
137    "Illegal character escape code"
138  ErrNumberOutOfRange ->
139    "Number literal is out of range"
140  ErrLeadingZero ->
141    "Unexpected leading zeros"
142  ErrExpectedFraction ->
143    "Expected fraction"
144  ErrExpectedExponent ->
145    "Expected exponent"
146  ErrExpectedHex ->
147    "Expected hex digit"
148  ErrReservedSymbol ->
149    "Unexpected reserved symbol"
150  ErrCharInGap ch ->
151    "Unexpected character '" <> [ch] <> "' in gap"
152  ErrModuleName ->
153    "Invalid module name; underscores and primes are not allowed in module names"
154  ErrQualifiedName ->
155    "Unexpected qualified name"
156  ErrEmptyDo ->
157    "Expected do statement"
158  ErrLexeme _ _ ->
159    basicError
160  ErrToken
161    | SourceToken _ (TokLeftArrow _) : _ <- errToks ->
162        "Unexpected \"<-\" in expression, perhaps due to a missing 'do' or 'ado' keyword"
163  ErrToken ->
164    basicError
165  ErrCustom err ->
166    err
167
168  where
169  basicError = case errToks of
170    tok : _ -> basicTokError (tokValue tok)
171    [] -> "Unexpected input"
172
173  basicTokError = \case
174    TokLayoutStart -> "Unexpected or mismatched indentation"
175    TokLayoutSep   -> "Unexpected or mismatched indentation"
176    TokLayoutEnd   -> "Unexpected or mismatched indentation"
177    TokEof         -> "Unexpected end of input"
178    tok            -> "Unexpected token '" <> Text.unpack (printToken tok) <> "'"
179
180  displayCodePoint :: Char -> String
181  displayCodePoint x =
182    "U+" <> map toUpper (printf "%0.4x" (fromEnum x))
183
184prettyPrintWarningMessage :: ParserWarning -> String
185prettyPrintWarningMessage ParserErrorInfo {..} = case errType of
186  WarnDeprecatedRowSyntax ->
187    "Unary '#' syntax for row kinds is deprecated and will be removed in a future release. Use the 'Row' kind instead."
188  WarnDeprecatedForeignKindSyntax ->
189    "Foreign kind imports are deprecated and will be removed in a future release. Use empty 'data' instead."
190  WarnDeprecatedConstraintInForeignImportSyntax ->
191    "Constraints are deprecated in foreign imports and will be removed in a future release. Omit the constraint instead and update the foreign module accordingly."
192  WarnDeprecatedKindImportSyntax ->
193    "Kind imports are deprecated and will be removed in a future release. Omit the 'kind' keyword instead."
194  WarnDeprecatedKindExportSyntax ->
195    "Kind exports are deprecated and will be removed in a future release. Omit the 'kind' keyword instead."
196