module RhsCheck(checkRhs,checkBlock,checkTy) where
import Language.Haskell.Exts (parseExpWithMode, parseModuleWithMode, parseTypeWithMode, srcLine, srcColumn, srcFilename, baseFixities, glasgowExts, ParseMode (..), defaultParseMode, ParseResult (..), Extension (..))
import ErrorMessages
import Expression
import HsToken
import UU.Scanner.Position
checkRhs,checkBlock,checkTy :: Expression -> Errors
checkRhs = check parseExpWithMode
checkBlock = check parseModuleWithMode
checkTy = check parseTypeWithMode
check :: (ParseMode -> String -> ParseResult a) -> Expression -> Errors
check p (Expression pos tks) = case res of
ParseOk _ -> []
ParseFailed loc msg -> let pos' = Pos (srcLine loc + line pos 1) (srcColumn loc) (srcFilename loc)
in [HsParseError pos' msg]
where
pos0 = Pos (line pos) 1 (file pos)
str = toString pos0 tks
res = p mode str
bf = case baseFixities of
[] -> Nothing
xs -> Just xs
mode = defaultParseMode { parseFilename = file pos, ignoreLanguagePragmas = False, extensions = exts
, ignoreLinePragmas = False, fixities = bf }
exts :: [Extension]
exts = glasgowExts
toString :: Pos -> HsTokens -> String
toString _ [] = ""
toString cPos (tk:tks) = move ++ current ++ next
where
tkPos = getPos tk
move = addSpacing (line tkPos line cPos) (column cPos) (column tkPos)
current = fmt tk
nPos = upd tkPos current
next = toString nPos tks
getPos :: HsToken -> Pos
getPos (AGLocal _ pos _) = pos
getPos (AGField _ _ pos _) = pos
getPos (HsToken _ pos) = pos
getPos (CharToken _ pos) = pos
getPos (StrToken _ pos) = pos
getPos (Err _ pos) = pos
fmt :: HsToken -> String
fmt (AGLocal var _ _) = "_" ++ show var
fmt (AGField field attr _ _) = "_" ++ show field ++ "_" ++ show attr
fmt (HsToken val _) = val
fmt (CharToken val _) = show val
fmt (StrToken val _) = show val
fmt (Err val _) = val
upd :: Pos -> String -> Pos
upd p s = foldl adv p s
addSpacing :: Int -> Int -> Int -> String
addSpacing l c1 c2 = replicate l '\n' ++ replicate c ' '
where
c | l == 0 = c2 c1
| otherwise = c2 1