module Language.Go.Parser.Operators (
goOpExpr,
goUnaryOp
) where
import Text.Parsec.Expr
import Text.Parsec.Prim (try, token)
import Text.Parsec.Combinator (anyToken)
import Language.Go.Parser.Tokens (GoParser,GoToken(..),GoTokenPos(..))
import Language.Go.Syntax.AST
goOpExpr :: GoParser GoExpr -> GoParser GoExpr
goOpExpr p = buildExpressionParser goOpTable p
goOpTable =
[ [ Infix (goBinaryOp mul_op) AssocLeft ]
, [ Infix (goBinaryOp add_op) AssocLeft ]
, [ Infix (goBinaryOp rel_op) AssocLeft ]
, [ Infix (goBinaryOp and_op) AssocLeft ]
, [ Infix (goBinaryOp or_op) AssocLeft ]
]
goUnaryOp :: GoParser GoOp
goUnaryOp = do
GoTokenPos _ tok <- anyToken
case tok of
GoTokPlus -> return $ GoOp "+"
GoTokMinus -> return $ GoOp "-"
GoTokExclaim -> return $ GoOp "!"
GoTokXOR -> return $ GoOp "^"
GoTokAsterisk-> return $ GoOp "*"
GoTokAND -> return $ GoOp "&"
GoTokArrow -> return $ GoOp "<-"
_ -> fail "not a unary operator"
goBinaryOp :: (GoToken -> Maybe String) -> GoParser (GoExpr -> GoExpr -> GoExpr)
goBinaryOp want = try $ do
let s (GoTokenPos _ t) = show t
pos (GoTokenPos pos _) = pos
match (GoTokenPos _ t) = want t
op <- token s pos match
return (Go2Op $ GoOp op)
mul_op :: GoToken -> Maybe String
mul_op op = case op of
GoTokAsterisk -> Just "*"
GoTokSolidus -> Just "/"
GoTokPercent -> Just "%"
GoTokSHL -> Just "<<"
GoTokSHR -> Just ">>"
GoTokAND -> Just "&"
GoTokBUT -> Just "&^"
_ -> Nothing
add_op :: GoToken -> Maybe String
add_op op = case op of
GoTokPlus -> Just "+"
GoTokMinus -> Just "-"
GoTokIOR -> Just "|"
GoTokXOR -> Just "^"
_ -> Nothing
rel_op :: GoToken -> Maybe String
rel_op op = case op of
GoTokEQ -> Just "=="
GoTokNE -> Just "!="
GoTokLT -> Just "<"
GoTokLE -> Just "<="
GoTokGT -> Just ">"
GoTokGE -> Just ">="
_ -> Nothing
or_op op = if op == GoTokLOR then Just "||" else Nothing
and_op op = if op == GoTokLAND then Just "&&" else Nothing