1
------------------------------------------------------------------------
2
------------------------------------------------------------------------
4
{-# LANGUAGE FlexibleContexts, GADTs #-}
6
module ExpressionParser
11
import qualified Parser
12
import Parser hiding (parse)
13
import PrecedenceGraph
19
import qualified MemoisedCPS
21
import Control.Applicative as A
22
import Data.Foldable (asum)
23
import qualified Data.List as List
24
import qualified Data.Set as Set
28
(!*) :: Annotation -> Fixity -> Set Name
29
m !* k = Set.unions [m ! (k, ass) | ass <- [Non, L, R]]
32
type Op = (Name, [Maybe Expr])
35
appLeft :: Maybe Expr -> Op -> Op
36
appLeft e (u, es) = (u, e : es)
38
appRight :: Op -> Maybe Expr -> Op
39
appRight (u, es) e = (u, es ++ [e])
41
appBoth :: Maybe Expr -> Op -> Maybe Expr -> Op
42
appBoth e1 o e2 = appLeft e1 (appRight o e2)
50
ExprN :: Set Node -> NT Expr
51
OpN :: Set Name -> NT Op
52
NodeN :: Node -> NT Expr
53
PostLeftsN :: Node -> NT Expr
57
expression :: PrecedenceGraph -> NT Expr
58
expression g = ExprN (nodes g)
61
placeholder :: NTParser p NT Token => Pos -> p (Maybe Expr)
62
placeholder p = Nothing <$ sym (Placeholder p)
65
namePart :: NTParser p NT Token
71
namePart ms n = symbol >>= \s -> case s of
72
QualifiedName ms' n' -> if ms' `List.isSuffixOf` ms && n' == n
73
then return () else A.empty
77
grammar :: NTParser p NT Token =>
79
-- ^ The precedence graph.
81
-- ^ A function giving all qualified names matching the
82
-- given qualified name (which might be given with an
83
-- incomplete module name prefix).
85
-- ^ Closed mixfix operators.
90
grammar g lookupName closed AtomN =
91
Fun <$> (asum =<< map return . filter (not . isOperator) .
92
Set.toList . lookupName <$> parseName)
93
<|> WildcardE <$ sym Wildcard
94
<|> sym LParen *> nonTerm (expression g) <* sym RParen
95
<|> toE <$> ( nonTerm (OpN closed)
96
<|> appRight <$> nonTerm (OpN prefix) <*> placeholder End
97
<|> appLeft <$> placeholder Beg <*> nonTerm (OpN postfix)
98
<|> appBoth <$> placeholder Beg <*> nonTerm (OpN infx) <*>
101
allOps = allOperators g
102
prefix = allOps !* Prefix
103
postfix = allOps !* Postfix
104
infx = allOps !* Infix
107
grammar _ _ _ (ExprN ns)
108
= app <$> nonTerm AtomN <*> many (nonTerm AtomN)
109
<|> asum (map (nonTerm . NodeN) $ Set.toList ns)
112
grammar g _ _ (OpN ops) = asum $ map op (Set.toList ops)
115
(Just <$> nonTerm (expression g) <|> placeholder Mid)
117
map (namePart (moduleName n)) (nameParts n)
120
grammar g _ _ (NodeN n) =
121
nonAssoc <|> preRights <|> nonTerm (PostLeftsN n)
123
-- Applications of non-associative operators.
124
nonAssoc = appBoth' <$>
125
higher g n <*> internal g n Infix Non <*> higher g n
127
-- Sequences of prefix/infix right-associative operators.
128
preRights = preRight <*> (preRights <|> higher g n)
130
preRight = appRight' <$> internal g n Prefix Non
131
<|> appBoth' <$> higher g n <*> internal g n Infix R
133
appRight' o e2 = toE $ appRight o (Just e2)
134
appBoth' e1 o e2 = toE $ appBoth (Just e1) o (Just e2)
137
grammar g _ _ (PostLeftsN n) = flip ($) <$>
138
(nonTerm (PostLeftsN n) <|> higher g n) <*> postLeft
140
postLeft = appLeft' <$> internal g n Postfix Non
141
<|> appBoth' <$> internal g n Infix L <*> higher g n
143
appLeft' o e1 = toE $ appLeft (Just e1) o
144
appBoth' o e2 e1 = toE $ appBoth (Just e1) o (Just e2)
147
internal :: NTParser p NT Token =>
148
PrecedenceGraph -> Node -> Fixity -> Assoc -> p Op
150
nonTerm (OpN (ann ! (f, ass)))
152
Prefix -> appLeft <$> placeholder Beg <*> infx
153
Postfix -> appRight <$> infx <*> placeholder End
157
infx = nonTerm (OpN (ann !* Infix))
160
higher :: NTParser p NT Token =>
161
PrecedenceGraph -> Node -> p Expr
162
higher g n = nonTerm (ExprN (successors g n))
165
parse :: PrecedenceGraph ->
166
-- ^ The precedence graph.
167
(Name -> Set Name) ->
168
-- ^ A function giving all qualified names matching the
169
-- given qualified name (which might be given with an
170
-- incomplete module name prefix).
172
-- ^ Closed mixfix operators.
176
parse g lookupName closed =
177
MemoisedCPS.parse (grammar g lookupName closed)
178
(nonTerm $ expression g)
180
------------------------------------------------------------------------
182
instance IndexedEq NT where
183
iEq (ExprN ns1) (ExprN ns2) = boolToEq $ ns1 == ns2
184
iEq (OpN ns1) (OpN ns2) = boolToEq $ ns1 == ns2
185
iEq (NodeN n1) (NodeN n2) = boolToEq $ n1 == n2
186
iEq (PostLeftsN n1) (PostLeftsN n2) = boolToEq $ n1 == n2
187
iEq AtomN AtomN = Just Refl
190
instance IndexedOrd NT where
191
iCompare (ExprN ns1) (ExprN ns2) = compare ns1 ns2
192
iCompare (OpN ns1) (OpN ns2) = compare ns1 ns2
193
iCompare (NodeN n1) (NodeN n2) = compare n1 n2
194
iCompare (PostLeftsN n1) (PostLeftsN n2) = compare n1 n2
195
iCompare AtomN AtomN = EQ
196
iCompare (ExprN _) _ = LT
197
iCompare (OpN _) (ExprN _) = GT
198
iCompare (OpN _) _ = LT
199
iCompare (NodeN _) (ExprN _) = GT
200
iCompare (NodeN _) (OpN _) = GT
201
iCompare (NodeN _) _ = LT
202
iCompare (PostLeftsN _) AtomN = LT
203
iCompare (PostLeftsN _) _ = GT
204
iCompare AtomN _ = GT