on master help sign in
Get parse errors working for many primitive cases
768a565Evan Czaplicki
src/Parse/Primitives.hs+40−35
@@ -416,37 +416,39 @@ infixOp =
416 eerr (loneTheory row col InfixOp)
416 eerr (loneTheory row col InfixOp)
417
417
418 else
418 else
419+ let
420+ (Text.Iter char size) = peek array offset
421+ in
422+ if not (Help.isSymbol char) then
423+ eerr (loneTheory row col InfixOp)
424+ else
419− case infixOpHelp array offset length row col of
425+ case infixOpHelp array (offset + size) (length - size) row (col + 1) of
420− Left err ->
426+ Left err ->
421− cerr err
427+ cerr err
422−
428+
423− Right ( newOffset, newLength, newCol ) ->
429+ Right ( newOffset, newLength, newCol ) ->
424− let
430+ let
425− !size =
431+ !newSize =
426− newOffset - offset
432+ newOffset - offset
427−
433+
428− makeArray =
434+ makeArray =
429− do mutableArray <- Text.new size
435+ do mutableArray <- Text.new newSize
430− Text.copyI mutableArray 0 array offset size
436+ Text.copyI mutableArray 0 array offset newSize
431− return mutableArray
437+ return mutableArray
432− in
438+ in
433− if size == 0 then
434− eerr (loneTheory row col InfixOp)
435−
436− else
437− case Text.Text (Text.run makeArray) 0 size of
439+ case Text.Text (Text.run makeArray) 0 newSize of
438− "=" -> cerr (ParseError row col Dot)
440+ "=" -> cerr (ParseError row col Dot)
439− "|" -> cerr (ParseError row col Pipe)
441+ "|" -> cerr (ParseError row col Pipe)
440− ":" -> cerr (ParseError row col Arrow)
442+ ":" -> cerr (ParseError row col Arrow)
441− "." -> cerr (ParseError row col Equals)
443+ "." -> cerr (ParseError row col Equals)
442− "->" -> cerr (ParseError row col HasType)
444+ "->" -> cerr (ParseError row col HasType)
443− op -> cok op (State array newOffset newLength indent row newCol)
445+ op -> cok op (State array newOffset newLength indent row newCol)
444
446
445
447
446infixOpHelp :: Text.Array -> Int -> Int -> Int -> Int -> Either ParseError (Int, Int, Int)
448infixOpHelp :: Text.Array -> Int -> Int -> Int -> Int -> Either ParseError (Int, Int, Int)
447infixOpHelp array offset length row col =
449infixOpHelp array offset length row col =
448 if length == 0 then
450 if length == 0 then
449− Left (ParseError row col (EndOfFile "infix operator"))
451+ Right ( offset, length, col )
450
452
451 else
453 else
452 let
454 let
@@ -599,7 +601,7 @@ eatMultiComment array offset length row col =
599eatMultiCommentHelp :: Text.Array -> Int -> Int -> Int -> Int -> Int -> Either ParseError ( Int, Int, Int, Int )
601eatMultiCommentHelp :: Text.Array -> Int -> Int -> Int -> Int -> Int -> Either ParseError ( Int, Int, Int, Int )
600eatMultiCommentHelp array offset length row col openComments =
602eatMultiCommentHelp array offset length row col openComments =
601 if length == 0 then
603 if length == 0 then
602− Left (ParseError row col (EndOfFile "multi-line comment"))
604+ Left (ParseError row col EndOfFile_Comment)
603
605
604 else
606 else
605 let
607 let
@@ -703,7 +705,7 @@ isQuote array offset =
703singleString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, Text.Text )
705singleString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, Text.Text )
704singleString array offset length row col initialOffset builder =
706singleString array offset length row col initialOffset builder =
705 if length == 0 then
707 if length == 0 then
706− Left (ParseError row col (EndOfFile "string"))
708+ Left (ParseError row col EndOfFile_String)
707
709
708 else
710 else
709 let
711 let
@@ -724,7 +726,7 @@ singleString array offset length row col initialOffset builder =
724 Left (ParseError row col NewLineInString)
726 Left (ParseError row col NewLineInString)
725
727
726 else if word == 0x005C {- \ -} then
728 else if word == 0x005C {- \ -} then
727− case eatEscape array (offset + 1) (length - 1) row (col + 1) of
729+ case eatEscape array (offset + 1) (length - 1) row (col + 1) EndOfFile_String of
728 Left err ->
730 Left err ->
729 Left err
731 Left err
730
732
@@ -743,10 +745,10 @@ singleString array offset length row col initialOffset builder =
743 singleString array (offset + 2) (length - 2) row (col + 1) initialOffset builder
745 singleString array (offset + 2) (length - 2) row (col + 1) initialOffset builder
744
746
745
747
746−eatEscape :: Text.Array -> Int -> Int -> Int -> Int -> Either ParseError ( Int, Char )
748+eatEscape :: Text.Array -> Int -> Int -> Int -> Int -> Problem -> Either ParseError ( Int, Char )
747−eatEscape array offset length row col =
749+eatEscape array offset length row col problem =
748 if length == 0 then
750 if length == 0 then
749− Left (ParseError row col (EndOfFile "escape sequence"))
751+ Left (ParseError row col problem)
750
752
751 else
753 else
752 case Text.unsafeIndex array offset of
754 case Text.unsafeIndex array offset of
@@ -804,7 +806,7 @@ eatHex array offset length n =
804multiString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, Text.Text )
806multiString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, Text.Text )
805multiString array offset length row col initialOffset builder =
807multiString array offset length row col initialOffset builder =
806 if length == 0 then
808 if length == 0 then
807− Left (ParseError row col (EndOfFile "multi-line string"))
809+ Left (ParseError row col EndOfFile_MultiString)
808
810
809 else
811 else
810 let
812 let
@@ -822,7 +824,7 @@ multiString array offset length row col initialOffset builder =
822 Right ( offset + 3, length - 3, col + 3, str )
824 Right ( offset + 3, length - 3, col + 3, str )
823
825
824 else if word == 0x005C {- \ -} then
826 else if word == 0x005C {- \ -} then
825− case eatEscape array (offset + 1) (length - 1) row (col + 1) of
827+ case eatEscape array (offset + 1) (length - 1) row (col + 1) EndOfFile_MultiString of
826 Left err ->
828 Left err ->
827 Left err
829 Left err
828
830
@@ -887,7 +889,7 @@ characterHelp array offset length row col =
887 Left (ParseError row col BadChar)
889 Left (ParseError row col BadChar)
888
890
889 else if word == 0x005C {- \ -} then
891 else if word == 0x005C {- \ -} then
890− eatEscape array (offset + 1) (length - 1) row (col + 1)
892+ eatEscape array (offset + 1) (length - 1) row (col + 1) BadChar
891
893
892 else if word == 0x000A {- \n -} then
894 else if word == 0x000A {- \n -} then
893 Left (ParseError row col BadChar)
895 Left (ParseError row col BadChar)
@@ -990,6 +992,9 @@ chompInt array startOffset offset length =
990 else if word == 0x002E {- . -} then
992 else if word == 0x002E {- . -} then
991 chompFraction array startOffset (offset + 1) (length - 1)
993 chompFraction array startOffset (offset + 1) (length - 1)
992
994
995+ else if word == 0x0065 {- e -} || word == 0x0045 {- E -} then
996+ chompExponent array startOffset (offset + 1) (length - 1)
997+
993 else
998 else
994 Right ( offset, length, readInt array startOffset offset )
999 Right ( offset, length, readInt array startOffset offset )
995
1000
src/Reporting/Error/Syntax.hs+237−25
@@ -8,13 +8,14 @@ module Reporting.Error.Syntax
8 )
8 )
9 where
9 where
10
10
11+import qualified Data.Set as Set
11import Data.Text (Text)
12import Data.Text (Text)
12
13
13import qualified Reporting.Render.Type as RenderType
14import qualified Reporting.Render.Type as RenderType
14import qualified Reporting.Region as Region
15import qualified Reporting.Region as Region
15import qualified Reporting.Report as Report
16import qualified Reporting.Report as Report
16import qualified Reporting.Helpers as Help
17import qualified Reporting.Helpers as Help
17−import Reporting.Helpers ((<>), dullyellow, hsep, i2t, text)
18+import Reporting.Helpers ((<>), dullyellow, hsep, i2t, reflowParagraph, text)
18
19
19
20
20
21
@@ -59,7 +60,9 @@ data ParseError
59
60
60data Problem
61data Problem
61 = Tab
62 = Tab
62− | EndOfFile Text
63+ | EndOfFile_Comment
64+ | EndOfFile_String
65+ | EndOfFile_MultiString
63 | NewLineInString
66 | NewLineInString
64 | BadEscape
67 | BadEscape
65 | BadChar
68 | BadChar
@@ -69,11 +72,11 @@ data Problem
69 | BadNumberHex
72 | BadNumberHex
70 | BadNumberZero
73 | BadNumberZero
71 | BadChunkInQualifiedCapVar
74 | BadChunkInQualifiedCapVar
72− | HasType -- "A single colon is for type annotations. Maybe you want :: instead? Or maybe you are defining a type annotation, but there is whitespace before it?"
75+ | HasType
73− | Equals -- "The = operator is reserved for defining variables. Maybe you want == instead? Or maybe you are defining a variable, but there is whitespace before it?"
76+ | Equals
74− | Arrow -- "Arrows are reserved for cases and anonymous functions. Maybe you want > or >= instead?"
77+ | Arrow
75− | Pipe -- "Vertical bars are reserved for use in union type declarations. Maybe you want || instead?"
78+ | Pipe
76− | Dot -- "Dots are for record access. They cannot float around on their own!"
79+ | Dot
77 | Theories [Theory]
80 | Theories [Theory]
78
81
79
82
@@ -86,6 +89,7 @@ data Theory
86 | BadIndent
89 | BadIndent
87 | FreshLine
90 | FreshLine
88 | Expecting Text
91 | Expecting Text
92+ deriving (Eq, Ord)
89
93
90
94
91
95
@@ -95,15 +99,15 @@ data Theory
95toReport :: RenderType.Localizer -> Error -> Report.Report
99toReport :: RenderType.Localizer -> Error -> Report.Report
96toReport _localizer err =
100toReport _localizer err =
97 case err of
101 case err of
98− Parse _ ->
102+ Parse problem ->
99− Report.report "PARSE ERROR" Nothing "Something is wrong." (text "TODO")
103+ problemToReport problem
100
104
101 BadFunctionName arity ->
105 BadFunctionName arity ->
102 Report.report
106 Report.report
103 "BAD FUNCTION DEFINITION"
107 "BAD FUNCTION DEFINITION"
104 Nothing
108 Nothing
105 "Complex patterns cannot be used as function names."
109 "Complex patterns cannot be used as function names."
106− ( Help.reflowParagraph $
110+ ( reflowParagraph $
107 "This function definition has " <> i2t arity <> " arguments, but instead\
111 "This function definition has " <> i2t arity <> " arguments, but instead\
108 \ of a normal name like `add` or `reverse` it has a pattern. There is no\
112 \ of a normal name like `add` or `reverse` it has a pattern. There is no\
109 \ way to \"deconstruct\" a function with pattern matching, so this needs to\
113 \ way to \"deconstruct\" a function with pattern matching, so this needs to\
@@ -117,7 +121,7 @@ toReport _localizer err =
117 ("The free variable `" <> name <> "` appears more than once in this pattern.")
121 ("The free variable `" <> name <> "` appears more than once in this pattern.")
118 ( Help.stack
122 ( Help.stack
119 [ text "Rename the variables so there are no duplicates."
123 [ text "Rename the variables so there are no duplicates."
120− , Help.reflowParagraph $
124+ , reflowParagraph $
121 "In Elm, pattern matching works by binding these free variables to subsections\
125 "In Elm, pattern matching works by binding these free variables to subsections\
122 \ of the matching value. It does not make sense to have the same name for two\
126 \ of the matching value. It does not make sense to have the same name for two\
123 \ different subsections though! When you say `" <> name <> "` in some code, there\
127 \ different subsections though! When you say `" <> name <> "` in some code, there\
@@ -130,7 +134,7 @@ toReport _localizer err =
130 "STRAY COMMENT"
134 "STRAY COMMENT"
131 Nothing
135 Nothing
132 ("This documentation comment is not followed by anything.")
136 ("This documentation comment is not followed by anything.")
133− ( Help.reflowParagraph $
137+ ( reflowParagraph $
134 "All documentation comments need to be right above the declaration they\
138 "All documentation comments need to be right above the declaration they\
135 \ describe. Maybe some code got deleted or commented out by accident? Or\
139 \ describe. Maybe some code got deleted or commented out by accident? Or\
136 \ maybe this comment is here by accident?"
140 \ maybe this comment is here by accident?"
@@ -141,7 +145,7 @@ toReport _localizer err =
141 "BAD MODULE DECLARATION"
145 "BAD MODULE DECLARATION"
142 Nothing
146 Nothing
143 "A normal module can expose values, but not settings like this."
147 "A normal module can expose values, but not settings like this."
144− ( Help.reflowParagraph $
148+ ( reflowParagraph $
145 "If you want a normal module, just remove this stuff. If you want to create\
149 "If you want a normal module, just remove this stuff. If you want to create\
146 \ an `effect module` you just forgot to use the `effect` keyword. In that\
150 \ an `effect module` you just forgot to use the `effect` keyword. In that\
147 \ case, just change `module` to `effect module` and you should be headed in\
151 \ case, just change `module` to `effect module` and you should be headed in\
@@ -153,7 +157,7 @@ toReport _localizer err =
153 "BAD MODULE DECLARATION"
157 "BAD MODULE DECLARATION"
154 Nothing
158 Nothing
155 "A port module can expose values, but not have settings like this."
159 "A port module can expose values, but not have settings like this."
156− ( Help.reflowParagraph $
160+ ( reflowParagraph $
157 "If you want a port module, just remove this stuff. If you want to create\
161 "If you want a port module, just remove this stuff. If you want to create\
158 \ a custom effect module instead (which is rare) just change `port module`\
162 \ a custom effect module instead (which is rare) just change `port module`\
159 \ to `effect module` and you should be headed in the right direction!"
163 \ to `effect module` and you should be headed in the right direction!"
@@ -164,7 +168,7 @@ toReport _localizer err =
164 "EFFECT MODULE PROBLEM"
168 "EFFECT MODULE PROBLEM"
165 Nothing
169 Nothing
166 ("You have defined " <> Help.functionName name <> " multiple times.")
170 ("You have defined " <> Help.functionName name <> " multiple times.")
167− ( Help.reflowParagraph $
171+ ( reflowParagraph $
168 "There can only be one " <> Help.functionName name
172 "There can only be one " <> Help.functionName name
169 <> " though! Remove until there is one left."
173 <> " though! Remove until there is one left."
170 )
174 )
@@ -174,7 +178,7 @@ toReport _localizer err =
174 "EFFECT MODULE PROBLEM"
178 "EFFECT MODULE PROBLEM"
175 Nothing
179 Nothing
176 ("Setting " <> Help.functionName name <> " is not recognized.")
180 ("Setting " <> Help.functionName name <> " is not recognized.")
177− ( Help.reflowParagraph $
181+ ( reflowParagraph $
178 "Remove this entry and you should be all set!"
182 "Remove this entry and you should be all set!"
179 )
183 )
180
184
@@ -183,7 +187,7 @@ toReport _localizer err =
183 "EFFECT MODULE PROBLEM"
187 "EFFECT MODULE PROBLEM"
184 Nothing
188 Nothing
185 ("You are defining an effect module, but it has no settings.")
189 ("You are defining an effect module, but it has no settings.")
186− ( Help.reflowParagraph $
190+ ( reflowParagraph $
187 "If you just wanted a normal module, change the keywords `effect module`\
191 "If you just wanted a normal module, change the keywords `effect module`\
188 \ to `module` and you should be all set. If you want a proper effect module,\
192 \ to `module` and you should be all set. If you want a proper effect module,\
189 \ you need to specify your commands and/or subscriptions. Read more about this\
193 \ you need to specify your commands and/or subscriptions. Read more about this\
@@ -195,7 +199,7 @@ toReport _localizer err =
195 "EFFECT MODULE PROBLEM"
199 "EFFECT MODULE PROBLEM"
196 Nothing
200 Nothing
197 ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
201 ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
198− ( Help.reflowParagraph $
202+ ( reflowParagraph $
199 "There is a small set of top-level functions and values that must be defined\
203 "There is a small set of top-level functions and values that must be defined\
200 \ in any complete effect module. The best thing is probably to just read more\
204 \ in any complete effect module. The best thing is probably to just read more\
201 \ about effect modules here:\
205 \ about effect modules here:\
@@ -207,7 +211,7 @@ toReport _localizer err =
207 "BAD PORT"
211 "BAD PORT"
208 Nothing
212 Nothing
209 ("You are declaring port " <> Help.functionName name <> " in a normal module.")
213 ("You are declaring port " <> Help.functionName name <> " in a normal module.")
210− ( Help.reflowParagraph $
214+ ( reflowParagraph $
211 "All ports must be defined in a `port module`. You should probably have just\
215 "All ports must be defined in a `port module`. You should probably have just\
212 \ one of these for your project. This way all of your foreign interactions\
216 \ one of these for your project. This way all of your foreign interactions\
213 \ stay relatively organized."
217 \ stay relatively organized."
@@ -233,7 +237,7 @@ toReport _localizer err =
233 <> "` is used more than once in the arguments of "
237 <> "` is used more than once in the arguments of "
234 <> Help.functionName funcName <> "."
238 <> Help.functionName funcName <> "."
235 )
239 )
236− ( Help.reflowParagraph $
240+ ( reflowParagraph $
237 "Rename things until `" <> argName <> "` is used only once.\
241 "Rename things until `" <> argName <> "` is used only once.\
238 \ Otherwise how can we tell which one you want when you\
242 \ Otherwise how can we tell which one you want when you\
239 \ say `" <> argName <> "` it in the body of your function?"
243 \ say `" <> argName <> "` it in the body of your function?"
@@ -253,7 +257,7 @@ toReport _localizer err =
253 ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
257 ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
254 <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
258 <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
255 )
259 )
256− ( Help.reflowParagraph $
260+ ( reflowParagraph $
257 "Find all the top-level values named " <> Help.functionName name
261 "Find all the top-level values named " <> Help.functionName name
258 <> " and do some renaming. Make sure the names are distinct!"
262 <> " and do some renaming. Make sure the names are distinct!"
259 )
263 )
@@ -264,7 +268,7 @@ toReport _localizer err =
264 Nothing
268 Nothing
265 ( "There are multiple types named `" <> name <> "` in this module."
269 ( "There are multiple types named `" <> name <> "` in this module."
266 )
270 )
267− ( Help.reflowParagraph $
271+ ( reflowParagraph $
268 "Search through this module, find all the types named `"
272 "Search through this module, find all the types named `"
269 <> name <> "`, and give each of them a unique name."
273 <> name <> "`, and give each of them a unique name."
270 )
274 )
@@ -275,7 +279,7 @@ toReport _localizer err =
275 Nothing
279 Nothing
276 ("There are multiple values named `" <> name <> "` in this let-expression."
280 ("There are multiple values named `" <> name <> "` in this let-expression."
277 )
281 )
278− ( Help.reflowParagraph $
282+ ( reflowParagraph $
279 "Search through this let-expression, find all the values named `"
283 "Search through this let-expression, find all the values named `"
280 <> name <> "`, and give each of them a unique name."
284 <> name <> "`, and give each of them a unique name."
281 )
285 )
@@ -307,7 +311,7 @@ toReport _localizer err =
307 ( "Type alias `" <> typeName <> "` has some problems with type variables."
311 ( "Type alias `" <> typeName <> "` has some problems with type variables."
308 )
312 )
309 ( Help.stack
313 ( Help.stack
310− [ Help.reflowParagraph $
314+ [ reflowParagraph $
311 "The declaration says it uses certain type variables ("
315 "The declaration says it uses certain type variables ("
312 <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
316 <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
313 <> "Furthermore, the aliased type says it uses type variables ("
317 <> "Furthermore, the aliased type says it uses type variables ("
@@ -334,9 +338,217 @@ unboundTypeVars declKind typeName givenVars unboundVars =
334 map text (declKind : typeName : givenVars)
338 map text (declKind : typeName : givenVars)
335 ++ map (dullyellow . text) unboundVars
339 ++ map (dullyellow . text) unboundVars
336 ++ map text ["=", "..."]
340 ++ map text ["=", "..."]
337− , Help.reflowParagraph $
341+ , reflowParagraph $
338 "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
342 "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
339 "` is an Int and another where it is a Bool. When we explicitly list the type\
343 "` is an Int and another where it is a Bool. When we explicitly list the type\
340 \ variables, the type checker can see that they are actually different types."
344 \ variables, the type checker can see that they are actually different types."
341 ]
345 ]
342 )
346 )
347+
348+
349+
350+-- PARSE ERROR TO REPORT
351+
352+
353+parseReport :: Text -> Help.Doc -> Report.Report
354+parseReport pre post =
355+ Report.report "PARSE ERROR" Nothing pre post
356+
357+
358+problemToReport :: Problem -> Report.Report
359+problemToReport problem =
360+ case problem of
361+ Tab ->
362+ parseReport
363+ "I ran into a tab, but tabs are not allowed in Elm files."
364+ (reflowParagraph "Replace the tab with spages.")
365+
366+ EndOfFile_Comment ->
367+ parseReport
368+ "I got to the end of the file while parsing a multi-line comment."
369+ ( Help.stack
370+ [ reflowParagraph $
371+ "Multi-line comments look like {- comment -}, and it looks like\
372+ \ you are missing the closing marker."
373+ , reflowParagraph $
374+ "Nested multi-line comments like {- this {- and this -} -} are allowed.\
375+ \ That means the opening and closing markers must be balanced, just\
376+ \ like parentheses in normal code. Maybe that is the problem?"
377+ ]
378+ )
379+
380+ EndOfFile_String ->
381+ parseReport
382+ "I got to the end of the file while parsing a string."
383+ (reflowParagraph $
384+ "Strings look like \"this\" with double quotes on each end.\
385+ \ So the closing double quote seems to be missing."
386+ )
387+
388+ EndOfFile_MultiString ->
389+ parseReport
390+ "I got to the end of the file while parsing a multi-line string."
391+ (reflowParagraph $
392+ "Multi-line strings begin and end with three double quotes in a\
393+ \ row, like \"\"\"this\"\"\". So the closing marker seems\
394+ \ to be missing."
395+ )
396+
397+ NewLineInString ->
398+ parseReport
399+ "This string is missing the closing quote."
400+ ( Help.stack
401+ [ reflowParagraph $
402+ "Elm strings must start and end with a double quote, like \"this\"."
403+ , reflowParagraph $
404+ "If you want a string that can contain newlines, use three double quotes in a\
405+ \ row, like \"\"\"this\"\"\"."
406+ ]
407+ )
408+
409+ BadEscape ->
410+ parseReport
411+ "Ran into a bad escape code."
412+ ( reflowParagraph
413+ "Elm allows typical escape characters like \\n and \\t, but you can\
414+ \ also use \\x0040 to refer to unicode characters by their hex code.\
415+ \ It seems like something has gone wrong with one of these codes."
416+ )
417+
418+ BadChar ->
419+ parseReport
420+ "Ran into a bad use of single quotes."
421+ ( Help.stack
422+ [ reflowParagraph $
423+ "If you want to create a string, just switch to double quotes:"
424+ , Help.indent 4 $
425+ dullyellow (text "'this'")
426+ <> text " => "
427+ <> dullyellow (text "\"this\"")
428+ , reflowParagraph $
429+ "Unlike JavaScript, Elm distinguishes between strings like \"hello\"\
430+ \ and individual characters like 'A' and '3'. It is not all strings!\
431+ \ If you really do want a character though, something went wrong\
432+ \ and I did not find the closing single quote."
433+ ]
434+ )
435+
436+ BadNumberDot ->
437+ parseReport
438+ "Numbers cannot end with a decimal points."
439+ ( reflowParagraph $
440+ "Leave it off or add some digits after it, like or 3 or 3.0"
441+ )
442+
443+ BadNumberEnd ->
444+ parseReport
445+ "Numbers cannot have letters or underscores in them."
446+ ( reflowParagraph $
447+ "Maybe a space is missing between a number and a variable?"
448+ )
449+
450+ BadNumberExp ->
451+ parseReport
452+ "If you put the letter E in a number, it should followed by more digits."
453+ ( reflowParagraph $
454+ "If you want to say 1000, you can also say 1e3.\
455+ \ You cannot just end it with an E though!"
456+ )
457+
458+ BadNumberHex ->
459+ parseReport
460+ "I see the start of a hex number, but not the end."
461+ ( reflowParagraph $
462+ "A hex number looks like 0x123ABC, where the 0x is followed by hexidecimal digits (i.e. 0123456789abcdefABCDEF)"
463+ )
464+
465+ BadNumberZero ->
466+ parseReport
467+ "Normal numbers cannot start with a zero. Take the zeros off the front."
468+ ( reflowParagraph $
469+ "Only numbers like 0x0040 or 0.25 can start with a zero."
470+ )
471+
472+ BadChunkInQualifiedCapVar ->
473+ error "TODO"
474+
475+ HasType ->
476+ parseReport
477+ "Single colons should only show up in types."
478+ ( reflowParagraph $
479+ "Maybe you want :: instead? Or maybe you are defining\
480+ \ a type annotation but there are extra spaces before it?"
481+ )
482+
483+ Equals ->
484+ parseReport
485+ "The = operator is reserved for defining variables."
486+ ( reflowParagraph $
487+ "Maybe you want == instead? Or maybe you are defining a\
488+ \ variable but there are extra spaces before it?"
489+ )
490+
491+ Arrow ->
492+ parseReport
493+ "Arrows are reserved for cases and anonymous functions."
494+ ( reflowParagraph $
495+ "Maybe you want > or >= instead?"
496+ )
497+
498+ Pipe ->
499+ parseReport
500+ "Vertical bars are reserved for use in type declarations."
501+ ( reflowParagraph $
502+ "Maybe you want || instead?"
503+ )
504+
505+ Dot ->
506+ parseReport
507+ "Dots are for record access and decimal points."
508+ ( reflowParagraph $
509+ "They cannot float around on their own though, so\
510+ \ maybe there is some extra whitespace?"
511+ )
512+
513+ Theories allTheories ->
514+ case Set.toList (Set.fromList allTheories) of
515+ [] ->
516+ parseReport
517+ "Something went wrong when parsing this code."
518+ ( reflowParagraph $
519+ "I do not have any suggestions though, and I suspect there is some\
520+ \ sort of bug. Can you get it down to an <http://sscce.org> and\
521+ \ share it at <https://github.com/elm-lang/error-message-catalog/issues>?\
522+ \ That way we can figure out how to give better advice!"
523+ )
524+
525+ theories ->
526+ error "TODO" (map theoryToText theories)
527+
528+
529+theoryToText :: Theory -> Text
530+theoryToText theory =
531+ case theory of
532+ Keyword _ ->
533+ ""
534+
535+ Symbol _ ->
536+ ""
537+
538+ Variable ->
539+ ""
540+
541+ InfixOp ->
542+ ""
543+
544+ Digit ->
545+ "a digit, like 0 or 6"
546+
547+ BadIndent ->
548+ ""
549+
550+ FreshLine ->
551+ ""
552+
553+ Expecting _ ->
554+ ""