aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom@tomsmeding.com>2024-02-19 23:32:09 +0100
committerTom Smeding <tom@tomsmeding.com>2024-02-19 23:32:09 +0100
commitb0c81ee7def783037b514af9fdeab06f7e3bdb13 (patch)
tree78e11274cc3b4779fe06b5f30c3d8426dc36202f
parent91b62660cd522ce59ba1294eb2e6582e92f0a264 (diff)
Show source line in parse error
-rw-r--r--examples/test1.hs4
-rw-r--r--src/Parser.hs31
2 files changed, 22 insertions, 13 deletions
diff --git a/examples/test1.hs b/examples/test1.hs
index 2a3a834..ea09465 100644
--- a/examples/test1.hs
+++ b/examples/test1.hs
@@ -12,7 +12,7 @@ g y ding = ding f (y - 2) + 7
reverse :: [a] -> [a]
reverse l =
let go [] acc = acc
- go (x:xs) acc go xs (x:acc) 7 ->
- in go l []
+ go (x:xs) acc = go xs (x:acc)
+ in (go l []
kaas = 42
diff --git a/src/Parser.hs b/src/Parser.hs
index 1746eca..76cc10e 100644
--- a/src/Parser.hs
+++ b/src/Parser.hs
@@ -30,6 +30,7 @@ import Control.Monad.State.Lazy
import Data.Char
import Data.Either (partitionEithers)
import Data.Foldable
+import Data.List (intercalate)
import Data.List.NonEmpty (NonEmpty(..))
import Data.These
@@ -58,6 +59,7 @@ data PS = PS
data Context = Context
{ ctxFile :: FilePath
+ , ctxLines :: [String] -- ^ The file contents, split up in lines
, ctxStack :: [String] -- ^ Stack of syntax scopes, for error reporting
}
deriving (Show)
@@ -156,17 +158,23 @@ data ErrMsg = ErrMsg
{ errFile :: FilePath
, errStk :: [String]
, errPos :: Pos
- , errMsg :: String }
+ , errMsg :: String
+ , errSourceLine :: String }
deriving (Show)
printErrMsg :: ErrMsg -> String
-printErrMsg (ErrMsg fp stk (Pos y x) s) =
- unlines (map (\descr -> "In " ++ descr ++ ":") (reverse stk)) ++
- fp ++ ":" ++ show (y + 1) ++ ":" ++ show (x + 1) ++ ": " ++ s
+printErrMsg (ErrMsg fp stk (Pos y x) s srcline) =
+ let linenum = show (y + 1)
+ in intercalate "\n" $
+ map (\descr -> "In " ++ descr ++ ":") (reverse stk)
+ ++ [fp ++ ":" ++ show (y + 1) ++ ":" ++ show (x + 1) ++ ": " ++ s
+ ,map (\_ -> ' ') linenum ++ " |"
+ ,linenum ++ " | " ++ srcline
+ ,map (\_ -> ' ') linenum ++ " | " ++ replicate x ' ' ++ "^"]
parse :: FilePath -> String -> These [ErrMsg] (Program ())
parse fp source =
- runParser pProgram (Context fp []) (PS (Pos 0 0) (Pos 0 0) source)
+ runParser pProgram (Context fp (lines source) []) (PS (Pos 0 0) (Pos 0 0) source)
(\_ errs res -> case errs of
[] -> That res
_ -> These errs res)
@@ -551,10 +559,11 @@ pEVarOrCon0 =
pEParens0 :: FParser (Expr ())
pEParens0 = do
char '('
- e <- pExpr
- inlineWhite
- char ')'
- return e
+ noFail $ do
+ e <- pExpr <|>> (raise Error "Expected expression" >> return (ETup () []))
+ inlineWhite
+ char ')' <|>> raise Error "Expected closing ')'"
+ return e
data Associativity = AssocLeft | AssocRight | AssocNone
deriving (Show, Eq)
@@ -813,8 +822,8 @@ raise fat msg = gets psCur >>= \pos -> raiseAt pos fat msg
-- | Raise an error with the given fatality and description.
raiseAt :: (KnownFallible fail, FatalCtx fatal a) => Pos -> Fatality fatal -> String -> Parser fail a
raiseAt pos fat msg = do
- Context { ctxFile = fp , ctxStack = stk } <- ask
- let err = ErrMsg fp stk pos msg
+ Context { ctxFile = fp , ctxStack = stk, ctxLines = srcLines } <- ask
+ let err = ErrMsg fp stk pos msg (srcLines !! posLine pos)
case fat of
Error -> dictate (pure err)
Fatal -> confess (pure err)