buildExpressionParser only deals with unary and binary operators. Can it handle ternary operators like ?:
? There are some discussions here and here, but none is conclusive.
One of the great benefits of monadic parsers is that they compose really well.
This means that you don't have to try to trick a single buildExpressionParser
into building the exact parser you want. You can simply use it to build a parser, and then use that parser like any other for anything, including another buildExpressionParser
.
In your case, you can:
buildExpressionParser
to create a parser for expressions with higher precedence than ?:
?:
using the abovebuildExpressionParser
to create a parser for expressions with lower precedence than ?:
using the aboveHere's a complete example:
import Control.Monad.Identity
import Text.Parsec
import Text.Parsec.Expr
data Ex = Var String | Mul Ex Ex | Add Ex Ex | Assign Ex Ex | Trinary Ex Ex Ex
deriving (Show)
var = Var <$> many1 letter
topOps = [ [binary "*" Mul], [binary "+" Add] ]
topParser = buildExpressionParser topOps var
trinaryExpr = do
expr <- topParser
trinary expr <|> return expr
where
trinary expr = do
string "?"
thenV <- trinaryExpr
string ":"
elseV <- trinaryExpr
return $ Trinary expr thenV elseV
bottomOps = [ [ binary "=" Assign ] ]
bottomParser = buildExpressionParser bottomOps trinaryExpr
binary :: String -> (Ex -> Ex -> Ex) -> Operator String () Identity Ex
binary s t = Infix (string s >> return t) AssocLeft
testParse s = runParser bottomParser () "" s
main = print $ testParse "a=b+c*d?e+f:g*h"
The output (manually formatted) is:
Right
(Assign
(Var "a")
(Trinary
(Add (Var "b")
(Mul (Var "c") (Var "d")))
(Add (Var "e") (Var "f"))
(Mul (Var "g") (Var "h"))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With