@@ -16,8 +16,10 @@ import Idris.Parser.Helpers
1616import Prelude hiding (pi)
1717
1818import Control.Applicative
19+import Control.Arrow (first)
1920import Control.Monad
2021import Control.Monad.State.Strict
22+import Data.Char (isAlpha)
2123import Data.List
2224import Text.Parser.Expression
2325import Text.Trifecta hiding (char, charLiteral, natural, span, string,
@@ -29,56 +31,85 @@ table :: [FixDecl] -> OperatorTable IdrisParser PTerm
2931table fixes
3032 = [[prefix "-" (\fc x -> PApp fc (PRef fc [fc] (sUN "negate")) [pexp x])]] ++
3133 toTable (reverse fixes) ++
32− [[backtick],
33− [binary "$" (\fc x y -> flatten $ PApp fc x [pexp y]) AssocRight],
34− [binary "=" (\fc x y -> PApp fc (PRef fc [fc] eqTy) [pexp x, pexp y]) AssocLeft],
35− [nofixityoperator]]
34+ [[noFixityBacktickOperator],
35+ [binary "$" AssocRight $ \fc _ x y -> flatten $ PApp fc x [pexp y]],
36+ [binary "=" AssocLeft $ \fc _ x y -> PApp fc (PRef fc [fc] eqTy) [pexp x, pexp y]],
37+ [noFixityOperator]]
3638 where
37− flatten :: PTerm -> PTerm -- flatten application
39+ flatten :: PTerm -> PTerm -- flatten application
3840 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
39− flatten t = t
40−
41−
42−-- | Calculates table for fixity declarations
43−toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
44−toTable fs = map (map toBin)
45− (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
46− where toBin (Fix (PrefixN _) op) = prefix op
47− (\fc x -> PApp fc (PRef fc [] (sUN op)) [pexp x])
48− toBin (Fix f op)
49− = binary op (\fc x y -> PApp fc (PRef fc [] (sUN op)) [pexp x,pexp y]) (assoc f)
50− assoc (Infixl _) = AssocLeft
51− assoc (Infixr _) = AssocRight
52− assoc (InfixN _) = AssocNone
53−
54−-- | Binary operator
55−binary :: String -> (FC -> PTerm -> PTerm -> PTerm) -> Assoc -> Operator IdrisParser PTerm
56−binary name f = Infix (do indentPropHolds gtProp
57− fc <- reservedOpFC name
58− indentPropHolds gtProp
59− return (f fc))
60−
61−-- | Prefix operator
62−prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
63−prefix name f = Prefix (do reservedOp name
64− fc <- getFC
65− indentPropHolds gtProp
66− return (f fc))
67−
68−-- | Backtick operator
69−backtick :: Operator IdrisParser PTerm
70−backtick = Infix (do indentPropHolds gtProp
71− lchar '`'; (n, fc) <- fnName
72− lchar '`'
73− indentPropHolds gtProp
74− return (\x y -> PApp fc (PRef fc [fc] n) [pexp x, pexp y])) AssocNone
75−
76−-- | Operator without fixity (throws an error)
77−nofixityoperator :: Operator IdrisParser PTerm
78−nofixityoperator = Infix (do indentPropHolds gtProp
79− op <- try operator
80− unexpected $ "Operator without known fixity: " ++ op) AssocNone
41+ flatten t = t
42+
43+ noFixityBacktickOperator :: Operator IdrisParser PTerm
44+ noFixityBacktickOperator = flip Infix AssocNone $ do
45+ (n, fc) <- backtickOperator
46+ return $ \x y -> PApp fc (PRef fc [fc] n) [pexp x, pexp y]
47+
48+ -- | Operator without fixity (throws an error)
49+ noFixityOperator :: Operator IdrisParser PTerm
50+ noFixityOperator = flip Infix AssocNone $ do
51+ indentGt
52+ op <- try symbolicOperator
53+ unexpected $ "Operator without known fixity: " ++ op
54+
55+ -- | Calculates table for fixity declarations
56+ toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
57+ toTable fs = map (map toBin) (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
58+
59+ toBin (Fix (PrefixN _) op) = prefix op $ \fc x ->
60+ PApp fc (PRef fc [] (sUN op)) [pexp x]
61+ toBin (Fix f op) = binary op (assoc f) $ \fc n x y ->
62+ PApp fc (PRef fc [] n) [pexp x,pexp y]
63+
64+ assoc (Infixl _) = AssocLeft
65+ assoc (Infixr _) = AssocRight
66+ assoc (InfixN _) = AssocNone
67+
68+ isBacktick :: String -> Bool
69+ isBacktick (c : _) = c == '_' || isAlpha c
70+ isBacktick _ = False
71+
72+ binary :: String -> Assoc -> (FC -> Name -> PTerm -> PTerm -> PTerm) -> Operator IdrisParser PTerm
73+ binary name assoc f
74+ | isBacktick name = flip Infix assoc $ try $ do
75+ (n, fc) <- backtickOperator
76+ guard $ show (nsroot n) == name
77+ return $ f fc n
78+ | otherwise = flip Infix assoc $ do
79+ indentGt
80+ fc <- reservedOpFC name
81+ indentGt
82+ return $ f fc (sUN name)
83+
84+ prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
85+ prefix name f = Prefix (do reservedOp name
86+ fc <- getFC
87+ indentGt
88+ return (f fc))
89+
90+{- | Parses a function used as an operator -- enclosed in backticks
8191
92+@
93+ BacktickOperator ::=
94+ '`' Name '`'
95+ ;
96+@
97+-}
98+backtickOperator :: IdrisParser (Name, FC)
99+backtickOperator = between (indentGt *> lchar '`') (indentGt *> lchar '`') name
100+
101+{- | Parses an operator name (either a symbolic name or a backtick-quoted name)
102+
103+@
104+ OperatorName ::=
105+ SymbolicOperator
106+ | BacktickOperator
107+ ;
108+@
109+-}
110+operatorName :: IdrisParser (Name, FC)
111+operatorName = first sUN <$> symbolicOperatorFC
112+ <|> backtickOperator
82113
83114{- | Parses an operator in function position i.e. enclosed by `()', with an
84115 optional namespace
@@ -96,7 +127,7 @@ operatorFront = try (do (FC f (l, c) _) <- getFC
96127 op <- lchar '(' *> reservedOp "=" <* lchar ')'
97128 return (eqTy, FC f (l, c) (l, c+3)))
98129 <|> maybeWithNS (do (FC f (l, c) _) <- getFC
99− op <- lchar '(' *> operator
130+ op <- lchar '(' *> symbolicOperator
100131 (FC _ _ (l', c')) <- getFC
101132 lchar ')'
102133 return (op, (FC f (l, c) (l', c' + 1)))) False []
@@ -120,7 +151,7 @@ Fixity ::=
120151fixity :: IdrisParser PDecl
121152fixity = do pushIndent
122153 f <- fixityType; i <- fst <$> natural;
123− ops <- sepBy1 operator (lchar ',')
154+ ops <- sepBy1 (show . nsroot . fst <$> operatorName) (lchar ',')
124155 terminator
125156 let prec = fromInteger i
126157 istate <- get
@@ -137,14 +168,15 @@ fixity = do pushIndent
137168 else fail $ concatMap (\(f, (x:xs)) -> "Illegal redeclaration of fixity:\n\t\""
138169 ++ show f ++ "\" overrides \"" ++ show x ++ "\"") ill
139170 <?> "fixity declaration"
140− where alreadyDeclared :: [FixDecl] -> FixDecl -> (FixDecl, [FixDecl])
141− alreadyDeclared fs f = (f, filter ((extractName f ==) . extractName) fs)
171+ where
172+ alreadyDeclared :: [FixDecl] -> FixDecl -> (FixDecl, [FixDecl])
173+ alreadyDeclared fs f = (f, filter ((extractName f ==) . extractName) fs)
142174
143− checkValidity :: (FixDecl, [FixDecl]) -> Bool
144− checkValidity (f, fs) = all (== f) fs
175+ checkValidity :: (FixDecl, [FixDecl]) -> Bool
176+ checkValidity (f, fs) = all (== f) fs
145177
146− extractName :: FixDecl -> String
147− extractName (Fix _ n) = n
178+ extractName :: FixDecl -> String
179+ extractName (Fix _ n) = n
148180
149181-- | Check that a declaration of an operator also has fixity declared
150182checkDeclFixity :: IdrisParser PDecl -> IdrisParser PDecl