1 -----------------------------------------------------------------------------
3 -- Module : Text.ParserCombinators.Parsec.Expr
4 -- Copyright : (c) Daan Leijen 1999-2001
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : daan@cs.uu.nl
8 -- Stability : provisional
9 -- Portability : portable
11 -- A helper module to parse \"expressions\".
12 -- Builds a parser given a table of operators and associativities.
14 -----------------------------------------------------------------------------
16 module Text.ParserCombinators.Parsec.Expr
17 ( Assoc(..), Operator(..), OperatorTable
18 , buildExpressionParser
21 import Text.ParserCombinators.Parsec.Prim
22 import Text.ParserCombinators.Parsec.Combinator
25 -----------------------------------------------------------
26 -- Assoc and OperatorTable
27 -----------------------------------------------------------
28 data Assoc = AssocNone
32 data Operator t st a = Infix (GenParser t st (a -> a -> a)) Assoc
33 | Prefix (GenParser t st (a -> a))
34 | Postfix (GenParser t st (a -> a))
36 type OperatorTable t st a = [[Operator t st a]]
40 -----------------------------------------------------------
41 -- Convert an OperatorTable and basic term parser into
42 -- a full fledged expression parser
43 -----------------------------------------------------------
44 buildExpressionParser :: OperatorTable tok st a -> GenParser tok st a -> GenParser tok st a
45 buildExpressionParser operators simpleExpr
46 = foldl (makeParser) simpleExpr operators
49 = let (rassoc,lassoc,nassoc
50 ,prefix,postfix) = foldr splitOp ([],[],[],[],[]) ops
52 rassocOp = choice rassoc
53 lassocOp = choice lassoc
54 nassocOp = choice nassoc
55 prefixOp = choice prefix <?> ""
56 postfixOp = choice postfix <?> ""
58 ambigious assoc op= try $
59 do{ op; fail ("ambiguous use of a " ++ assoc
60 ++ " associative operator")
63 ambigiousRight = ambigious "right" rassocOp
64 ambigiousLeft = ambigious "left" lassocOp
65 ambigiousNon = ambigious "non" nassocOp
67 termP = do{ pre <- prefixP
70 ; return (post (pre x))
73 postfixP = postfixOp <|> return id
75 prefixP = prefixOp <|> return id
77 rassocP x = do{ f <- rassocOp
78 ; y <- do{ z <- termP; rassocP1 z }
85 rassocP1 x = rassocP x <|> return x
87 lassocP x = do{ f <- lassocOp
95 lassocP1 x = lassocP x <|> return x
97 nassocP x = do{ f <- nassocOp
107 ; rassocP x <|> lassocP x <|> nassocP x <|> return x
112 splitOp (Infix op assoc) (rassoc,lassoc,nassoc,prefix,postfix)
114 AssocNone -> (rassoc,lassoc,op:nassoc,prefix,postfix)
115 AssocLeft -> (rassoc,op:lassoc,nassoc,prefix,postfix)
116 AssocRight -> (op:rassoc,lassoc,nassoc,prefix,postfix)
118 splitOp (Prefix op) (rassoc,lassoc,nassoc,prefix,postfix)
119 = (rassoc,lassoc,nassoc,op:prefix,postfix)
121 splitOp (Postfix op) (rassoc,lassoc,nassoc,prefix,postfix)
122 = (rassoc,lassoc,nassoc,prefix,op:postfix)