ebnf-bff-0.1.0.0: src/Text/EBNF/Build/Parser/Except.hs
module Text.EBNF.Build.Parser.Except where
import Text.Parsec.Pos
import Text.EBNF.SyntaxTree
import Text.EBNF.Helper
import Data.List
{-
A number of exception structures for reporting
warnings or invalid structures in EBNF grammars
-}
data FailData = FailData {failtype :: String, description :: String, pos :: SourcePos}
instance Show FailData where
show fd = concat [(show $ pos fd), " ", (failtype fd), ":", (description fd)]
data Report = Clean
| Warning {warnings :: [FailData]}
| Failed {failures :: [FailData]}
instance Show Report where
show Clean = ""
show (Warning w) = ""
show (Failed f) = ""
concatReports :: [Report] -> Report
concatReports reps = foldl combineReports (Clean) reps
{-
Combining reports is a symmetric operation where Cleans
are overridden by warnings and failures, whereas warnings
are overridden only by failures. At the end the
-}
combineReports :: Report -> Report -> Report
combineReports Clean Clean = Clean
combineReports Clean a = a
combineReports a Clean = a
combineReports (Warning w) (Failed f) = Failed (sortBy (\a b -> compare (pos a) (pos b)) $ f ++ w)
combineReports (Failed f) (Warning w) = Failed (sortBy (\a b -> compare (pos a) (pos b)) $ f ++ w)
combineReports (Failed f) (Failed f') = Failed (sortBy (\a b -> compare (pos a) (pos b)) $ f ++ f')
combineReports (Warning w) (Warning w') = Warning (sortBy (\a b -> compare (pos a) (pos b)) $ w ++ w')
{-|
Will analyse a syntax tree, returning reports to be combined
together
-}
generateReport :: SyntaxTree -> Report
generateReport st = concatReports $ map ($ st) reports
reports :: [(SyntaxTree -> Report)]
reports = [reportNeverTerminating]
{-|
A never terminating parser is one that can parse an infinite
amount of empty strings, such parsers can be achieved with
@{[identifer]}@ pattern rules, which can parse indefinitely
but never terminate.
-}
reportNeverTerminating :: SyntaxTree -> Report
reportNeverTerminating st =
let rep = (\_ -> Clean) st
reps = map reportNeverTerminating . children $ st
in concatReports $ rep:reps