on master help sign in
Nicer error when using = | : -> as infix ops
816a476Evan Czaplicki
src/Parse/Binop.hs+30−6
@@ -1,9 +1,11 @@
1module Parse.Binop (infixOp, binops, OpTable) where
1module Parse.Binop (infixOp, binops, OpTable) where
2
2
3−import Control.Monad (guard)
4import qualified Data.List as List
3import qualified Data.List as List
5import qualified Data.Map as Map
4import qualified Data.Map as Map
5+import Text.Parsec
6−import Text.Parsec ((<|>), choice, getState, lower, many1, notFollowedBy, satisfy, try)
6+ ( (<|>), choice, getState, lookAhead, lower, many1
7+ , notFollowedBy, satisfy, string, try
8+ )
7
9
8import AST.Declaration (Assoc(L, N, R))
10import AST.Declaration (Assoc(L, N, R))
9import AST.Expression.General (Expr'(Binop))
11import AST.Expression.General (Expr'(Binop))
@@ -20,12 +22,34 @@ import qualified Reporting.Annotation as A
20
22
21infixOp :: IParser String
23infixOp :: IParser String
22infixOp =
24infixOp =
25+ infixOpWith notReserved
26+
27+
28+infixOpWith :: IParser String -> IParser String
29+infixOpWith checker =
23 expecting "an infix operator like (+)" $
30 expecting "an infix operator like (+)" $
24− do op <- many1 (satisfy (\c -> Help.isSymbol c))
31+ do op <- checker <|> many1 (satisfy Help.isSymbol)
25− guard (op `notElem` [ "=", "->", "--", "|", ":" ])
26 case op of
32 case op of
27 "." -> notFollowedBy lower >> return op
33 "." -> notFollowedBy lower >> return op
28− _ -> return op
34+ _ -> return op
35+
36+
37+failOn :: String -> String -> IParser a
38+failOn op msg =
39+ do try $ lookAhead $ do
40+ string op
41+ notFollowedBy (satisfy Help.isSymbol)
42+ failure msg
43+
44+
45+notReserved :: IParser a
46+notReserved =
47+ choice
48+ [ failOn "=" "The = operator is reserved for defining variables. Maybe you want == instead?"
49+ , failOn "->" "Arrows are reserved for cases and anonymous functions. Maybe you want > or >= instead?"
50+ , failOn "|" "Vertical bars are reserved for use in union type declarations. Maybe you want || instead?"
51+ , failOn ":" "A singe colon is for type annotations. Maybe you want :: instead?"
52+ ]
29
53
30
54
31
55
@@ -58,7 +82,7 @@ binops term last =
58 where
82 where
59 nextOps =
83 nextOps =
60 choice
84 choice
61− [ commitIf (whitespace >> infixOp) $
85+ [ commitIf (whitespace >> infixOpWith (fail "")) $
62 do whitespace
86 do whitespace
63 op <- infixOp
87 op <- infixOp
64 whitespace
88 whitespace