Add automatic error collector to the parser
This commit is contained in:
parent
916d9897bd
commit
c497da5841
@ -141,7 +141,7 @@ field name parser = do
|
|||||||
where
|
where
|
||||||
sandbox firstOne tree@ParseTree {ptID, ptRange} = do
|
sandbox firstOne tree@ParseTree {ptID, ptRange} = do
|
||||||
st@Forest {pfGrove = grove, pfRange = rng} <- get
|
st@Forest {pfGrove = grove, pfRange = rng} <- get
|
||||||
let grove' = delete name grove
|
let (errs, grove') = delete name grove
|
||||||
put Forest
|
put Forest
|
||||||
{ pfID = ptID
|
{ pfID = ptID
|
||||||
, pfGrove = [(name, tree)]
|
, pfGrove = [(name, tree)]
|
||||||
@ -155,6 +155,8 @@ field name parser = do
|
|||||||
, pfRange = if firstOne then diffRange rng ptRange else rng
|
, pfRange = if firstOne then diffRange rng ptRange else rng
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_ errs (tell . pure . unexpected)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
-- | Variuos error reports.
|
-- | Variuos error reports.
|
||||||
@ -169,6 +171,10 @@ die msg = throwError =<< makeError msg
|
|||||||
die' msg rng = throwError =<< makeError' msg rng
|
die' msg rng = throwError =<< makeError' msg rng
|
||||||
complain msg rng = tell . pure =<< makeError' msg rng
|
complain msg rng = tell . pure =<< makeError' msg rng
|
||||||
|
|
||||||
|
unexpected :: ParseTree -> Error
|
||||||
|
unexpected ParseTree { ptSource, ptRange } =
|
||||||
|
Expected "unexpected" ptSource ptRange
|
||||||
|
|
||||||
-- | If a parser fails, return stub with error originating here.
|
-- | If a parser fails, return stub with error originating here.
|
||||||
stubbed :: Stubbed a => Text -> Parser a -> Parser a
|
stubbed :: Stubbed a => Text -> Parser a -> Parser a
|
||||||
stubbed msg parser = do
|
stubbed msg parser = do
|
||||||
@ -183,6 +189,8 @@ subtree msg parser = do
|
|||||||
then do
|
then do
|
||||||
save <- get
|
save <- get
|
||||||
put ptChildren
|
put ptChildren
|
||||||
|
rest <- gets pfGrove
|
||||||
|
collectErrors rest
|
||||||
parser <* put save
|
parser <* put save
|
||||||
else do
|
else do
|
||||||
die msg
|
die msg
|
||||||
@ -237,14 +245,15 @@ runParser (Parser parser) fin = do
|
|||||||
either (error . show) (return . fst) res
|
either (error . show) (return . fst) res
|
||||||
|
|
||||||
-- | Run parser on given file and pretty-print stuff.
|
-- | Run parser on given file and pretty-print stuff.
|
||||||
debugParser :: Parser a -> FilePath -> IO a
|
debugParser :: Show a => Parser a -> FilePath -> IO ()
|
||||||
debugParser parser fin = do
|
debugParser parser fin = do
|
||||||
(res, errs) <- runParser parser fin
|
(res, errs) <- runParser parser fin
|
||||||
putStrLn "Errors:"
|
|
||||||
for_ errs (print . nest 2 . pp)
|
|
||||||
putStrLn ""
|
|
||||||
putStrLn "Result:"
|
putStrLn "Result:"
|
||||||
return res
|
print res
|
||||||
|
unless (null errs) do
|
||||||
|
putStrLn ""
|
||||||
|
putStrLn "Errors:"
|
||||||
|
for_ errs (print . nest 2 . pp)
|
||||||
|
|
||||||
-- | Consume next tree if it has give name. Or die.
|
-- | Consume next tree if it has give name. Or die.
|
||||||
token :: Text -> Parser Text
|
token :: Text -> Parser Text
|
||||||
@ -280,12 +289,25 @@ getRange = snd <$> range (return ())
|
|||||||
--
|
--
|
||||||
-- Notice: this works differently from `Prelude.remove`!
|
-- Notice: this works differently from `Prelude.remove`!
|
||||||
--
|
--
|
||||||
delete :: Eq k => k -> [(k, v)] -> [(k, v)]
|
delete :: Text -> [(Text, ParseTree)] -> ([ParseTree], [(Text, ParseTree)])
|
||||||
delete _ [] = []
|
delete _ [] = ([], [])
|
||||||
delete k ((k', v) : rest) =
|
delete k ((k', v) : rest) =
|
||||||
if k == k'
|
if k == k'
|
||||||
then rest
|
then (addIfError v [], rest)
|
||||||
else delete k rest
|
else (addIfError v vs, remains)
|
||||||
|
where
|
||||||
|
(vs, remains) = delete k rest
|
||||||
|
|
||||||
|
addIfError v =
|
||||||
|
if ptName v == "ERROR"
|
||||||
|
then (:) v
|
||||||
|
else id
|
||||||
|
|
||||||
|
collectErrors :: [(Text, ParseTree)] -> Parser ()
|
||||||
|
collectErrors vs =
|
||||||
|
for_ vs \(_, v) -> do
|
||||||
|
when (ptName v == "ERROR") do
|
||||||
|
tell [unexpected v]
|
||||||
|
|
||||||
-- | Parser negation.
|
-- | Parser negation.
|
||||||
notFollowedBy :: Parser a -> Parser ()
|
notFollowedBy :: Parser a -> Parser ()
|
||||||
|
Loading…
Reference in New Issue
Block a user