1
1
module Text.Parsing.Parser where
2
2
3
3
import Prelude
4
+ import Control.Monad
4
5
import Data.Array
5
6
import Data.Either
6
7
import Data.Maybe
@@ -151,6 +152,11 @@ chainr1' p f a = (do f' <- f
151
152
a' <- chainr1 p f
152
153
return $ f' a a') <|> return a
153
154
155
+ choice :: forall s a . [Parser s a ] -> Parser s a
156
+ choice [] = fail " Nothing to parse"
157
+ choice [x] = x
158
+ choice (x: xs) = x <|> choice xs
159
+
154
160
-- String Parsers
155
161
156
162
eof :: Parser String {}
@@ -167,3 +173,78 @@ char :: Parser String String
167
173
char = Parser $ \ s -> case s of
168
174
" " -> failureResult s false $ parseError " Unexpected EOF"
169
175
_ -> successResult (substring 1 (lengthS s) s) true (substr 0 1 s)
176
+
177
+ -- Expressions
178
+
179
+ data Assoc = AssocNone | AssocLeft | AssocRight
180
+
181
+ data Operator s a = Infix (Parser s (a -> a -> a )) Assoc |
182
+ Prefix (Parser s (a -> a )) |
183
+ Postfix (Parser s (a -> a ))
184
+
185
+ type OperatorTable s a = [[Operator s a ]]
186
+
187
+ type SplitAccum s a = { rassoc :: [Parser s (a -> a -> a )], lassoc :: [Parser s (a -> a -> a )], nassoc :: [Parser s (a -> a -> a )], prefix :: [Parser s (a -> a )], postfix :: [Parser s (a -> a )] }
188
+
189
+ splitOp :: forall s a . SplitAccum s a -> Operator s a -> SplitAccum s a
190
+ splitOp accum (Infix op AssocNone ) = accum { nassoc = op: accum. nassoc }
191
+ splitOp accum (Infix op AssocLeft ) = accum { lassoc = op: accum. lassoc }
192
+ splitOp accum (Infix op AssocRight ) = accum { rassoc = op: accum. rassoc }
193
+ splitOp accum (Prefix op) = accum { prefix = op: accum. prefix }
194
+ splitOp accum (Postfix op) = accum { postfix = op: accum. postfix }
195
+
196
+ buildExprParser :: forall s a . OperatorTable s a -> Parser s a -> Parser s a
197
+ buildExprParser operators simpleExpr =
198
+ let
199
+ makeParser = \ term ops ->
200
+ let accum = foldr splitOp { rassoc: [] , lassoc: [] , nassoc: [] , prefix: [] , postfix: [] } ops in
201
+
202
+ let rassocOp = choice accum. rassoc in
203
+ let lassocOp = choice accum. lassoc in
204
+ let nassocOp = choice accum. nassoc in
205
+ let prefixOp = choice accum. prefix <?> " " in
206
+ let postfixOp = choice accum. postfix <?> " " in
207
+
208
+ let ambigious = \ assoc op -> try $ op >>= \ _ -> fail (" ambiguous use of a " ++ assoc ++ " associative operator" ) in
209
+
210
+ let ambigiousRight = ambigious " right" rassocOp in
211
+ let ambigiousLeft = ambigious " left" lassocOp in
212
+ let ambigiousNon = ambigious " non" nassocOp in
213
+
214
+ let postfixP = postfixOp <|> return id in
215
+
216
+ let prefixP = prefixOp <|> return id in
217
+
218
+ let termP = do
219
+ pre <- prefixP
220
+ x <- term
221
+ post <- postfixP
222
+ return (post (pre x)) in
223
+
224
+ let rassocP = \ x -> (do
225
+ f <- rassocOp
226
+ y <- do
227
+ z <- termP
228
+ rassocP1 z
229
+ return (f x y)) <|> ambigiousLeft <|> ambigiousNon in
230
+
231
+ let rassocP1 = \ x -> rassocP x <|> return x in
232
+
233
+ let lassocP = \ x -> (do
234
+ f <- lassocOp
235
+ y <- termP
236
+ lassocP1 (f x y)) <|> ambigiousRight <|> ambigiousNon in
237
+
238
+ let lassocP1 = \ x -> lassocP x <|> return x in
239
+
240
+ let nassocP = \ x -> do
241
+ f <- nassocOp
242
+ y <- termP
243
+ ambigiousRight <|> ambigiousLeft <|> ambigiousNon <|> return (f x y)
244
+
245
+ in do
246
+ x <- termP
247
+ rassocP x <|> lassocP x <|> nassocP x <|> return x <?> " operator"
248
+
249
+ in foldl (makeParser) simpleExpr operators
250
+
0 commit comments