packages feed

alms-0.4.9: src/Prec.hs

-- | Operator precdences
--
-- We use operator precedences from Ocaml.  The precence and
-- associativity of an operator is determined by its first character.
module Prec (
  Prec, precOp, fixities,
  -- * Precedences for reserved operators needed by the parser
  precMin, precStart, precMax,
  precCast, precCom, precDot, precSemi, precEq, precCaret, precArr,
  precPlus, precStar, precAt, precApp, precBang, precTApp
) where

-- | Precedence and associativity, e.g. @Right 4@ is right-associative
--   at level 4.  Higher precedences bind tighter, with application
--   at precedence 9.
type Prec = Either Int Int

precOp :: String -> Prec
precOp ('*':'*':_)    = Right precAt
precOp ('-':'>':_)    = Right precArr
precOp ('-':'o':_)    = Right precArr
precOp "-[]>"         = Right precArr
precOp (';':_)        = Right precSemi
precOp "!="           = Left precEq
precOp (c:_)
  | c `elem` "=<>|&$" = Left precEq
  | c `elem` "*/%"    = Left precStar
  | c `elem` "+-"     = Left precPlus
  | c `elem` "^"      = Right precCaret
  | c `elem` "@"      = Right precAt
  | c `elem` "!~?"    = Right precBang
precOp _              = Left precApp

precMin, precStart, precMax,
  precCast, precCom, precDot, precSemi, precEq, precCaret, precArr,
  precPlus, precStar, precAt, precApp, precBang, precTApp :: Int
precMin   = -2
precCast  = -2 -- :>
precCom   = -1 -- ,
precStart =  0
precDot   =  1 -- in, else, as, of, .
precArr   =  2 -- ->
precEq    =  3 -- != = < > | & $
precCaret =  4 -- ^ (infixr)
precPlus  =  5 -- - +
precStar  =  6 -- % / *
precSemi  =  7 -- ;  (types only)
precAt    =  8 -- @ ** (infixr)
precApp   =  9 -- f x
precBang  = 10 -- ! ~ ? (prefix)
precTApp  = 11 -- f[t]
precMax   = 11

-- To find out the fixity of a precedence level
fixities :: Int -> Maybe Prec
fixities n
  | n == precArr  = Just $ Right precArr
  | n == precEq   = Just $ Left precEq
  | n == precCaret= Just $ Right precCaret
  | n == precPlus = Just $ Left precPlus
  | n == precStar = Just $ Left precStar
  | n == precSemi = Just $ Right precSemi
  | n == precAt   = Just $ Right precAt
  | n == precBang = Just $ Right precBang
  | otherwise     = Nothing